intlist.c (3144B)
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 13static 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 29static void int_node__delete(struct int_node *ilist) 30{ 31 free(ilist); 32} 33 34static 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 42static 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 55int intlist__add(struct intlist *ilist, unsigned long i) 56{ 57 return rblist__add_node(&ilist->rblist, (void *)i); 58} 59 60void intlist__remove(struct intlist *ilist, struct int_node *node) 61{ 62 rblist__remove_node(&ilist->rblist, &node->rb_node); 63} 64 65static 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 85struct int_node *intlist__find(struct intlist *ilist, unsigned long i) 86{ 87 return __intlist__findnew(ilist, i, false); 88} 89 90struct int_node *intlist__findnew(struct intlist *ilist, unsigned long i) 91{ 92 return __intlist__findnew(ilist, i, true); 93} 94 95static 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 114struct 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; 129out_delete: 130 intlist__delete(ilist); 131 return NULL; 132} 133 134void intlist__delete(struct intlist *ilist) 135{ 136 if (ilist != NULL) 137 rblist__delete(&ilist->rblist); 138} 139 140struct 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}