]> git.ozlabs.org Git - ccan/blobdiff - ccan/jmap/jmap.h
container_of: don't put member_ptr in container_off.
[ccan] / ccan / jmap / jmap.h
index 0b389b6079300fb6872b5ea67889acaf141821dc..e30a6ecef4a4c3e98b4522ce5db5b2b0c6e358ff 100644 (file)
@@ -1,27 +1,65 @@
+/* Licensed under LGPLv2.1+ - see LICENSE file for details */
 #ifndef CCAN_JMAP_H
 #define CCAN_JMAP_H
+#include <ccan/compiler/compiler.h>
+#include <ccan/tcon/tcon.h>
 #include <stddef.h>
 #include <Judy.h>
 #include <stdbool.h>
 #include <string.h>
-#include <ccan/compiler/compiler.h>
 #include <assert.h>
-#ifdef DEBUG
+#ifdef CCAN_JMAP_DEBUG
 #include <stdio.h>
 #endif
 
+/**
+ * struct map - private definition of a jmap.
+ *
+ * It's exposed here so you can put it in your structures and so we can
+ * supply inline functions.
+ */
+struct jmap {
+       Pvoid_t judy;
+       JError_t err;
+       const char *errstr;
+       /* Used if !NDEBUG */
+       int num_accesses;
+       /* Used if CCAN_JMAP_DEBUG */
+       unsigned long *acc_value;
+       unsigned long acc_index;
+       const char *funcname;
+};
+
+/**
+ * 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)
+
 /**
  * jmap_new - create a new, empty jmap.
  *
  * See Also:
- *     JMAP_DEFINE_TYPE()
+ *     JMAP_MEMBERS()
  *
  * Example:
- *     struct jmap *map = jmap_new();
+ *     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");
  */
-struct jmap *jmap_new(void);
+#define jmap_new(type) ((type *)jmap_new_(sizeof(type)))
 
 /**
  * jmap_free - destroy a jmap.
@@ -30,61 +68,7 @@ struct jmap *jmap_new(void);
  * 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;
-       const char *errstr;
-       /* Used if !NDEBUG */
-       int num_accesses;
-       /* Used if DEBUG */
-       unsigned long *acc_value;
-       unsigned long acc_index;
-       const char *funcname;
-};
-const char *COLD_ATTRIBUTE 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 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 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)));
-}
-
-static inline void jmap_debug_access(struct jmap *map)
-{
-#ifdef 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);
-}
+#define jmap_free(map) jmap_free_(&(map)->raw)
 
 /**
  * jmap_error - test for an error in the a previous jmap_ operation.
@@ -98,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.
@@ -124,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.
@@ -149,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.
@@ -174,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.
@@ -186,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.
@@ -228,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.
@@ -258,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.
@@ -376,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.
@@ -414,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.
@@ -461,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);
@@ -471,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.
@@ -493,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.
@@ -511,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.
@@ -533,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,