]> git.ozlabs.org Git - ccan/blob - ccan/objset/objset.h
objset: new module.
[ccan] / ccan / objset / objset.h
1 /* Licensed under LGPLv2+ - see LICENSE file for details */
2 #ifndef CCAN_OBJSET_H
3 #define CCAN_OBJSET_H
4 #include "config.h"
5 #include <ccan/htable/htable_type.h>
6 #include <ccan/hash/hash.h>
7 #include <ccan/tcon/tcon.h>
8 #include <stdlib.h>
9 #include <stdbool.h>
10
11 static inline const void *objset_key_(const void *elem)
12 {
13         return elem;
14 }
15 static inline size_t objset_hashfn_(const void *elem)
16 {
17         return hash_pointer(elem, 0);
18 }
19 static inline bool objset_eqfn_(const void *e1, const void *e2)
20 {
21         return e1 == e2;
22 }
23 HTABLE_DEFINE_TYPE(void, objset_key_, objset_hashfn_, objset_eqfn_, objset_h);
24
25 /**
26  * OBJSET_MEMBERS - declare members for a type-specific unordered objset.
27  * @type: type for this set's values, or void * for any pointer.
28  *
29  * You use this to create your own typed objset for a particular type.
30  * You can use an integer type, *but* remember you can't use "0" as a
31  * value!
32  *
33  * Example:
34  *      struct objset_int {
35  *              OBJSET_MEMBERS(int *);
36  *      };
37  */
38 #define OBJSET_MEMBERS(type)                    \
39         struct objset_h raw;                    \
40         TCON(type canary)
41
42 /**
43  * objset_init - initialize an empty objset
44  * @set: the typed objset to initialize.
45  *
46  * Example:
47  *      struct objset_int set;
48  *
49  *      objset_init(&set);
50  */
51 #define objset_init(set) objset_h_init(&(set)->raw)
52
53 /**
54  * objset_empty - is this set empty?
55  * @set: the typed objset to check.
56  *
57  * Example:
58  *      if (!objset_empty(&set))
59  *              abort();
60  */
61 #define objset_empty(set) objset_empty_(&(set)->raw)
62
63 static inline bool objset_empty_(const struct objset_h *set)
64 {
65         struct objset_h_iter i;
66         return objset_h_first(set, &i) == NULL;
67 }
68
69 /**
70  * objset_add - place a member into the set.
71  * @set: the typed objset to add to.
72  * @value: the (non-NULL) object to place in the set.
73  *
74  * This returns false if we run out of memory (errno = ENOMEM), or
75  * (more normally) if that pointer already appears in the set (EEXIST).
76  *
77  * Example:
78  *      int *val;
79  *
80  *      val = malloc(sizeof *val);
81  *      *val = 17;
82  *      if (!objset_add(&set, val))
83  *              printf("Impossible: value was already in the set?\n");
84  */
85 #define objset_add(set, value)                                          \
86         objset_h_add(&tcon_check((set), canary, (value))->raw, (void *)(value))
87
88 /**
89  * objset_get - get a value from a set
90  * @set: the typed objset to search.
91  * @value: the value to search for.
92  *
93  * Returns the value, or NULL if it isn't in the set (and sets errno = ENOENT).
94  *
95  * Example:
96  *      if (objset_get(&set, val));
97  *              printf("hello => %i\n", *val);
98  */
99 #define objset_get(set, member) \
100         tcon_cast((set), canary, objset_h_get(&(set)->raw, (member)))
101
102 /**
103  * objset_del - remove a member from the set.
104  * @set: the typed objset to delete from.
105  * @value: the value (non-NULL) to remove from the set
106  *
107  * This returns false NULL if @value was not in the set (and sets
108  * errno = ENOENT).
109  *
110  * Example:
111  *      if (!objset_del(&set, val))
112  *              printf("val was not in the set?\n");
113  */
114 #define objset_del(set, value)                                          \
115         objset_h_del(&tcon_check((set), canary, value)->raw,            \
116                      (const void *)value)
117
118 /**
119  * objset_clear - remove every member from the set.
120  * @set: the typed objset to clear.
121  *
122  * The set will be empty after this.
123  *
124  * Example:
125  *      objset_clear(&set);
126  */
127 #define objset_clear(set) objset_h_clear(&(set)->raw)
128
129 /**
130  * objset_iter - iterator reference.
131  *
132  * This is valid for a particular set as long as the contents remain unchaged,
133  * otherwise the effect is undefined.
134  */
135 struct objset_iter {
136         struct objset_h_iter iter;
137 };
138
139 /**
140  * objset_first - get an element in the set
141  * @set: the typed objset to iterate through.
142  * @i: a struct objset_iter to use as an iterator.
143  *
144  * Example:
145  *      struct objset_iter i;
146  *      int *v;
147  *
148  *      v = objset_first(&set, &i);
149  *      if (v)
150  *              printf("One value is %i\n", *v);
151  */
152 #define objset_first(set, i) \
153         tcon_cast((set), canary, objset_h_first(&(set)->raw, &(i)->iter))
154
155 /**
156  * objset_next - get the another element in the set
157  * @set: the typed objset to iterate through.
158  * @i: a struct objset_iter to use as an iterator.
159  *
160  * @i must have been set by a successful objset_first() or
161  * objset_next() call.
162  *
163  * Example:
164  *      while (v) {
165  *              v = objset_next(&set, &i);
166  *              if (v)
167  *                      printf("Another value is %i\n", *v);
168  *      }
169  */
170 #define objset_next(set, i) \
171         tcon_cast((set), canary, objset_h_next(&(set)->raw, &(i)->iter))
172
173 #endif /* CCAN_OBJSET_H */