1 /* 2 * Based on intlist.c by: 3 * (c) 2009 Arnaldo Carvalho de Melo <acme@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 node->priv = NULL; 24 rc = &node->rb_node; 25 } 26 27 return rc; 28 } 29 30 static void int_node__delete(struct int_node *ilist) 31 { 32 free(ilist); 33 } 34 35 static void intlist__node_delete(struct rblist *rblist __maybe_unused, 36 struct rb_node *rb_node) 37 { 38 struct int_node *node = container_of(rb_node, struct int_node, rb_node); 39 40 int_node__delete(node); 41 } 42 43 static int intlist__node_cmp(struct rb_node *rb_node, const void *entry) 44 { 45 int i = (int)((long)entry); 46 struct int_node *node = container_of(rb_node, struct int_node, rb_node); 47 48 return node->i - i; 49 } 50 51 int intlist__add(struct intlist *ilist, int i) 52 { 53 return rblist__add_node(&ilist->rblist, (void *)((long)i)); 54 } 55 56 void intlist__remove(struct intlist *ilist, struct int_node *node) 57 { 58 rblist__remove_node(&ilist->rblist, &node->rb_node); 59 } 60 61 static struct int_node *__intlist__findnew(struct intlist *ilist, 62 int i, bool create) 63 { 64 struct int_node *node = NULL; 65 struct rb_node *rb_node; 66 67 if (ilist == NULL) 68 return NULL; 69 70 if (create) 71 rb_node = rblist__findnew(&ilist->rblist, (void *)((long)i)); 72 else 73 rb_node = rblist__find(&ilist->rblist, (void *)((long)i)); 74 75 if (rb_node) 76 node = container_of(rb_node, struct int_node, rb_node); 77 78 return node; 79 } 80 81 struct int_node *intlist__find(struct intlist *ilist, int i) 82 { 83 return __intlist__findnew(ilist, i, false); 84 } 85 86 struct int_node *intlist__findnew(struct intlist *ilist, int i) 87 { 88 return __intlist__findnew(ilist, i, true); 89 } 90 91 static int intlist__parse_list(struct intlist *ilist, const char *s) 92 { 93 char *sep; 94 int err; 95 96 do { 97 long value = strtol(s, &sep, 10); 98 err = -EINVAL; 99 if (*sep != ',' && *sep != '\0') 100 break; 101 err = intlist__add(ilist, value); 102 if (err) 103 break; 104 s = sep + 1; 105 } while (*sep != '\0'); 106 107 return err; 108 } 109 110 struct intlist *intlist__new(const char *slist) 111 { 112 struct intlist *ilist = malloc(sizeof(*ilist)); 113 114 if (ilist != NULL) { 115 rblist__init(&ilist->rblist); 116 ilist->rblist.node_cmp = intlist__node_cmp; 117 ilist->rblist.node_new = intlist__node_new; 118 ilist->rblist.node_delete = intlist__node_delete; 119 120 if (slist && intlist__parse_list(ilist, slist)) 121 goto out_delete; 122 } 123 124 return ilist; 125 out_delete: 126 intlist__delete(ilist); 127 return NULL; 128 } 129 130 void intlist__delete(struct intlist *ilist) 131 { 132 if (ilist != NULL) 133 rblist__delete(&ilist->rblist); 134 } 135 136 struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx) 137 { 138 struct int_node *node = NULL; 139 struct rb_node *rb_node; 140 141 rb_node = rblist__entry(&ilist->rblist, idx); 142 if (rb_node) 143 node = container_of(rb_node, struct int_node, rb_node); 144 145 return node; 146 } 147