1 /* 2 * Based on intlist.c by: 3 * (c) 2009 Arnaldo Carvalho de Melo <acme (at) redhat.com> 4 * 5 * Licensed under the GPLv2. 6 */ 7 8 #include <errno.h> 9 #include <stdlib.h> 10 #include <linux/compiler.h> 11 12 #include "intlist.h" 13 14 static struct rb_node *intlist__node_new(struct rblist *rblist __maybe_unused, 15 const void *entry) 16 { 17 int i = (int)((long)entry); 18 struct rb_node *rc = NULL; 19 struct int_node *node = malloc(sizeof(*node)); 20 21 if (node != NULL) { 22 node->i = i; 23 rc = &node->rb_node; 24 } 25 26 return rc; 27 } 28 29 static void int_node__delete(struct int_node *ilist) 30 { 31 free(ilist); 32 } 33 34 static void intlist__node_delete(struct rblist *rblist __maybe_unused, 35 struct rb_node *rb_node) 36 { 37 struct int_node *node = container_of(rb_node, struct int_node, rb_node); 38 39 int_node__delete(node); 40 } 41 42 static int intlist__node_cmp(struct rb_node *rb_node, const void *entry) 43 { 44 int i = (int)((long)entry); 45 struct int_node *node = container_of(rb_node, struct int_node, rb_node); 46 47 return node->i - i; 48 } 49 50 int intlist__add(struct intlist *ilist, int i) 51 { 52 return rblist__add_node(&ilist->rblist, (void *)((long)i)); 53 } 54 55 void intlist__remove(struct intlist *ilist, struct int_node *node) 56 { 57 rblist__remove_node(&ilist->rblist, &node->rb_node); 58 } 59 60 struct int_node *intlist__find(struct intlist *ilist, int i) 61 { 62 struct int_node *node; 63 struct rb_node *rb_node; 64 65 if (ilist == NULL) 66 return NULL; 67 68 node = NULL; 69 rb_node = rblist__find(&ilist->rblist, (void *)((long)i)); 70 if (rb_node) 71 node = container_of(rb_node, struct int_node, rb_node); 72 73 return node; 74 } 75 76 static int intlist__parse_list(struct intlist *ilist, const char *s) 77 { 78 char *sep; 79 int err; 80 81 do { 82 long value = strtol(s, &sep, 10); 83 err = -EINVAL; 84 if (*sep != ',' && *sep != '\0') 85 break; 86 err = intlist__add(ilist, value); 87 if (err) 88 break; 89 s = sep + 1; 90 } while (*sep != '\0'); 91 92 return err; 93 } 94 95 struct intlist *intlist__new(const char *slist) 96 { 97 struct intlist *ilist = malloc(sizeof(*ilist)); 98 99 if (ilist != NULL) { 100 rblist__init(&ilist->rblist); 101 ilist->rblist.node_cmp = intlist__node_cmp; 102 ilist->rblist.node_new = intlist__node_new; 103 ilist->rblist.node_delete = intlist__node_delete; 104 105 if (slist && intlist__parse_list(ilist, slist)) 106 goto out_delete; 107 } 108 109 return ilist; 110 out_delete: 111 intlist__delete(ilist); 112 return NULL; 113 } 114 115 void intlist__delete(struct intlist *ilist) 116 { 117 if (ilist != NULL) 118 rblist__delete(&ilist->rblist); 119 } 120 121 struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx) 122 { 123 struct int_node *node = NULL; 124 struct rb_node *rb_node; 125 126 rb_node = rblist__entry(&ilist->rblist, idx); 127 if (rb_node) 128 node = container_of(rb_node, struct int_node, rb_node); 129 130 return node; 131 } 132