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 int i = (int)((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 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 static struct int_node *__intlist__findnew(struct intlist *ilist, 61 int i, bool create) 62 { 63 struct int_node *node = NULL; 64 struct rb_node *rb_node; 65 66 if (ilist == NULL) 67 return NULL; 68 69 if (create) 70 rb_node = rblist__findnew(&ilist->rblist, (void *)((long)i)); 71 else 72 rb_node = rblist__find(&ilist->rblist, (void *)((long)i)); 73 74 if (rb_node) 75 node = container_of(rb_node, struct int_node, rb_node); 76 77 return node; 78 } 79 80 struct int_node *intlist__find(struct intlist *ilist, int i) 81 { 82 return __intlist__findnew(ilist, i, false); 83 } 84 85 struct int_node *intlist__findnew(struct intlist *ilist, int i) 86 { 87 return __intlist__findnew(ilist, i, true); 88 } 89 90 static int intlist__parse_list(struct intlist *ilist, const char *s) 91 { 92 char *sep; 93 int err; 94 95 do { 96 long value = strtol(s, &sep, 10); 97 err = -EINVAL; 98 if (*sep != ',' && *sep != '\0') 99 break; 100 err = intlist__add(ilist, value); 101 if (err) 102 break; 103 s = sep + 1; 104 } while (*sep != '\0'); 105 106 return err; 107 } 108 109 struct intlist *intlist__new(const char *slist) 110 { 111 struct intlist *ilist = malloc(sizeof(*ilist)); 112 113 if (ilist != NULL) { 114 rblist__init(&ilist->rblist); 115 ilist->rblist.node_cmp = intlist__node_cmp; 116 ilist->rblist.node_new = intlist__node_new; 117 ilist->rblist.node_delete = intlist__node_delete; 118 119 if (slist && intlist__parse_list(ilist, slist)) 120 goto out_delete; 121 } 122 123 return ilist; 124 out_delete: 125 intlist__delete(ilist); 126 return NULL; 127 } 128 129 void intlist__delete(struct intlist *ilist) 130 { 131 if (ilist != NULL) 132 rblist__delete(&ilist->rblist); 133 } 134 135 struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx) 136 { 137 struct int_node *node = NULL; 138 struct rb_node *rb_node; 139 140 rb_node = rblist__entry(&ilist->rblist, idx); 141 if (rb_node) 142 node = container_of(rb_node, struct int_node, rb_node); 143 144 return node; 145 } 146