1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Based on intlist.c by: 4 * (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com> 5 */ 6 7 #include <errno.h> 8 #include <stdlib.h> 9 #include <linux/compiler.h> 10 11 #include "intlist.h" 12 13 static struct rb_node *intlist__node_new(struct rblist *rblist __maybe_unused, 14 const void *entry) 15 { 16 unsigned long i = (unsigned long)entry; 17 struct rb_node *rc = NULL; 18 struct int_node *node = malloc(sizeof(*node)); 19 20 if (node != NULL) { 21 node->i = i; 22 node->priv = NULL; 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 unsigned long i = (unsigned long)entry; 45 struct int_node *node = container_of(rb_node, struct int_node, rb_node); 46 47 if (node->i > i) 48 return 1; 49 else if (node->i < i) 50 return -1; 51 52 return 0; 53 } 54 55 int intlist__add(struct intlist *ilist, unsigned long i) 56 { 57 return rblist__add_node(&ilist->rblist, (void *)i); 58 } 59 60 void intlist__remove(struct intlist *ilist, struct int_node *node) 61 { 62 rblist__remove_node(&ilist->rblist, &node->rb_node); 63 } 64 65 static struct int_node *__intlist__findnew(struct intlist *ilist, 66 unsigned long i, bool create) 67 { 68 struct int_node *node = NULL; 69 struct rb_node *rb_node; 70 71 if (ilist == NULL) 72 return NULL; 73 74 if (create) 75 rb_node = rblist__findnew(&ilist->rblist, (void *)i); 76 else 77 rb_node = rblist__find(&ilist->rblist, (void *)i); 78 79 if (rb_node) 80 node = container_of(rb_node, struct int_node, rb_node); 81 82 return node; 83 } 84 85 struct int_node *intlist__find(struct intlist *ilist, unsigned long i) 86 { 87 return __intlist__findnew(ilist, i, false); 88 } 89 90 struct int_node *intlist__findnew(struct intlist *ilist, unsigned long i) 91 { 92 return __intlist__findnew(ilist, i, true); 93 } 94 95 static int intlist__parse_list(struct intlist *ilist, const char *s) 96 { 97 char *sep; 98 int err; 99 100 do { 101 unsigned long value = strtol(s, &sep, 10); 102 err = -EINVAL; 103 if (*sep != ',' && *sep != '\0') 104 break; 105 err = intlist__add(ilist, value); 106 if (err) 107 break; 108 s = sep + 1; 109 } while (*sep != '\0'); 110 111 return err; 112 } 113 114 struct intlist *intlist__new(const char *slist) 115 { 116 struct intlist *ilist = malloc(sizeof(*ilist)); 117 118 if (ilist != NULL) { 119 rblist__init(&ilist->rblist); 120 ilist->rblist.node_cmp = intlist__node_cmp; 121 ilist->rblist.node_new = intlist__node_new; 122 ilist->rblist.node_delete = intlist__node_delete; 123 124 if (slist && intlist__parse_list(ilist, slist)) 125 goto out_delete; 126 } 127 128 return ilist; 129 out_delete: 130 intlist__delete(ilist); 131 return NULL; 132 } 133 134 void intlist__delete(struct intlist *ilist) 135 { 136 if (ilist != NULL) 137 rblist__delete(&ilist->rblist); 138 } 139 140 struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx) 141 { 142 struct int_node *node = NULL; 143 struct rb_node *rb_node; 144 145 rb_node = rblist__entry(&ilist->rblist, idx); 146 if (rb_node) 147 node = container_of(rb_node, struct int_node, rb_node); 148 149 return node; 150 } 151