5 #include <ccan/compiler/compiler.h>
12 * jmap_new - create a new, empty jmap.
18 * struct jmap *map = jmap_new();
20 * errx(1, "Failed to allocate jmap");
22 struct jmap *jmap_new(void);
25 * jmap_free - destroy a jmap.
26 * @map: the map returned from jmap_new.
31 void jmap_free(const struct jmap *map);
33 /* This is exposed in the header so we can inline. Treat it as private! */
45 const char *COLD_ATTRIBUTE jmap_error_(struct jmap *map);
47 /* Debugging checks. */
48 static inline void jmap_debug_add_access(const struct jmap *map,
49 size_t index, size_t *val,
53 if (!map->acc_value) {
54 ((struct jmap *)map)->acc_value = val;
55 ((struct jmap *)map)->acc_index = index;
56 ((struct jmap *)map)->funcname = funcname;
60 assert(++((struct jmap *)map)->num_accesses);
63 static inline void jmap_debug_del_access(struct jmap *map, size_t **val)
65 assert(--map->num_accesses >= 0);
67 if (map->acc_value == *val)
68 map->acc_value = NULL;
70 /* Set it to some invalid value. Not NULL, they might rely on that! */
71 assert((*val = (void *)jmap_new) != NULL);
74 static inline void jmap_debug_access(struct jmap *map)
77 if (map->num_accesses && map->acc_value)
79 "jmap: still got index %zu, val %zu (%p) from %s\n",
80 map->acc_index, *map->acc_value, map->acc_value,
83 assert(!map->num_accesses);
87 * jmap_error - test for an error in the a previous jmap_ operation.
88 * @map: the map to test.
90 * Under normal circumstances, return NULL to indicate no error has occurred.
91 * Otherwise, it will return a string containing the error. This string
92 * can only be freed by jmap_free() on the map.
94 * Other than out-of-memory, errors are caused by memory corruption or
98 * struct jmap *map = jmap_new();
102 * err(1, "allocating jmap");
103 * errstr = jmap_error(map);
105 * errx(1, "Woah, error on newly created map?! %s", errstr);
107 static inline const char *jmap_error(struct jmap *map)
109 if (JU_ERRNO(&map->err) <= JU_ERRNO_NFMAX)
111 return jmap_error_(map);
115 * jmap_add - add or replace a value for a given index in the map.
116 * @map: map from jmap_new
117 * @index: the index to map
118 * @value: the value to associate with the index
120 * Adds index into the map; replaces value if it's already there.
121 * Returns false on error (out of memory).
124 * if (!jmap_add(map, 0, 1))
125 * err(1, "jmap_add failed!");
127 static inline bool jmap_add(struct jmap *map, size_t index, size_t value)
130 jmap_debug_access(map);
131 val = (void *)JudyLIns(&map->judy, index, &map->err);
139 * jmap_set - change a value for an existing index in the map.
140 * @map: map from jmap_new
141 * @index: the index to map
142 * @value: the value to associate with the index
144 * This sets the value of an index if it already exists, and return true,
145 * otherwise returns false and does nothing.
148 * if (!jmap_set(map, 0, 2))
149 * err(1, "jmap_set: index 0 not found");
151 static inline bool jmap_set(const struct jmap *map, size_t index, size_t value)
154 val = (void *)JudyLGet(map->judy, index, (JError_t *)&map->err);
155 if (val && val != PJERR) {
163 * jmap_del - remove an index from the map.
164 * @map: map from jmap_new
165 * @index: the index to map
168 * if (!jmap_del(map, 0))
169 * err(1, "jmap_del failed!");
171 static inline bool jmap_del(struct jmap *map, size_t index)
173 jmap_debug_access(map);
174 return JudyLDel(&map->judy, index, &map->err) == 1;
178 * jmap_test - test if a given index is defined.
179 * @map: map from jmap_new
180 * @index: the index to find
183 * jmap_add(map, 0, 1);
184 * assert(jmap_test(map, 0));
186 static inline bool jmap_test(const struct jmap *map, size_t index)
188 return JudyLGet(map->judy, index, (JError_t *)&map->err) != NULL;
192 * jmap_get - get a value for a given index.
193 * @map: map from jmap_new
194 * @index: the index to find
195 * @invalid: the value to return if the index isn't found.
198 * jmap_add(map, 0, 1);
199 * assert(jmap_get(map, 0, -1) == 1);
204 static inline size_t jmap_get(const struct jmap *map, size_t index,
208 val = (void *)JudyLGet(map->judy, index, (JError_t *)&map->err);
209 if (!val || val == PJERR)
215 * jmap_popcount - get population of (some part of) the map.
216 * @map: map from jmap_new
217 * @start: first index to count
218 * @end_incl: last index to count (use -1 for end).
221 * assert(jmap_popcount(map, 0, 1000) <= jmap_popcount(map, 0, 2000));
223 static inline size_t jmap_popcount(const struct jmap *map,
224 size_t start, size_t end_incl)
226 return JudyLCount(map->judy, start, end_incl, (JError_t *)&map->err);
230 * jmap_nth - return the index of the nth value in the map.
231 * @map: map from jmap_new
232 * @n: which index we are interested in (0-based)
233 * @invalid: what to return if n >= map population
235 * This normally returns the nth index in the map, and often there is a
236 * convenient known-invalid value (ie. something which is never in the
237 * map). Otherwise you can use jmap_nthval().
242 * // We know 0 isn't in map.
243 * assert(!jmap_test(map, 0));
244 * for (i = 0; (index = jmap_nth(map, i, 0)) != 0; i++) {
245 * assert(jmap_popcount(map, 0, index) == i);
246 * printf("Index %zu = %zu\n", i, index);
252 static inline size_t jmap_nth(const struct jmap *map,
253 size_t n, size_t invalid)
256 if (!JudyLByCount(map->judy, n+1, &index, (JError_t *)&map->err))
262 * jmap_first - return the first index in the map.
263 * @map: map from jmap_new
264 * @invalid: return value if jmap is empty.
266 * This is equivalent to jmap_nth(map, 0, invalid).
269 * assert(!jmap_test(map, 0));
270 * printf("Map indices (increasing order):");
271 * for (i = jmap_first(map, 0); i; i = jmap_next(map, i, 0))
278 static inline size_t jmap_first(const struct jmap *map, size_t invalid)
281 if (!JudyLFirst(map->judy, &index, (JError_t *)&map->err))
284 assert(index != invalid);
289 * jmap_next - return the next index in the map.
290 * @map: map from jmap_new
291 * @prev: previous index
292 * @invalid: return value if there prev was final index in map.
294 * This is usually used to find an adjacent index after jmap_first.
298 static inline size_t jmap_next(const struct jmap *map, size_t prev,
301 if (!JudyLNext(map->judy, (Word_t *)&prev, (JError_t *)&map->err))
304 assert(prev != invalid);
309 * jmap_last - return the last index in the map.
310 * @map: map from jmap_new
311 * @invalid: return value if map is empty.
314 * assert(!jmap_test(map, 0));
315 * printf("Map indices (increasing order):");
316 * for (i = jmap_last(map, 0); i; i = jmap_prev(map, i, 0))
322 static inline size_t jmap_last(const struct jmap *map, size_t invalid)
325 if (!JudyLLast(map->judy, &index, (JError_t *)&map->err))
328 assert(index != invalid);
333 * jmap_prev - return the previous index in the map.
334 * @map: map from jmap_new
335 * @prev: previous index
336 * @invalid: return value if no previous indices are in the map.
338 * This is usually used to find an prior adjacent index after jmap_last.
342 static inline size_t jmap_prev(const struct jmap *map, size_t prev,
345 if (!JudyLPrev(map->judy, (Word_t *)&prev, (JError_t *)&map->err))
348 assert(prev != invalid);
353 * jmap_getval - access a value in-place for a given index.
354 * @map: map from jmap_new
355 * @index: the index to find
357 * Returns a pointer into the map, or NULL if the index isn't in the
358 * map. Like the other val functions (jmap_nthval, jmap_firstval
359 * etc), this pointer cannot be used after a jmap_add or jmap_del
360 * call, and you must call jmap_putval() once you are finished.
362 * Unless you define NDEBUG, jmap_add and kmap_del will check that you
363 * have called jmap_putval().
367 * jmap_add(map, 0, 1);
368 * p = jmap_getval(map, 0);
370 * errx(1, "Could not find 0 in map!");
372 * errx(1, "Value in map was not 0?!");
374 * jmap_putval(map, &p);
375 * // Accessing p now would probably crash.
378 * jmap_putval(), jmap_firstval()
380 static inline size_t *jmap_getval(struct jmap *map, size_t index)
383 val = (void *)JudyLGet(map->judy, index, (JError_t *)&map->err);
384 jmap_debug_add_access(map, index, val, "jmap_getval");
389 * jmap_putval - revoke access to a value.
390 * @map: map from jmap_new
391 * @p: the pointer to a pointer to the value
393 * @p is a pointer to the (successful) value retuned from one of the
394 * jmap_*val functions (listed below). After this, it will be invalid.
396 * Unless NDEBUG is defined, this will actually alter the value of p
397 * to point to garbage to help avoid accidental use.
400 * jmap_getval(), jmap_nthval(), jmap_firstval(), jmap_nextval(),
401 * jmap_lastval(), jmap_prevval().
403 static inline void jmap_putval(struct jmap *map, size_t **p)
405 jmap_debug_del_access(map, p);
409 * jmap_nthval - access the value of the nth value in the map.
410 * @map: map from jmap_new
411 * @n: which index we are interested in (0-based)
413 * This returns a pointer to the value at the nth index in the map,
414 * or NULL if there are n is greater than the population of the map.
415 * You must use jmap_putval() on the pointer once you are done with it.
420 * // We know 0 isn't in map.
421 * assert(!jmap_test(map, 0));
422 * for (i = 0; (val = jmap_nthval(map, i, &index)) != NULL; i++) {
423 * assert(jmap_popcount(map, 0, index) == i);
424 * printf("Index %zu = %zu, value = %zu\n", i, index, *val);
425 * jmap_putval(map, &val);
431 static inline size_t *jmap_nthval(const struct jmap *map,
432 size_t n, size_t *index)
435 val = (size_t *)JudyLByCount(map->judy, n+1, (Word_t *)index,
436 (JError_t *)&map->err);
437 jmap_debug_add_access(map, *index, val, "jmap_nthval");
442 * jmap_firstval - access the first value in the map.
443 * @map: map from jmap_new
444 * @index: set to the first index in the map.
446 * Returns NULL if the map is empty; otherwise this returns a pointer to
447 * the first value, which you must call jmap_putval() on!
450 * // Add one to every value.
451 * for (val = jmap_firstval(map, &i); val; val = jmap_nextval(map, &i)) {
453 * jmap_putval(map, &val);
458 * jmap_first, jmap_nextval()
460 static inline size_t *jmap_firstval(const struct jmap *map, size_t *index)
464 val = (size_t *)JudyLFirst(map->judy, (Word_t *)index,
465 (JError_t *)&map->err);
466 jmap_debug_add_access(map, *index, val, "jmap_firstval");
471 * jmap_nextval - access the next value in the map.
472 * @map: map from jmap_new
473 * @index: previous index, updated with the new index.
475 * This returns a pointer to a value (which you must call jmap_putval on)
476 * or NULL. This usually used to find an adjacent value after jmap_firstval.
479 * jmap_firstval(), jmap_putval()
481 static inline size_t *jmap_nextval(const struct jmap *map, size_t *index)
484 val = (size_t *)JudyLNext(map->judy, (Word_t *)index,
485 (JError_t *)&map->err);
486 jmap_debug_add_access(map, *index, val, "jmap_nextval");
491 * jmap_lastval - access the last value in the map.
492 * @map: map from jmap_new
493 * @index: set to the last index in the map.
496 * jmap_last(), jmap_putval()
498 static inline size_t *jmap_lastval(const struct jmap *map, size_t *index)
502 val = (size_t *)JudyLLast(map->judy, (Word_t *)index,
503 (JError_t *)&map->err);
504 jmap_debug_add_access(map, *index, val, "jmap_lastval");
509 * jmap_prevval - access the previous value in the map.
510 * @map: map from jmap_new
511 * @index: previous index, updated with the new index.
513 * This returns a pointer to a value (which you must call jmap_putval on)
514 * or NULL. This usually used to find an adjacent value after jmap_lastval.
517 * jmap_lastval(), jmap_putval()
519 static inline size_t *jmap_prevval(const struct jmap *map, size_t *index)
522 val = (size_t *)JudyLPrev(map->judy, (Word_t *)index,
523 (JError_t *)&map->err);
524 jmap_debug_add_access(map, *index, val, "jmap_prevval");
527 #endif /* CCAN_JMAP_H */