From: Rusty Russell Date: Fri, 23 Sep 2011 02:30:49 +0000 (+0930) Subject: jmap: use ccan/tcon and always be typesafe. X-Git-Url: https://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=3a34aa1a0c71b0be86511a8aa83af9935351dad1 jmap: use ccan/tcon and always be typesafe. This handles both pointer and integer types using ccan/tcon. --- diff --git a/ccan/jmap/_info b/ccan/jmap/_info index cad473bf..0047dc05 100644 --- a/ccan/jmap/_info +++ b/ccan/jmap/_info @@ -9,38 +9,46 @@ * integers or pointers as an index, Judy arrays provide an efficient * map to integers or pointers. * - * jmap.h simply contains wrappers for a size_t-indexed size_t values, and - * jmap_type.h contain a wrapper macro for size_t->pointer maps and pointer - * ->pointer maps. + * You define a struct for your particular index and value types using + * the JMAP_MEMBERS macro, then use the jmap routines to manipulate + * the mapping. + * + * Note: if you use an integer type for the index or value types and + * your compiler doesn't support "typeof", you will get warnings about + * mixing pointers and integers. * * Example: * // Silly example of associating data with arguments by pointer and int. * #include * #include - * #include + * #include * * struct opt_detail { * bool is_long; * unsigned int length; // == 1 if !is_long. * }; * - * // Define jmap_arg_ and jmap_arg, for int -> argv. - * JMAP_DEFINE_UINTIDX_TYPE(char, arg); - * // Define jmap_opt_ and jmap_opt, for argv -> struct opt_detail *. - * JMAP_DEFINE_PTRIDX_TYPE(char, struct opt_detail, opt); + * // Define map type for int -> argv. + * struct arg_map { + * JMAP_MEMBERS(int, char *); + * }; + * // Define map type for argv -> struct opt_detail *. + * struct opt_map { + * JMAP_MEMBERS(char *, struct opt_detail *); + * }; * * int main(int argc, char *argv[]) * { * int i; * // This map is equivalent to the argv[] array. Silly example. - * struct jmap_arg *arg = jmap_arg_new(); - * struct jmap_opt *opt = jmap_opt_new(); + * struct arg_map *arg = jmap_new(struct arg_map); + * struct opt_map *opt = jmap_new(struct opt_map); * struct opt_detail *d; * * // Note: this is not correct for real parsing! - * for (i = 0; i < argc; i++) { - * jmap_arg_add(arg, i, argv[i]); - * if (i < 1 || argv[i][0] != '-') + * for (i = 1; i < argc; i++) { + * jmap_add(arg, i, argv[i]); + * if (argv[i][0] != '-') * continue; * d = malloc(sizeof(*d)); * if (argv[i][1] == '-') { @@ -52,27 +60,30 @@ * d->is_long = false; * d->length = 1; * } - * jmap_opt_add(opt, argv[i], d); + * jmap_add(opt, argv[i], d); * } * - * printf("Found %lu options:\n", jmap_opt_count(opt)); - * for (i = jmap_arg_first(arg,-1); i!=-1; i = jmap_arg_next(arg,i,-1)) { - * char *a = jmap_arg_get(arg, i); - * d = jmap_opt_get(opt, a); + * printf("Found %lu options:\n", jmap_count(opt)); + * for (i = jmap_first(arg); i; i = jmap_next(arg,i)) { + * char *a = jmap_get(arg, i); + * d = jmap_get(opt, a); * printf(" Arg %i ('%s') is a %s of %u chars\n", * i, a, - * d == NULL ? "normal argument" - * : d->is_long ? "long option" - * : "short option", + * d == NULL ? "normal arg" + * : d->is_long ? "long opt" + * : "short opt", * d == NULL ? strlen(a) : d->length); * // We no longer need it, so free it here. * free(d); * } - * jmap_opt_free(opt); - * jmap_arg_free(arg); + * jmap_free(opt); + * jmap_free(arg); * return 0; * } - * + * // Given "--help" output contains "Arg 1 ('--help') is a long opt of 4 chars" + * // Given "-h" output contains "Arg 1 ('-h') is a short opt of 1 chars" + * // Given "foo" output contains "Arg 1 ('foo') is a normal arg of 3 chars" + * * License: LGPL (v2.1 or any later version) * Author: Rusty Russell */ @@ -84,6 +95,7 @@ int main(int argc, char *argv[]) if (strcmp(argv[1], "depends") == 0) { printf("ccan/build_assert\n"); printf("ccan/compiler\n"); + printf("ccan/tcon\n"); printf("Judy\n"); return 0; } diff --git a/ccan/jmap/jmap.c b/ccan/jmap/jmap.c index 78b7ba21..8982a715 100644 --- a/ccan/jmap/jmap.c +++ b/ccan/jmap/jmap.c @@ -4,7 +4,7 @@ #include #include -struct jmap *jmap_new(void) +struct jmap *jmap_new_(size_t size) { struct jmap *map; @@ -13,7 +13,8 @@ struct jmap *jmap_new(void) /* We also put pointers into Judy, in jmap_types.h */ BUILD_ASSERT(sizeof(Word_t) >= sizeof(void *)); - map = malloc(sizeof(*map)); + assert(size >= sizeof(*map)); + map = malloc(size); if (map) { map->judy = NULL; memset(&map->err, 0, sizeof(map->err)); @@ -26,7 +27,7 @@ struct jmap *jmap_new(void) return map; } -const char *jmap_error_(struct jmap *map) +const char *jmap_error_str_(struct jmap *map) { char *str; free((char *)map->errstr); @@ -40,7 +41,7 @@ const char *jmap_error_(struct jmap *map) return str; } -void jmap_free(const struct jmap *map) +void jmap_free_(const struct jmap *map) { free((char *)map->errstr); JudyLFreeArray((PPvoid_t)&map->judy, PJE0); diff --git a/ccan/jmap/jmap.h b/ccan/jmap/jmap.h index 26a8d339..e30a6ece 100644 --- a/ccan/jmap/jmap.h +++ b/ccan/jmap/jmap.h @@ -1,39 +1,23 @@ /* Licensed under LGPLv2.1+ - see LICENSE file for details */ #ifndef CCAN_JMAP_H #define CCAN_JMAP_H +#include +#include #include #include #include #include -#include #include #ifdef CCAN_JMAP_DEBUG #include #endif /** - * jmap_new - create a new, empty jmap. + * struct map - private definition of a jmap. * - * See Also: - * JMAP_DEFINE_TYPE() - * - * Example: - * struct jmap *map = jmap_new(); - * if (!map) - * errx(1, "Failed to allocate jmap"); + * It's exposed here so you can put it in your structures and so we can + * supply inline functions. */ -struct jmap *jmap_new(void); - -/** - * jmap_free - destroy a jmap. - * @map: the map returned from jmap_new. - * - * Example: - * jmap_free(map); - */ -void jmap_free(const struct jmap *map); - -/* This is exposed in the header so we can inline. Treat it as private! */ struct jmap { Pvoid_t judy; JError_t err; @@ -45,47 +29,46 @@ struct jmap { unsigned long acc_index; const char *funcname; }; -const char *COLD jmap_error_(struct jmap *map); -/* Debugging checks. */ -static inline void jmap_debug_add_access(const struct jmap *map, - unsigned long index, - unsigned long *val, - const char *funcname) -{ -#ifdef CCAN_JMAP_DEBUG - if (!map->acc_value) { - ((struct jmap *)map)->acc_value = val; - ((struct jmap *)map)->acc_index = index; - ((struct jmap *)map)->funcname = funcname; - } -#endif - if (val) - assert(++((struct jmap *)map)->num_accesses); -} +/** + * JMAP_MEMBERS - declare members for a type-specific jmap. + * @itype: index type for this map, or void * for any pointer. + * @ctype: contents type for this map, or void * for any pointer. + * + * Example: + * struct jmap_long_to_charp { + * JMAP_MEMBERS(long, char *); + * }; + */ +#define JMAP_MEMBERS(itype, ctype) \ + struct jmap raw; \ + TCON(itype icanary; ctype ccanary) -static inline void jmap_debug_del_access(struct jmap *map, unsigned long **val) -{ - assert(--map->num_accesses >= 0); -#ifdef CCAN_JMAP_DEBUG - if (map->acc_value == *val) - map->acc_value = NULL; -#endif - /* Set it to some invalid value. Not NULL, they might rely on that! */ - assert(memset(val, 0x42, sizeof(*val))); -} +/** + * jmap_new - create a new, empty jmap. + * + * See Also: + * JMAP_MEMBERS() + * + * Example: + * struct jmap_long_to_charp { + * JMAP_MEMBERS(long, char *); + * }; + * + * struct jmap_long_to_charp *map = jmap_new(struct jmap_long_to_charp); + * if (!map) + * errx(1, "Failed to allocate jmap"); + */ +#define jmap_new(type) ((type *)jmap_new_(sizeof(type))) -static inline void jmap_debug_access(struct jmap *map) -{ -#ifdef CCAN_JMAP_DEBUG - if (map->num_accesses && map->acc_value) - fprintf(stderr, - "jmap: still got index %lu, val %lu (%p) from %s\n", - map->acc_index, *map->acc_value, map->acc_value, - map->funcname); -#endif - assert(!map->num_accesses); -} +/** + * jmap_free - destroy a jmap. + * @map: the map returned from jmap_new. + * + * Example: + * jmap_free(map); + */ +#define jmap_free(map) jmap_free_(&(map)->raw) /** * jmap_error - test for an error in the a previous jmap_ operation. @@ -99,21 +82,48 @@ static inline void jmap_debug_access(struct jmap *map) * interface misuse. * * Example: - * struct jmap *map = jmap_new(); * const char *errstr; * - * if (!map) - * err(1, "allocating jmap"); * errstr = jmap_error(map); * if (errstr) * errx(1, "Woah, error on newly created map?! %s", errstr); */ -static inline const char *jmap_error(struct jmap *map) -{ - if (JU_ERRNO(&map->err) <= JU_ERRNO_NFMAX) - return NULL; - return jmap_error_(map); -} +#define jmap_error(map) jmap_error_(&(map)->raw) + +/** + * jmap_rawi - unwrap the typed map and check the index type + * @map: the typed jmap + * @expr: the expression to check the index type against (not evaluated) + * + * This macro usually causes the compiler to emit a warning if the + * variable is of an unexpected type. It is used internally where we + * need to access the raw underlying jmap. + */ +#define jmap_rawi(map, expr) (&tcon_check((map), icanary, (expr))->raw) + +/** + * jmap_rawc - unwrap the typed map and check the contents type + * @map: the typed jmap + * @expr: the expression to check the content type against (not evaluated) + * + * This macro usually causes the compiler to emit a warning if the + * variable is of an unexpected type. It is used internally where we + * need to access the raw underlying jmap. + */ +#define jmap_rawc(map, expr) (&tcon_check((map), ccanary, (expr))->raw) + +/** + * jmap_rawci - unwrap the typed map and check the index and contents types + * @map: the typed jmap + * @iexpr: the expression to check the index type against (not evaluated) + * @cexpr: the expression to check the contents type against (not evaluated) + * + * This macro usually causes the compiler to emit a warning if the + * variable is of an unexpected type. It is used internally where we + * need to access the raw underlying jmap. + */ +#define jmap_rawci(map, iexpr, cexpr) \ + (&tcon_check(tcon_check((map), ccanary, (cexpr)), icanary, (iexpr))->raw) /** * jmap_add - add or replace a value for a given index in the map. @@ -125,20 +135,12 @@ static inline const char *jmap_error(struct jmap *map) * Returns false on error (out of memory). * * Example: - * if (!jmap_add(map, 0, 1)) + * if (!jmap_add(map, 0, "hello")) * err(1, "jmap_add failed!"); */ -static inline bool jmap_add(struct jmap *map, - unsigned long index, unsigned long value) -{ - unsigned long *val; - jmap_debug_access(map); - val = (unsigned long *)JudyLIns(&map->judy, index, &map->err); - if (val == PJERR) - return false; - *val = value; - return true; -} +#define jmap_add(map, index, value) \ + jmap_add_(jmap_rawci((map), (index), (value)), \ + (unsigned long)(index), (unsigned long)value) /** * jmap_set - change a value for an existing index in the map. @@ -150,21 +152,12 @@ static inline bool jmap_add(struct jmap *map, * otherwise returns false and does nothing. * * Example: - * if (!jmap_set(map, 0, 2)) + * if (!jmap_set(map, 0, "goodbye")) * err(1, "jmap_set: index 0 not found"); */ -static inline bool jmap_set(const struct jmap *map, - unsigned long index, unsigned long value) -{ - unsigned long *val; - val = (unsigned long *)JudyLGet(map->judy, index, - (JError_t *)&map->err); - if (val && val != PJERR) { - *val = value; - return true; - } - return false; -} +#define jmap_set(map, index, value) \ + jmap_set_(jmap_rawci((map), (index), (value)), \ + (unsigned long)(index), (unsigned long)value) /** * jmap_del - remove an index from the map. @@ -175,11 +168,8 @@ static inline bool jmap_set(const struct jmap *map, * if (!jmap_del(map, 0)) * err(1, "jmap_del failed!"); */ -static inline bool jmap_del(struct jmap *map, unsigned long index) -{ - jmap_debug_access(map); - return JudyLDel(&map->judy, index, &map->err) == 1; -} +#define jmap_del(map, index) \ + jmap_del_(jmap_rawi((map), (index)), (unsigned long)(index)) /** * jmap_test - test if a given index is defined. @@ -187,38 +177,40 @@ static inline bool jmap_del(struct jmap *map, unsigned long index) * @index: the index to find * * Example: - * jmap_add(map, 0, 1); - * assert(jmap_test(map, 0)); + * jmap_add(map, 1, "hello"); + * assert(jmap_test(map, 1)); */ -static inline bool jmap_test(const struct jmap *map, unsigned long index) -{ - return JudyLGet(map->judy, index, (JError_t *)&map->err) != NULL; -} +#define jmap_test(map, index) \ + jmap_test_(jmap_rawi((map), (index)), (unsigned long)(index)) /** * jmap_get - get a value for a given index. * @map: map from jmap_new * @index: the index to find - * @invalid: the value to return if the index isn't found. + * + * Returns 0 if !jmap_test(map, index). * * Example: - * jmap_add(map, 0, 1); - * assert(jmap_get(map, 0, -1) == 1); + * const char *str = "hello"; + * jmap_add(map, 2, str); + * assert(jmap_get(map, 0) == str); * * See Also: * jmap_getval() */ -static inline unsigned long jmap_get(const struct jmap *map, - unsigned long index, - unsigned long invalid) -{ - unsigned long *val; - val = (unsigned long *)JudyLGet(map->judy, index, - (JError_t *)&map->err); - if (!val || val == PJERR) - return invalid; - return *val; -} +#define jmap_get(map, index) \ + tcon_cast((map), ccanary, \ + jmap_get_(jmap_rawi((map), (index)), (unsigned long)(index))) + +/** + * jmap_count - get population of the map. + * @map: map from jmap_new + * + * Example: + * assert(jmap_count(map) < 1000); + */ +#define jmap_count(map) \ + jmap_popcount_(&(map)->raw, 0, -1UL) /** * jmap_popcount - get population of (some part of) the map. @@ -229,12 +221,9 @@ static inline unsigned long jmap_get(const struct jmap *map, * Example: * assert(jmap_popcount(map, 0, 1000) <= jmap_popcount(map, 0, 2000)); */ -static inline unsigned long jmap_popcount(const struct jmap *map, - unsigned long start, - unsigned long end_incl) -{ - return JudyLCount(map->judy, start, end_incl, (JError_t *)&map->err); -} +#define jmap_popcount(map, start, end_incl) \ + jmap_popcount_(jmap_rawi((map), (start) ? (start) : (end_incl)), \ + (unsigned long)(start), (unsigned long)(end_incl)) /** * jmap_nth - return the index of the nth value in the map. @@ -259,109 +248,74 @@ static inline unsigned long jmap_popcount(const struct jmap *map, * See Also: * jmap_nthval(); */ -static inline unsigned long jmap_nth(const struct jmap *map, - unsigned long n, unsigned long invalid) -{ - unsigned long index; - if (!JudyLByCount(map->judy, n+1, &index, (JError_t *)&map->err)) - index = invalid; - return index; -} +#define jmap_nth(map, n, invalid) \ + tcon_cast((map), icanary, \ + jmap_nth_(jmap_rawi((map), (invalid)), \ + (n), (unsigned long)(invalid))) /** - * jmap_first - return the first index in the map. + * jmap_first - return the first index in the map (must not contain 0). * @map: map from jmap_new - * @invalid: return value if jmap is empty. * - * This is equivalent to jmap_nth(map, 0, invalid). + * This is equivalent to jmap_nth(map, 0, 0). * * Example: * assert(!jmap_test(map, 0)); * printf("Map indices (increasing order):"); - * for (i = jmap_first(map, 0); i; i = jmap_next(map, i, 0)) + * for (i = jmap_first(map); i; i = jmap_next(map, i)) * printf(" %lu", i); * printf("\n"); * * See Also: * jmap_firstval() */ -static inline unsigned long jmap_first(const struct jmap *map, - unsigned long invalid) -{ - unsigned long index = 0; - if (!JudyLFirst(map->judy, &index, (JError_t *)&map->err)) - index = invalid; - else - assert(index != invalid); - return index; -} +#define jmap_first(map) \ + tcon_cast((map), icanary, jmap_first_(&(map)->raw)) /** * jmap_next - return the next index in the map. * @map: map from jmap_new * @prev: previous index - * @invalid: return value if there prev was final index in map. * * This is usually used to find an adjacent index after jmap_first. * See Also: * jmap_nextval() */ -static inline unsigned long jmap_next(const struct jmap *map, - unsigned long prev, - unsigned long invalid) -{ - if (!JudyLNext(map->judy, &prev, (JError_t *)&map->err)) - prev = invalid; - else - assert(prev != invalid); - return prev; -} +#define jmap_next(map, prev) \ + tcon_cast((map), icanary, jmap_next_(jmap_rawi((map), (prev)), \ + (unsigned long)(prev))) /** * jmap_last - return the last index in the map. * @map: map from jmap_new - * @invalid: return value if map is empty. + * + * Returns 0 if map is empty. * * Example: * assert(!jmap_test(map, 0)); * printf("Map indices (increasing order):"); - * for (i = jmap_last(map, 0); i; i = jmap_prev(map, i, 0)) + * for (i = jmap_last(map); i; i = jmap_prev(map, i)) * printf(" %lu", i); * printf("\n"); * See Also: * jmap_lastval() */ -static inline unsigned long jmap_last(const struct jmap *map, - unsigned long invalid) -{ - unsigned long index = -1; - if (!JudyLLast(map->judy, &index, (JError_t *)&map->err)) - index = invalid; - else - assert(index != invalid); - return index; -} +#define jmap_last(map) \ + tcon_cast((map), icanary, jmap_last_(&(map)->raw)) /** - * jmap_prev - return the previous index in the map. + * jmap_prev - return the previous index in the map (must not contain 0) * @map: map from jmap_new * @prev: previous index - * @invalid: return value if no previous indices are in the map. * * This is usually used to find an prior adjacent index after jmap_last. + * Returns 0 if no previous indices in map. + * * See Also: * jmap_prevval() */ -static inline unsigned long jmap_prev(const struct jmap *map, - unsigned long prev, - unsigned long invalid) -{ - if (!JudyLPrev(map->judy, &prev, (JError_t *)&map->err)) - prev = invalid; - else - assert(prev != invalid); - return prev; -} +#define jmap_prev(map, prev) \ + tcon_cast((map), icanary, jmap_prev_(jmap_rawi((map), (prev)), (prev))) /** * jmap_getval - access a value in-place for a given index. @@ -377,28 +331,24 @@ static inline unsigned long jmap_prev(const struct jmap *map, * have called jmap_putval(). * * Example: - * unsigned long *p; - * jmap_add(map, 0, 1); + * char **p; + * jmap_add(map, 0, "hello"); * p = jmap_getval(map, 0); * if (!p) * errx(1, "Could not find 0 in map!"); - * if (*p != 1) - * errx(1, "Value in map was not 0?!"); - * *p = 7; + * if (strcmp(*p, "hello") != 0) + * errx(1, "Value in map was not correct?!"); + * *p = (char *)"goodbye"; * jmap_putval(map, &p); * // Accessing p now would probably crash. * * See Also: * jmap_putval(), jmap_firstval() */ -static inline unsigned long *jmap_getval(struct jmap *map, unsigned long index) -{ - unsigned long *val; - val = (unsigned long *)JudyLGet(map->judy, index, - (JError_t *)&map->err); - jmap_debug_add_access(map, index, val, "jmap_getval"); - return val; -} +#define jmap_getval(map, index) \ + tcon_cast_ptr((map), ccanary, \ + jmap_getval_(jmap_rawi((map), (index)), \ + (unsigned long)(index))) /** * jmap_putval - revoke access to a value. @@ -415,43 +365,36 @@ static inline unsigned long *jmap_getval(struct jmap *map, unsigned long index) * jmap_getval(), jmap_nthval(), jmap_firstval(), jmap_nextval(), * jmap_lastval(), jmap_prevval(). */ -static inline void jmap_putval(struct jmap *map, unsigned long **p) -{ - jmap_debug_del_access(map, p); -} +#define jmap_putval(map, p) \ + jmap_putval_(jmap_rawc((map), **(p)), (p)) /** * jmap_nthval - access the value of the nth value in the map. * @map: map from jmap_new * @n: which index we are interested in (0-based) + * @index: set to the nth index in the map. * * This returns a pointer to the value at the nth index in the map, * or NULL if there are n is greater than the population of the map. * You must use jmap_putval() on the pointer once you are done with it. * * Example: - * unsigned long *val; + * char **val; * * // We know 0 isn't in map. * assert(!jmap_test(map, 0)); * for (i = 0; (val = jmap_nthval(map, i, &index)) != NULL; i++) { * assert(jmap_popcount(map, 0, index) == i); - * printf("Index %lu = %lu, value = %lu\n", i, index, *val); + * printf("Index %lu = %lu, value = %s\n", i, index, *val); * jmap_putval(map, &val); * } * * See Also: * jmap_nth(); */ -static inline unsigned long *jmap_nthval(const struct jmap *map, - unsigned long n, unsigned long *index) -{ - unsigned long *val; - val = (unsigned long *)JudyLByCount(map->judy, n+1, index, - (JError_t *)&map->err); - jmap_debug_add_access(map, *index, val, "jmap_nthval"); - return val; -} +#define jmap_nthval(map, n, index) \ + tcon_cast_ptr((map), ccanary, \ + jmap_nthval_(jmap_rawi((map), *(index)), (n), (index))) /** * jmap_firstval - access the first value in the map. @@ -462,7 +405,7 @@ static inline unsigned long *jmap_nthval(const struct jmap *map, * the first value, which you must call jmap_putval() on! * * Example: - * // Add one to every value. + * // Add one to every value (ie. make it point into second char of string) * for (val = jmap_firstval(map, &i); val; val = jmap_nextval(map, &i)) { * (*val)++; * jmap_putval(map, &val); @@ -472,16 +415,10 @@ static inline unsigned long *jmap_nthval(const struct jmap *map, * See Also: * jmap_first, jmap_nextval() */ -static inline unsigned long *jmap_firstval(const struct jmap *map, - unsigned long *index) -{ - unsigned long *val; - *index = 0; - val = (unsigned long *)JudyLFirst(map->judy, index, - (JError_t *)&map->err); - jmap_debug_add_access(map, *index, val, "jmap_firstval"); - return val; -} +#define jmap_firstval(map, index) \ + tcon_cast_ptr((map), ccanary, \ + jmap_firstval_(jmap_rawi((map), *(index)), \ + (unsigned long *)(index))) /** * jmap_nextval - access the next value in the map. @@ -494,15 +431,11 @@ static inline unsigned long *jmap_firstval(const struct jmap *map, * See Also: * jmap_firstval(), jmap_putval() */ -static inline unsigned long *jmap_nextval(const struct jmap *map, - unsigned long *index) -{ - unsigned long *val; - val = (unsigned long *)JudyLNext(map->judy, index, - (JError_t *)&map->err); - jmap_debug_add_access(map, *index, val, "jmap_nextval"); - return val; -} +#define jmap_nextval(map, index) \ + tcon_cast_ptr((map), ccanary, \ + jmap_nextval_(jmap_rawi((map), *(index)), \ + (unsigned long *)(index))) + /** * jmap_lastval - access the last value in the map. @@ -512,16 +445,11 @@ static inline unsigned long *jmap_nextval(const struct jmap *map, * See Also: * jmap_last(), jmap_putval() */ -static inline unsigned long *jmap_lastval(const struct jmap *map, - unsigned long *index) -{ - unsigned long *val; - *index = -1; - val = (unsigned long *)JudyLLast(map->judy, index, - (JError_t *)&map->err); - jmap_debug_add_access(map, *index, val, "jmap_lastval"); - return val; -} +#define jmap_lastval(map, index) \ + tcon_cast_ptr((map), ccanary, \ + jmap_lastval_(jmap_rawi((map), *(index)), \ + (unsigned long *)(index))) + /** * jmap_prevval - access the previous value in the map. @@ -534,8 +462,207 @@ static inline unsigned long *jmap_lastval(const struct jmap *map, * See Also: * jmap_lastval(), jmap_putval() */ -static inline unsigned long *jmap_prevval(const struct jmap *map, +#define jmap_prevval(map, index) \ + tcon_cast_ptr((map), ccanary, \ + jmap_prevval_(jmap_rawi((map), *(index)), \ + (unsigned long *)(index))) + + + +/* Debugging checks. */ +static inline void jmap_debug_add_access(const struct jmap *map, + unsigned long index, + unsigned long *val, + const char *funcname) +{ +#ifdef CCAN_JMAP_DEBUG + if (!map->acc_value) { + ((struct jmap *)map)->acc_value = val; + ((struct jmap *)map)->acc_index = index; + ((struct jmap *)map)->funcname = funcname; + } +#endif + if (val) + assert(++((struct jmap *)map)->num_accesses); +} + +static inline void jmap_debug_del_access(struct jmap *map, unsigned long **val) +{ + assert(--map->num_accesses >= 0); +#ifdef CCAN_JMAP_DEBUG + if (map->acc_value == *val) + map->acc_value = NULL; +#endif + /* Set it to some invalid value. Not NULL, they might rely on that! */ + assert(memset(val, 0x42, sizeof(void *))); +} + +static inline void jmap_debug_access(struct jmap *map) +{ +#ifdef CCAN_JMAP_DEBUG + if (map->num_accesses && map->acc_value) + fprintf(stderr, + "jmap: still got index %lu, val %lu (%p) from %s\n", + map->acc_index, *map->acc_value, map->acc_value, + map->funcname); +#endif + assert(!map->num_accesses); +} + +/* Private functions */ +struct jmap *jmap_new_(size_t size); +void jmap_free_(const struct jmap *map); +const char *COLD jmap_error_str_(struct jmap *map); +static inline const char *jmap_error_(struct jmap *map) +{ + if (JU_ERRNO(&map->err) <= JU_ERRNO_NFMAX) + return NULL; + return jmap_error_str_(map); +} +static inline bool jmap_add_(struct jmap *map, + unsigned long index, unsigned long value) +{ + unsigned long *val; + jmap_debug_access(map); + val = (unsigned long *)JudyLIns(&map->judy, index, &map->err); + if (val == PJERR) + return false; + *val = value; + return true; +} +static inline bool jmap_set_(const struct jmap *map, + unsigned long index, unsigned long value) +{ + unsigned long *val; + val = (unsigned long *)JudyLGet(map->judy, index, + (JError_t *)&map->err); + if (val && val != PJERR) { + *val = value; + return true; + } + return false; +} +static inline bool jmap_del_(struct jmap *map, unsigned long index) +{ + jmap_debug_access(map); + return JudyLDel(&map->judy, index, &map->err) == 1; +} +static inline bool jmap_test_(const struct jmap *map, unsigned long index) +{ + return JudyLGet(map->judy, index, (JError_t *)&map->err) != NULL; +} +static inline unsigned long jmap_get_(const struct jmap *map, + unsigned long index) +{ + unsigned long *val; + val = (unsigned long *)JudyLGet(map->judy, index, + (JError_t *)&map->err); + if (!val || val == PJERR) + return 0; + return *val; +} +static inline unsigned long jmap_popcount_(const struct jmap *map, + unsigned long start, + unsigned long end_incl) +{ + return JudyLCount(map->judy, start, end_incl, (JError_t *)&map->err); +} +static inline unsigned long jmap_nth_(const struct jmap *map, + unsigned long n, unsigned long invalid) +{ + unsigned long index; + if (!JudyLByCount(map->judy, n+1, &index, (JError_t *)&map->err)) + index = invalid; + return index; +} +static inline unsigned long jmap_first_(const struct jmap *map) +{ + unsigned long index = 0; + if (!JudyLFirst(map->judy, &index, (JError_t *)&map->err)) + index = 0; + else + assert(index != 0); + return index; +} +static inline unsigned long jmap_next_(const struct jmap *map, + unsigned long prev) +{ + if (!JudyLNext(map->judy, &prev, (JError_t *)&map->err)) + prev = 0; + else + assert(prev != 0); + return prev; +} +static inline unsigned long jmap_last_(const struct jmap *map) +{ + unsigned long index = -1; + if (!JudyLLast(map->judy, &index, (JError_t *)&map->err)) + index = 0; + else + assert(index != 0); + return index; +} +static inline unsigned long jmap_prev_(const struct jmap *map, + unsigned long prev) +{ + if (!JudyLPrev(map->judy, &prev, (JError_t *)&map->err)) + prev = 0; + else + assert(prev != 0); + return prev; +} +static inline void *jmap_getval_(struct jmap *map, unsigned long index) +{ + unsigned long *val; + val = (unsigned long *)JudyLGet(map->judy, index, + (JError_t *)&map->err); + jmap_debug_add_access(map, index, val, "jmap_getval"); + return val; +} +static inline void jmap_putval_(struct jmap *map, void *p) +{ + jmap_debug_del_access(map, p); +} +static inline unsigned long *jmap_nthval_(const struct jmap *map, unsigned long n, unsigned long *index) +{ + unsigned long *val; + val = (unsigned long *)JudyLByCount(map->judy, n+1, index, + (JError_t *)&map->err); + jmap_debug_add_access(map, *index, val, "jmap_nthval"); + return val; +} +static inline unsigned long *jmap_firstval_(const struct jmap *map, + unsigned long *index) +{ + unsigned long *val; + *index = 0; + val = (unsigned long *)JudyLFirst(map->judy, index, + (JError_t *)&map->err); + jmap_debug_add_access(map, *index, val, "jmap_firstval"); + return val; +} +static inline unsigned long *jmap_nextval_(const struct jmap *map, + unsigned long *index) +{ + unsigned long *val; + val = (unsigned long *)JudyLNext(map->judy, index, + (JError_t *)&map->err); + jmap_debug_add_access(map, *index, val, "jmap_nextval"); + return val; +} +static inline unsigned long *jmap_lastval_(const struct jmap *map, + unsigned long *index) +{ + unsigned long *val; + *index = -1; + val = (unsigned long *)JudyLLast(map->judy, index, + (JError_t *)&map->err); + jmap_debug_add_access(map, *index, val, "jmap_lastval"); + return val; +} +static inline unsigned long *jmap_prevval_(const struct jmap *map, + unsigned long *index) { unsigned long *val; val = (unsigned long *)JudyLPrev(map->judy, index, diff --git a/ccan/jmap/jmap_type.h b/ccan/jmap/jmap_type.h deleted file mode 100644 index 43155a2c..00000000 --- a/ccan/jmap/jmap_type.h +++ /dev/null @@ -1,303 +0,0 @@ -/* Licensed under LGPLv2.1+ - see LICENSE file for details */ -#ifndef CCAN_JMAP_TYPE_H -#define CCAN_JMAP_TYPE_H -#include - -/** - * JMAP_DEFINE_UINTIDX_TYPE - create a set of jmap ops for integer->ptr map - * @type: a type whose pointers will be values in the map. - * @name: a name for all the functions to define (of form jmap__*) - * - * It's easiest if NULL values aren't placed in the map: jmap_@name_get will - * return NULL if an index isn't valid. - * - * The following wrapper functions are defined; each one is the same as - * the jmap.h generic equivalent except where noted: - * - * // Creating, errors and freeing. - * struct jmap_@name *jmap_@name_new(void); - * void jmap_@name_free(const struct jmap_@name *map); - * const char *jmap_@name_error(struct jmap_@name *map); - * - * // Add, set, delete, test and get. - * bool jmap_@name_add(struct jmap_@name *map, - * unsigned long idx, const type *value); - * bool jmap_@name_set(const struct jmap_@name *map, - * unsigned long idx, const type *value); - * bool jmap_@name_del(struct jmap_@name *map, unsigned long idx); - * bool jmap_@name_test(const struct jmap_@name *map, unsigned long idx); - * type *jmap_@name_get(const struct jmap_@name *map, unsigned long idx); - * - * // Counting and iteration. - * unsigned long jmap_@name_popcount(const struct jmap_@name *map, - * unsigned long start, - * unsigned long end_incl); - * unsigned long jmap_@name_nth(const struct jmap_@name *map, - * unsigned long n, unsigned long invalid); - * unsigned long jmap_@name_first(const struct jmap_@name *map, - * unsigned long invalid); - * unsigned long jmap_@name_next(const struct jmap_@name *map, - * unsigned long prev, - * unsigned long invalid); - * unsigned long jmap_@name_last(const struct jmap_@name *map, - * unsigned long invalid); - * unsigned long jmap_@name_prev(const struct jmap_@name *map, - * unsigned long prev, - * unsigned long invalid); - * - * // Get pointers to values to use. - * type **jmap_@name_getval(const struct jmap_@name *map, - * unsigned long idx); - * void jmap_@name_putval(struct jmap_@name *map, type ***p); - * type **jmap_@name_nthval(struct jmap_@name *map, - * unsigned long n, unsigned long *idx); - * type **jmap_@name_firstval(const struct jmap_@name *map, - * unsigned long *idx); - * type **jmap_@name_nextval(const struct jmap_@name *map, - * unsigned long *idx); - * type **jmap_@name_lastval(const struct jmap_@name *map, - * unsigned long *idx); - * type **jmap_@name_prevval(const struct jmap_@name *map, - * unsigned long *idx); - */ -#define JMAP_DEFINE_UINTIDX_TYPE(type, name) \ -struct jmap_##name; \ -static inline struct jmap_##name *jmap_##name##_new(void) \ -{ \ - return (struct jmap_##name *)jmap_new(); \ -} \ -static inline void jmap_##name##_free(const struct jmap_##name *map) \ -{ \ - jmap_free((const struct jmap *)map); \ -} \ -static inline const char *jmap_##name##_error(struct jmap_##name *map) \ -{ \ - return jmap_error((struct jmap *)map); \ -} \ -static inline bool jmap_##name##_add(struct jmap_##name *map, \ - unsigned long idx, const type *value) \ -{ \ - return jmap_add((struct jmap *)map, idx, (unsigned long)value); \ -} \ -static inline bool jmap_##name##_set(const struct jmap_##name *map, \ - unsigned long idx, const type *value) \ -{ \ - return jmap_set((const struct jmap *)map, idx, (unsigned long)value); \ -} \ -static inline bool jmap_##name##_del(struct jmap_##name *map, \ - unsigned long idx) \ -{ \ - return jmap_del((struct jmap *)map, idx); \ -} \ -static inline bool jmap_##name##_test(const struct jmap_##name *map, \ - unsigned long idx) \ -{ \ - return jmap_test((const struct jmap *)map, (unsigned long)idx); \ -} \ -static inline type *jmap_##name##_get(const struct jmap_##name *map, \ - unsigned long idx) \ -{ \ - return (type *)jmap_get((const struct jmap *)map, idx, 0); \ -} \ -static inline unsigned long \ -jmap_##name##_popcount(const struct jmap_##name *map, \ - unsigned long start, unsigned long end_incl) \ -{ \ - return jmap_popcount((const struct jmap *)map, start, end_incl); \ -} \ -static inline unsigned long jmap_##name##_nth(const struct jmap_##name *map, \ - unsigned long n, \ - unsigned long invalid) \ -{ \ - return jmap_nth((const struct jmap *)map, n, invalid); \ -} \ -static inline unsigned long \ -jmap_##name##_first(const struct jmap_##name *map, \ - unsigned long invalid) \ -{ \ - return jmap_first((const struct jmap *)map, invalid); \ -} \ -static inline unsigned long \ -jmap_##name##_next(const struct jmap_##name *map, \ - unsigned long prev, unsigned long invalid) \ -{ \ - return jmap_next((const struct jmap *)map, prev, invalid); \ -} \ -static inline unsigned long \ -jmap_##name##_last(const struct jmap_##name *map, \ - unsigned long invalid) \ -{ \ - return jmap_last((const struct jmap *)map, invalid); \ -} \ -static inline unsigned long \ -jmap_##name##_prev(const struct jmap_##name *map, \ - unsigned long prev, unsigned long invalid) \ -{ \ - return jmap_prev((const struct jmap *)map, prev, invalid); \ -} \ -static inline type **jmap_##name##_getval(const struct jmap_##name *map, \ - unsigned long idx) \ -{ \ - return (type **)jmap_getval((struct jmap *)map, idx); \ -} \ -static inline void jmap_##name##_putval(struct jmap_##name *map, \ - type ***p) \ -{ \ - return jmap_putval((struct jmap *)map, (unsigned long **)p); \ -} \ -static inline type **jmap_##name##_nthval(struct jmap_##name *map, \ - unsigned long n, \ - unsigned long *idx) \ -{ \ - return (type **)jmap_nthval((struct jmap *)map, n, idx); \ -} \ -static inline type **jmap_##name##_firstval(const struct jmap_##name *map, \ - unsigned long *idx) \ -{ \ - return (type **)jmap_firstval((const struct jmap *)map, idx); \ -} \ -static inline type **jmap_##name##_nextval(const struct jmap_##name *map, \ - unsigned long *idx) \ -{ \ - return (type **)jmap_nextval((const struct jmap *)map, idx); \ -} \ -static inline type **jmap_##name##_lastval(const struct jmap_##name *map, \ - unsigned long *idx) \ -{ \ - return (type **)jmap_lastval((const struct jmap *)map, idx); \ -} \ -static inline type **jmap_##name##_prevval(const struct jmap_##name *map, \ - unsigned long *idx) \ -{ \ - return (type **)jmap_prevval((const struct jmap *)map, idx); \ -} - -/** - * JMAP_DEFINE_PTRIDX_TYPE - create a map of jmap ops for ptr->ptr map - * @itype: a type whose pointers will idx into the map. - * @type: a type whose pointers will be values in the map. - * @name: a name for all the functions to define (of form jmap__*) - * - * This macro defines a map of inline functions for typesafe and - * convenient usage of a pointer-idxed Judy map of pointers. It is - * assumed that a NULL pointer is never an idx in the map, as - * various functions return NULL for "invalid idx". Similarly, - * jmap_@name_get will return NULL if an idx isn't valid, so NULL indices - * are not recommended (though you can tell using jmap_@name_test). - * - * Since the ordering is by idx pointer value, it's generally quite useless. - * Thus we don't define order-specific functions, except first/next for - * traversal. - * - * The following wrapper functions are defined; each one is the same as - * the jmap.h generic equivalent: - * - * struct jmap_@name *jmap_@name_new(void); - * void jmap_@name_free(const struct jmap_@name *map); - * const char *jmap_@name_error(struct jmap_@name *map); - * - * bool jmap_@name_add(const struct jmap_@name *map, - * const itype *idx, const type *value); - * bool jmap_@name_set(const struct jmap_@name *map, - * const itype *idx, const type *value); - * bool jmap_@name_del(struct jmap_@name *map, const itype *idx); - * bool jmap_@name_test(const struct jmap_@name *map, const itype *idx); - * - * type *jmap_@name_get(const struct jmap_@name *map, const itype *idx); - * itype *jmap_@name_count(const struct jmap_@name *map); - * itype *jmap_@name_first(const struct jmap_@name *map); - * itype *jmap_@name_next(const struct jmap_@name *map, - * const itype *prev); - * - * type **jmap_@name_getval(const struct jmap_@name *map, - * const itype *idx); - * void jmap_@name_putval(struct jmap_@name *map, type ***p); - * type **jmap_@name_firstval(const struct jmap_@name *map, - * const itype **idx); - * type **jmap_@name_nextval(const struct jmap_@name *map, - * const itype **idx); - */ -#define JMAP_DEFINE_PTRIDX_TYPE(itype, type, name) \ -struct jmap_##name; \ -static inline struct jmap_##name *jmap_##name##_new(void) \ -{ \ - return (struct jmap_##name *)jmap_new(); \ -} \ -static inline void jmap_##name##_free(const struct jmap_##name *map) \ -{ \ - jmap_free((const struct jmap *)map); \ -} \ -static inline const char *jmap_##name##_error(struct jmap_##name *map) \ -{ \ - return jmap_error((struct jmap *)map); \ -} \ -static inline bool jmap_##name##_add(struct jmap_##name *map, \ - const itype *idx, const type *value) \ -{ \ - return jmap_add((struct jmap *)map, (unsigned long)idx, \ - (unsigned long)value); \ -} \ -static inline bool jmap_##name##_set(const struct jmap_##name *map, \ - const itype *idx, const type *value) \ -{ \ - return jmap_set((const struct jmap *)map, (unsigned long)idx, \ - (unsigned long)value); \ -} \ -static inline bool jmap_##name##_del(struct jmap_##name *map, \ - const itype *idx) \ -{ \ - return jmap_del((struct jmap *)map, (unsigned long)idx); \ -} \ -static inline bool jmap_##name##_test(const struct jmap_##name *map, \ - const itype *idx) \ -{ \ - return jmap_test((const struct jmap *)map, (unsigned long)idx); \ -} \ -static inline type *jmap_##name##_get(const struct jmap_##name *map, \ - const itype *idx) \ -{ \ - return (type *)jmap_get((const struct jmap *)map, \ - (unsigned long)idx, 0); \ -} \ -static inline unsigned long \ -jmap_##name##_count(const struct jmap_##name *map) \ -{ \ - return jmap_popcount((const struct jmap *)map, 0, -1); \ -} \ -static inline itype *jmap_##name##_first(const struct jmap_##name *map) \ -{ \ - return (itype *)jmap_first((const struct jmap *)map, 0); \ -} \ -static inline itype *jmap_##name##_next(const struct jmap_##name *map, \ - const itype *prev) \ -{ \ - return (itype *)jmap_next((const struct jmap *)map, \ - (unsigned long)prev, 0); \ -} \ -static inline type **jmap_##name##_getval(const struct jmap_##name *map, \ - const itype *idx) \ -{ \ - return (type **)jmap_getval((struct jmap *)map, \ - (unsigned long)idx); \ -} \ -static inline void jmap_##name##_putval(struct jmap_##name *map, \ - type ***p) \ -{ \ - return jmap_putval((struct jmap *)map, (unsigned long **)p); \ -} \ -static inline type **jmap_##name##_firstval(const struct jmap_##name *map, \ - itype **idx) \ -{ \ - unsigned long i; \ - type **ret; \ - ret = (type **)jmap_firstval((const struct jmap *)map, &i); \ - *idx = (void *)i; \ - return ret; \ -} \ -static inline type **jmap_##name##_nextval(const struct jmap_##name *map, \ - itype **idx) \ -{ \ - return (type **)jmap_nextval((const struct jmap *)map, \ - (unsigned long *)idx); \ -} -#endif /* CCAN_JMAP_TYPE_H */ diff --git a/ccan/jmap/test/run-access-count.c b/ccan/jmap/test/run-access-count.c index 288e894c..d9773c9e 100644 --- a/ccan/jmap/test/run-access-count.c +++ b/ccan/jmap/test/run-access-count.c @@ -5,15 +5,19 @@ #include #include +struct map { + JMAP_MEMBERS(unsigned long, unsigned long); +}; + int main(int argc, char *argv[]) { - struct jmap *map; + struct map *map; unsigned long *value; int status; plan_tests(9); - map = jmap_new(); + map = jmap_new(struct map); ok1(jmap_error(map) == NULL); ok1(jmap_add(map, 0, 1)); diff --git a/ccan/jmap/test/run-ptridx-int.c b/ccan/jmap/test/run-ptridx-int.c new file mode 100644 index 00000000..112f5cbe --- /dev/null +++ b/ccan/jmap/test/run-ptridx-int.c @@ -0,0 +1,99 @@ +#include +#include + +struct idx; + +struct map { + JMAP_MEMBERS(struct idx *, int); +}; + +#define NUM 100 + +static int cmp_ptr(const void *a, const void *b) +{ + return *(char **)a - *(char **)b; +} + +int main(int argc, char *argv[]) +{ + struct map *map; + struct idx *idx[NUM+1], *index; + unsigned int i; + int *intp; + + plan_tests(25 + NUM*2 + 6); + for (i = 0; i < NUM+1; i++) + idx[i] = malloc(20); + + qsort(idx, NUM, sizeof(idx[0]), cmp_ptr); + + map = jmap_new(struct map); + ok1(jmap_error(map) == NULL); + + ok1(jmap_test(map, idx[NUM]) == false); + ok1(jmap_get(map, idx[NUM]) == 0); + ok1(jmap_count(map) == 0); + ok1(jmap_first(map) == 0); + ok1(jmap_del(map, idx[0]) == false); + + /* Set only works on existing cases. */ + ok1(jmap_set(map, idx[0], 0) == false); + ok1(jmap_add(map, idx[0], 1) == true); + ok1(jmap_get(map, idx[0]) == 1); + ok1(jmap_set(map, idx[0], -1) == true); + ok1(jmap_get(map, idx[0]) == -1); + + ok1(jmap_test(map, idx[0]) == true); + ok1(jmap_count(map) == 1); + ok1(jmap_first(map) == idx[0]); + ok1(jmap_next(map, idx[0]) == NULL); + + ok1(jmap_del(map, idx[0]) == true); + ok1(jmap_test(map, idx[0]) == false); + ok1(jmap_count(map) == 0); + + for (i = 0; i < NUM; i++) + jmap_add(map, idx[i], i+1); + + ok1(jmap_count(map) == NUM); + + ok1(jmap_first(map) == idx[0]); + ok1(jmap_next(map, idx[0]) == idx[1]); + ok1(jmap_next(map, idx[NUM-1]) == NULL); + + ok1(jmap_get(map, idx[0]) == 1); + ok1(jmap_get(map, idx[NUM-1]) == NUM); + ok1(jmap_get(map, (void *)((char *)idx[NUM-1] + 1)) == 0); + + /* Reverse values in map. */ + for (i = 0; i < NUM; i++) { + intp = jmap_getval(map, idx[i]); + ok1(*intp == i+1); + *intp = NUM-i; + jmap_putval(map, &intp); + } + for (i = 0; i < NUM; i++) + ok1(jmap_get(map, idx[i]) == NUM-i); + + intp = jmap_firstval(map, &index); + ok1(index == idx[0]); + ok1(*intp == NUM); + jmap_putval(map, &intp); + + intp = jmap_nextval(map, &index); + ok1(index == idx[1]); + ok1(*intp == NUM-1); + jmap_putval(map, &intp); + + index = idx[NUM-1]; + intp = jmap_nextval(map, &index); + ok1(intp == NULL); + + ok1(jmap_error(map) == NULL); + jmap_free(map); + + for (i = 0; i < NUM+1; i++) + free(idx[i]); + + return exit_status(); +} diff --git a/ccan/jmap/test/run-ptridx-type.c b/ccan/jmap/test/run-ptridx-type.c index 20a604a1..58c90b44 100644 --- a/ccan/jmap/test/run-ptridx-type.c +++ b/ccan/jmap/test/run-ptridx-type.c @@ -1,11 +1,12 @@ #include -#include #include struct foo; struct idx; -JMAP_DEFINE_PTRIDX_TYPE(struct idx, struct foo, foo); +struct jmap_foo { + JMAP_MEMBERS(struct idx *, struct foo *); +}; #define NUM 100 @@ -32,70 +33,70 @@ int main(int argc, char *argv[]) for (i = 0; i < NUM+1; i++) idx[i] = (void *)((char *)foo[i] + 1); - map = jmap_foo_new(); - ok1(jmap_foo_error(map) == NULL); + map = jmap_new(struct jmap_foo); + ok1(jmap_error(map) == NULL); - ok1(jmap_foo_test(map, idx[NUM]) == false); - ok1(jmap_foo_get(map, idx[NUM]) == (struct foo *)NULL); - ok1(jmap_foo_count(map) == 0); - ok1(jmap_foo_first(map) == (struct idx *)NULL); - ok1(jmap_foo_del(map, idx[0]) == false); + ok1(jmap_test(map, idx[NUM]) == false); + ok1(jmap_get(map, idx[NUM]) == (struct foo *)NULL); + ok1(jmap_count(map) == 0); + ok1(jmap_first(map) == (struct idx *)NULL); + ok1(jmap_del(map, idx[0]) == false); /* Set only works on existing cases. */ - ok1(jmap_foo_set(map, idx[0], foo[0]) == false); - ok1(jmap_foo_add(map, idx[0], foo[1]) == true); - ok1(jmap_foo_get(map, idx[0]) == foo[1]); - ok1(jmap_foo_set(map, idx[0], foo[0]) == true); - ok1(jmap_foo_get(map, idx[0]) == foo[0]); + ok1(jmap_set(map, idx[0], foo[0]) == false); + ok1(jmap_add(map, idx[0], foo[1]) == true); + ok1(jmap_get(map, idx[0]) == foo[1]); + ok1(jmap_set(map, idx[0], foo[0]) == true); + ok1(jmap_get(map, idx[0]) == foo[0]); - ok1(jmap_foo_test(map, idx[0]) == true); - ok1(jmap_foo_count(map) == 1); - ok1(jmap_foo_first(map) == idx[0]); - ok1(jmap_foo_next(map, idx[0]) == NULL); + ok1(jmap_test(map, idx[0]) == true); + ok1(jmap_count(map) == 1); + ok1(jmap_first(map) == idx[0]); + ok1(jmap_next(map, idx[0]) == NULL); - ok1(jmap_foo_del(map, idx[0]) == true); - ok1(jmap_foo_test(map, idx[0]) == false); - ok1(jmap_foo_count(map) == 0); + ok1(jmap_del(map, idx[0]) == true); + ok1(jmap_test(map, idx[0]) == false); + ok1(jmap_count(map) == 0); for (i = 0; i < NUM; i++) - jmap_foo_add(map, idx[i], foo[i]); + jmap_add(map, idx[i], foo[i]); - ok1(jmap_foo_count(map) == NUM); + ok1(jmap_count(map) == NUM); - ok1(jmap_foo_first(map) == idx[0]); - ok1(jmap_foo_next(map, idx[0]) == idx[1]); - ok1(jmap_foo_next(map, idx[NUM-1]) == NULL); + ok1(jmap_first(map) == idx[0]); + ok1(jmap_next(map, idx[0]) == idx[1]); + ok1(jmap_next(map, idx[NUM-1]) == NULL); - ok1(jmap_foo_get(map, idx[0]) == foo[0]); - ok1(jmap_foo_get(map, idx[NUM-1]) == foo[NUM-1]); - ok1(jmap_foo_get(map, (void *)((char *)idx[NUM-1] + 1)) == NULL); + ok1(jmap_get(map, idx[0]) == foo[0]); + ok1(jmap_get(map, idx[NUM-1]) == foo[NUM-1]); + ok1(jmap_get(map, (void *)((char *)idx[NUM-1] + 1)) == NULL); /* Reverse values in map. */ for (i = 0; i < NUM; i++) { - foop = jmap_foo_getval(map, idx[i]); + foop = jmap_getval(map, idx[i]); ok1(*foop == foo[i]); *foop = foo[NUM-1-i]; - jmap_foo_putval(map, &foop); + jmap_putval(map, &foop); } for (i = 0; i < NUM; i++) - ok1(jmap_foo_get(map, idx[i]) == foo[NUM-1-i]); + ok1(jmap_get(map, idx[i]) == foo[NUM-1-i]); - foop = jmap_foo_firstval(map, &index); + foop = jmap_firstval(map, &index); ok1(index == idx[0]); ok1(*foop == foo[NUM-1]); - jmap_foo_putval(map, &foop); + jmap_putval(map, &foop); - foop = jmap_foo_nextval(map, &index); + foop = jmap_nextval(map, &index); ok1(index == idx[1]); ok1(*foop == foo[NUM-2]); - jmap_foo_putval(map, &foop); + jmap_putval(map, &foop); index = idx[NUM-1]; - foop = jmap_foo_nextval(map, &index); + foop = jmap_nextval(map, &index); ok1(foop == NULL); - ok1(jmap_foo_error(map) == NULL); - jmap_foo_free(map); + ok1(jmap_error(map) == NULL); + jmap_free(map); for (i = 0; i < NUM+1; i++) free(foo[i]); diff --git a/ccan/jmap/test/run-uintidx-type.c b/ccan/jmap/test/run-uintidx-type.c index 2a371427..7427d33c 100644 --- a/ccan/jmap/test/run-uintidx-type.c +++ b/ccan/jmap/test/run-uintidx-type.c @@ -1,10 +1,11 @@ #include -#include #include struct foo; -JMAP_DEFINE_UINTIDX_TYPE(struct foo, foo); +struct jmap_foo { + JMAP_MEMBERS(unsigned long, struct foo *); +}; #define NUM 100 @@ -14,117 +15,120 @@ int main(int argc, char *argv[]) struct foo *foo[NUM], **foop; unsigned long i; - plan_tests(37 + NUM*2 + 19); + plan_tests(40 + NUM*2 + 19); for (i = 0; i < NUM; i++) foo[i] = malloc(20); - map = jmap_foo_new(); - ok1(jmap_foo_error(map) == NULL); + map = jmap_new(struct jmap_foo); + ok1(jmap_error(map) == NULL); - ok1(jmap_foo_test(map, 0) == false); - ok1(jmap_foo_get(map, 0) == (struct foo *)NULL); - ok1(jmap_foo_popcount(map, 0, -1) == 0); - ok1(jmap_foo_first(map, 0) == 0); - ok1(jmap_foo_last(map, 0) == 0); - ok1(jmap_foo_del(map, 0) == false); + ok1(jmap_test(map, 0) == false); + ok1(jmap_get(map, 0) == (struct foo *)NULL); + ok1(jmap_popcount(map, 0, -1) == 0); + ok1(jmap_first(map) == 0); + ok1(jmap_last(map) == 0); + ok1(jmap_del(map, 0) == false); /* Set only works on existing cases. */ - ok1(jmap_foo_set(map, 0, foo[0]) == false); - ok1(jmap_foo_add(map, 0, foo[1]) == true); - ok1(jmap_foo_get(map, 0) == foo[1]); - ok1(jmap_foo_set(map, 0, foo[0]) == true); - ok1(jmap_foo_get(map, 0) == foo[0]); - - ok1(jmap_foo_test(map, 0) == true); - ok1(jmap_foo_popcount(map, 0, -1) == 1); - ok1(jmap_foo_first(map, -1) == 0); - ok1(jmap_foo_last(map, -1) == 0); - ok1(jmap_foo_next(map, 0, -1) == (size_t)-1); - ok1(jmap_foo_prev(map, 0, -1) == (size_t)-1); - - ok1(jmap_foo_del(map, 0) == true); - ok1(jmap_foo_test(map, 0) == false); - ok1(jmap_foo_popcount(map, 0, -1) == 0); + ok1(jmap_set(map, 1, foo[0]) == false); + ok1(jmap_add(map, 1, foo[1]) == true); + ok1(jmap_get(map, 1) == foo[1]); + ok1(jmap_set(map, 1, foo[0]) == true); + ok1(jmap_get(map, 1) == foo[0]); + + ok1(jmap_test(map, 1) == true); + ok1(jmap_popcount(map, 0, -1) == 1); + ok1(jmap_first(map) == 1); + ok1(jmap_last(map) == 1); + ok1(jmap_next(map, 0) == 1); + ok1(jmap_next(map, 1) == 0); + ok1(jmap_prev(map, 2) == 1); + ok1(jmap_prev(map, 1) == 0); + + ok1(jmap_del(map, 1) == true); + ok1(jmap_test(map, 1) == false); + ok1(jmap_popcount(map, 0, -1) == 0); for (i = 0; i < NUM; i++) - jmap_foo_add(map, i, foo[i]); - - ok1(jmap_foo_popcount(map, 0, -1) == NUM); - ok1(jmap_foo_popcount(map, 0, NUM-1) == NUM); - ok1(jmap_foo_popcount(map, 0, NUM/2-1) == NUM/2); - ok1(jmap_foo_popcount(map, NUM/2, NUM) == NUM - NUM/2); - - ok1(jmap_foo_nth(map, 0, -1) == 0); - ok1(jmap_foo_nth(map, NUM-1, -1) == NUM-1); - ok1(jmap_foo_nth(map, NUM, -1) == (size_t)-1); - ok1(jmap_foo_first(map, -1) == 0); - ok1(jmap_foo_last(map, -1) == NUM-1); - ok1(jmap_foo_next(map, 0, -1) == 1); - ok1(jmap_foo_next(map, NUM-1, -1) == (size_t)-1); - ok1(jmap_foo_prev(map, 1, -1) == 0); - ok1(jmap_foo_prev(map, 0, -1) == (size_t)-1); - - ok1(jmap_foo_get(map, 0) == foo[0]); - ok1(jmap_foo_get(map, NUM-1) == foo[NUM-1]); - ok1(jmap_foo_get(map, NUM) == NULL); + jmap_add(map, i+1, foo[i]); + + ok1(jmap_count(map) == NUM); + ok1(jmap_popcount(map, 0, -1) == NUM); + ok1(jmap_popcount(map, 1, NUM) == NUM); + ok1(jmap_popcount(map, 1, NUM/2) == NUM/2); + ok1(jmap_popcount(map, NUM/2+1, NUM) == NUM - NUM/2); + + ok1(jmap_nth(map, 0, -1) == 1); + ok1(jmap_nth(map, NUM-1, -1) == NUM); + ok1(jmap_nth(map, NUM, -1) == (size_t)-1); + ok1(jmap_first(map) == 1); + ok1(jmap_last(map) == NUM); + ok1(jmap_next(map, 1) == 2); + ok1(jmap_next(map, NUM) == 0); + ok1(jmap_prev(map, 2) == 1); + ok1(jmap_prev(map, 1) == 0); + + ok1(jmap_get(map, 1) == foo[0]); + ok1(jmap_get(map, NUM) == foo[NUM-1]); + ok1(jmap_get(map, NUM+1) == NULL); /* Reverse values in map. */ for (i = 0; i < NUM; i++) { - foop = jmap_foo_getval(map, i); + foop = jmap_getval(map, i+1); ok1(*foop == foo[i]); *foop = foo[NUM-1-i]; - jmap_foo_putval(map, &foop); + jmap_putval(map, &foop); } for (i = 0; i < NUM; i++) - ok1(jmap_foo_get(map, i) == foo[NUM-1-i]); + ok1(jmap_get(map, i+1) == foo[NUM-1-i]); - foop = jmap_foo_nthval(map, 0, &i); - ok1(i == 0); + foop = jmap_nthval(map, 0, &i); + ok1(i == 1); ok1(*foop == foo[NUM-1]); - jmap_foo_putval(map, &foop); - foop = jmap_foo_nthval(map, NUM-1, &i); - ok1(i == NUM-1); + jmap_putval(map, &foop); + foop = jmap_nthval(map, NUM-1, &i); + ok1(i == NUM); ok1(*foop == foo[0]); - jmap_foo_putval(map, &foop); + jmap_putval(map, &foop); - foop = jmap_foo_firstval(map, &i); - ok1(i == 0); + foop = jmap_firstval(map, &i); + ok1(i == 1); ok1(*foop == foo[NUM-1]); - jmap_foo_putval(map, &foop); + jmap_putval(map, &foop); - foop = jmap_foo_nextval(map, &i); - ok1(i == 1); + foop = jmap_nextval(map, &i); + ok1(i == 2); ok1(*foop == foo[NUM-2]); - jmap_foo_putval(map, &foop); + jmap_putval(map, &foop); - foop = jmap_foo_prevval(map, &i); - ok1(i == 0); + foop = jmap_prevval(map, &i); + ok1(i == 1); ok1(*foop == foo[NUM-1]); - jmap_foo_putval(map, &foop); + jmap_putval(map, &foop); - foop = jmap_foo_prevval(map, &i); + foop = jmap_prevval(map, &i); ok1(foop == NULL); - foop = jmap_foo_lastval(map, &i); - ok1(i == NUM-1); + foop = jmap_lastval(map, &i); + ok1(i == NUM); ok1(*foop == foo[0]); - jmap_foo_putval(map, &foop); + jmap_putval(map, &foop); - foop = jmap_foo_prevval(map, &i); - ok1(i == NUM-2); + foop = jmap_prevval(map, &i); + ok1(i == NUM-1); ok1(*foop == foo[1]); - jmap_foo_putval(map, &foop); + jmap_putval(map, &foop); - foop = jmap_foo_nextval(map, &i); - ok1(i == NUM-1); + foop = jmap_nextval(map, &i); + ok1(i == NUM); ok1(*foop == foo[0]); - jmap_foo_putval(map, &foop); + jmap_putval(map, &foop); - foop = jmap_foo_nextval(map, &i); + foop = jmap_nextval(map, &i); ok1(foop == NULL); - ok1(jmap_foo_error(map) == NULL); - jmap_foo_free(map); + ok1(jmap_error(map) == NULL); + jmap_free(map); for (i = 0; i < NUM; i++) free(foo[i]); diff --git a/ccan/jmap/test/run.c b/ccan/jmap/test/run.c index e2c72ae3..3a4249dc 100644 --- a/ccan/jmap/test/run.c +++ b/ccan/jmap/test/run.c @@ -2,111 +2,113 @@ #define CCAN_JMAP_DEBUG #include +struct map { + JMAP_MEMBERS(unsigned long, unsigned long); +}; + int main(int argc, char *argv[]) { - struct jmap *map; + struct map *map; unsigned long i, *value; const char *err; - plan_tests(53); + plan_tests(51); - map = jmap_new(); + map = jmap_new(struct map); ok1(jmap_error(map) == NULL); ok1(jmap_test(map, 0) == false); ok1(jmap_del(map, 0) == false); ok1(jmap_add(map, 0, 1) == true); ok1(jmap_test(map, 0) == true); - ok1(jmap_get(map, 0, -1) == 1); - ok1(jmap_get(map, 1, -1) == (size_t)-1); + ok1(jmap_get(map, 0) == 1); + ok1(jmap_get(map, 1) == 0); ok1(jmap_del(map, 0) == true); ok1(jmap_popcount(map, 0, -1) == 0); ok1(jmap_nth(map, 0, 0) == 0); ok1(jmap_nth(map, 0, -1) == (size_t)-1); - ok1(jmap_first(map, 0) == 0); - ok1(jmap_first(map, -1) == (size_t)-1); - ok1(jmap_last(map, 0) == 0); - ok1(jmap_last(map, -1) == (size_t)-1); + ok1(jmap_first(map) == 0); + ok1(jmap_last(map) == 0); ok1(jmap_getval(map, 0) == NULL); /* Map a million indices, 16 apart. */ for (i = 0; i < 1000000; i++) - jmap_add(map, i << 4, (i << 5) + 1); + jmap_add(map, (i << 4) + 1, (i << 5) + 1); /* This only take 6.3MB on my 32-bit system. */ - diag("%u bytes memory used\n", (unsigned)JudyLMemUsed(map->judy)); + diag("%u bytes memory used\n", (unsigned)JudyLMemUsed(map->raw.judy)); - ok1(jmap_get(map, 0, -1) == 1); - ok1(jmap_get(map, 999999 << 4, -1) == (999999 << 5) + 1); + ok1(jmap_get(map, 1) == 1); + ok1(jmap_get(map, (999999 << 4) + 1) == (999999 << 5) + 1); ok1(jmap_popcount(map, 0, -1) == 1000000); - ok1(jmap_nth(map, 0, -1) == 0); - ok1(jmap_nth(map, 999999, -1) == 999999 << 4); + ok1(jmap_nth(map, 0, -1) == 1); + ok1(jmap_nth(map, 999999, -1) == (999999 << 4) + 1); ok1(jmap_nth(map, 1000000, -1) == (size_t)-1); - ok1(jmap_first(map, -1) == 0); - ok1(jmap_last(map, -1) == 999999 << 4); - ok1(jmap_next(map, 0, -1) == 1 << 4); - ok1(jmap_next(map, 999999 << 4, -1) == (size_t)-1); - ok1(jmap_prev(map, 1, -1) == 0); - ok1(jmap_prev(map, 0, -1) == (size_t)-1); + ok1(jmap_first(map) == 1); + ok1(jmap_last(map) == (999999 << 4) + 1); + ok1(jmap_next(map, 1) == (1 << 4) + 1); + ok1(jmap_next(map, (999999 << 4) + 1) == 0); + ok1(jmap_prev(map, 2) == 1); + ok1(jmap_prev(map, 0) == 0); ok1(jmap_error(map) == NULL); /* Accessors. */ - value = jmap_getval(map, 0); + value = jmap_getval(map, 1); ok1(value && *value == 1); *value = 2; - ok1(jmap_get(map, 0, -1) == 2); + ok1(jmap_get(map, 1) == 2); jmap_putval(map, &value); - ok1(jmap_get(map, 0, -1) == 2); - ok1(jmap_set(map, 0, 1)); + ok1(jmap_get(map, 1) == 2); + ok1(jmap_set(map, 1, 1)); - value = jmap_getval(map, 999999 << 4); + value = jmap_getval(map, (999999 << 4) + 1); ok1(value && *value == (999999 << 5) + 1); jmap_putval(map, &value); value = jmap_nthval(map, 0, &i); - ok1(i == 0); + ok1(i == 1); ok1(value && *value == 1); jmap_putval(map, &value); value = jmap_nthval(map, 999999, &i); - ok1(i == 999999 << 4); + ok1(i == (999999 << 4) + 1); ok1(value && *value == (999999 << 5) + 1); jmap_putval(map, &value); ok1(jmap_nthval(map, 1000000, &i) == NULL); value = jmap_firstval(map, &i); - ok1(i == 0); + ok1(i == 1); ok1(value && *value == 1); jmap_putval(map, &value); ok1(jmap_prevval(map, &i) == NULL); - i = 0; + i = 1; value = jmap_nextval(map, &i); - ok1(i == 1 << 4); + ok1(i == (1 << 4) + 1); ok1(value && *value == (1 << 5) + 1); jmap_putval(map, &value); value = jmap_lastval(map, &i); - ok1(i == 999999 << 4); + ok1(i == (999999 << 4) + 1); ok1(value && *value == (999999 << 5) + 1); jmap_putval(map, &value); ok1(jmap_nextval(map, &i) == NULL); - i = 999999 << 4; + i = (999999 << 4) + 1; value = jmap_prevval(map, &i); - ok1(i == 999998 << 4); + ok1(i == (999998 << 4) + 1); ok1(value && *value == (999998 << 5) + 1); jmap_putval(map, &value); /* Test error handling */ - JU_ERRNO(&map->err) = 100; - JU_ERRID(&map->err) = 991; + JU_ERRNO(&map->raw.err) = 100; + JU_ERRID(&map->raw.err) = 991; err = jmap_error(map); ok1(err); ok1(strstr(err, "100")); ok1(strstr(err, "991")); - ok1(err == map->errstr); + ok1(err == map->raw.errstr); jmap_free(map); return exit_status(); diff --git a/ccan/tcon/tcon.h b/ccan/tcon/tcon.h index 5b38c719..0f6981d9 100644 --- a/ccan/tcon/tcon.h +++ b/ccan/tcon/tcon.h @@ -74,8 +74,10 @@ */ #if HAVE_TYPEOF #define tcon_cast(x, canary, expr) ((__typeof__((x)->_tcon[0].canary))(expr)) +#define tcon_cast_ptr(x, canary, expr) ((__typeof__(&(x)->_tcon[0].canary))(expr)) #else #define tcon_cast(x, canary, expr) ((void *)(expr)) +#define tcon_cast_ptr(x, canary, expr) ((void *)(expr)) #endif #endif /* CCAN_TCON_H */