timer: handle time going backwards.
[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         TCON_WRAP(struct objset_h, type canary) objset_
40
41 #define objset_raw(set)                         \
42         tcon_unwrap(&(set)->objset_)
43
44 /**
45  * objset_init - initialize an empty objset
46  * @set: the typed objset to initialize.
47  *
48  * Example:
49  *      struct objset_int set;
50  *
51  *      objset_init(&set);
52  */
53 #define objset_init(set) objset_h_init(objset_raw(set))
54
55 /**
56  * objset_empty - is this set empty?
57  * @set: the typed objset to check.
58  *
59  * Example:
60  *      if (!objset_empty(&set))
61  *              abort();
62  */
63 #define objset_empty(set) objset_empty_(objset_raw(set))
64
65 static inline bool objset_empty_(const struct objset_h *set)
66 {
67         struct objset_h_iter i;
68         return objset_h_first(set, &i) == NULL;
69 }
70
71 /**
72  * objset_add - place a member into the set.
73  * @set: the typed objset to add to.
74  * @value: the (non-NULL) object to place in the set.
75  *
76  * This returns false if we run out of memory (errno = ENOMEM), or
77  * (more normally) if that pointer already appears in the set (EEXIST).
78  *
79  * Example:
80  *      int *val;
81  *
82  *      val = malloc(sizeof *val);
83  *      *val = 17;
84  *      if (!objset_add(&set, val))
85  *              printf("Impossible: value was already in the set?\n");
86  */
87 #define objset_add(set, value)                                          \
88         objset_h_add(tcon_unwrap(tcon_check(&(set)->objset_, canary, (value))), (void *)(value))
89
90 /**
91  * objset_get - get a value from a set
92  * @set: the typed objset to search.
93  * @value: the value to search for.
94  *
95  * Returns the value, or NULL if it isn't in the set (and sets errno = ENOENT).
96  *
97  * Example:
98  *      if (objset_get(&set, val));
99  *              printf("hello => %i\n", *val);
100  */
101 #define objset_get(set, member)                                 \
102         tcon_cast(&(set)->objset_, canary,                      \
103                   objset_h_get(objset_raw(set), (member)))
104
105 /**
106  * objset_del - remove a member from the set.
107  * @set: the typed objset to delete from.
108  * @value: the value (non-NULL) to remove from the set
109  *
110  * This returns false NULL if @value was not in the set (and sets
111  * errno = ENOENT).
112  *
113  * Example:
114  *      if (!objset_del(&set, val))
115  *              printf("val was not in the set?\n");
116  */
117 #define objset_del(set, value)                                          \
118         objset_h_del(tcon_unwrap(tcon_check(&(set)->objset_, canary, value)), \
119                      (const void *)value)
120
121 /**
122  * objset_clear - remove every member from the set.
123  * @set: the typed objset to clear.
124  *
125  * The set will be empty after this.
126  *
127  * Example:
128  *      objset_clear(&set);
129  */
130 #define objset_clear(set) objset_h_clear(objset_raw(set))
131
132 /**
133  * objset_iter - iterator reference.
134  *
135  * This is valid for a particular set as long as the contents remain unchaged,
136  * otherwise the effect is undefined.
137  */
138 struct objset_iter {
139         struct objset_h_iter iter;
140 };
141
142 /**
143  * objset_first - get an element in the set
144  * @set: the typed objset to iterate through.
145  * @i: a struct objset_iter to use as an iterator.
146  *
147  * Example:
148  *      struct objset_iter i;
149  *      int *v;
150  *
151  *      v = objset_first(&set, &i);
152  *      if (v)
153  *              printf("One value is %i\n", *v);
154  */
155 #define objset_first(set, i)                                    \
156         tcon_cast(&(set)->objset_, canary,                      \
157                   objset_h_first(objset_raw(set), &(i)->iter))
158
159 /**
160  * objset_next - get the another element in the set
161  * @set: the typed objset to iterate through.
162  * @i: a struct objset_iter to use as an iterator.
163  *
164  * @i must have been set by a successful objset_first() or
165  * objset_next() call.
166  *
167  * Example:
168  *      while (v) {
169  *              v = objset_next(&set, &i);
170  *              if (v)
171  *                      printf("Another value is %i\n", *v);
172  *      }
173  */
174 #define objset_next(set, i)                                     \
175         tcon_cast(&(set)->objset_, canary,                      \
176                   objset_h_next(objset_raw(set), &(i)->iter))
177
178 #endif /* CCAN_OBJSET_H */