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(ilist: 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(rblist: &ilist->rblist, new_entry: (void *)i); |
58 | } |
59 | |
60 | void intlist__remove(struct intlist *ilist, struct int_node *node) |
61 | { |
62 | rblist__remove_node(rblist: &ilist->rblist, rb_node: &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(rblist: &ilist->rblist, entry: (void *)i); |
76 | else |
77 | rb_node = rblist__find(rblist: &ilist->rblist, entry: (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, create: false); |
88 | } |
89 | |
90 | struct int_node *intlist__findnew(struct intlist *ilist, unsigned long i) |
91 | { |
92 | return __intlist__findnew(ilist, i, create: 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, i: 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(rblist: &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, s: 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(rblist: &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(rblist: &ilist->rblist, idx); |
146 | if (rb_node) |
147 | node = container_of(rb_node, struct int_node, rb_node); |
148 | |
149 | return node; |
150 | } |
151 | |