[tor-commits] [tor/master] Refactor {str,digest}map into a common implementation; add digest256map

nickm at torproject.org nickm at torproject.org
Fri Oct 31 15:15:49 UTC 2014


commit 542b4701644224bf096599931a61dbae645aa2cd
Author: Nick Mathewson <nickm at torproject.org>
Date:   Fri Oct 31 10:54:12 2014 -0400

    Refactor {str,digest}map into a common implementation; add digest256map
    
    Needed for #13399.
---
 changes/bug13399_part1 |    3 +
 src/common/container.c |  673 ++++++++++++++++++++----------------------------
 src/common/container.h |   10 +
 3 files changed, 287 insertions(+), 399 deletions(-)

diff --git a/changes/bug13399_part1 b/changes/bug13399_part1
new file mode 100644
index 0000000..2ad3f8d
--- /dev/null
+++ b/changes/bug13399_part1
@@ -0,0 +1,3 @@
+  o Code simplifications and refactoring:
+    - Refactor our generic strmap and digestmap types into a single
+      implementation, so that we can add a new digest256map type trivially.
diff --git a/src/common/container.c b/src/common/container.c
index 5997f52..ab4e22d 100644
--- a/src/common/container.c
+++ b/src/common/container.c
@@ -1021,6 +1021,7 @@ smartlist_uniq_digests256(smartlist_t *sl)
 
 DEFINE_MAP_STRUCTS(strmap_t, char *key, strmap_);
 DEFINE_MAP_STRUCTS(digestmap_t, char key[DIGEST_LEN], digestmap_);
+DEFINE_MAP_STRUCTS(digest256map_t, uint8_t key[DIGEST256_LEN], digest256map_);
 
 /** Helper: compare strmap_entry_t objects by key value. */
 static INLINE int
@@ -1050,6 +1051,21 @@ digestmap_entry_hash(const digestmap_entry_t *a)
   return (unsigned) siphash24g(a->key, DIGEST_LEN);
 }
 
+/** Helper: compare digestmap_entry_t objects by key value. */
+static INLINE int
+digest256map_entries_eq(const digest256map_entry_t *a,
+                        const digest256map_entry_t *b)
+{
+  return tor_memeq(a->key, b->key, DIGEST256_LEN);
+}
+
+/** Helper: return a hash value for a digest_map_t. */
+static INLINE unsigned int
+digest256map_entry_hash(const digest256map_entry_t *a)
+{
+  return (unsigned) siphash24g(a->key, DIGEST256_LEN);
+}
+
 HT_PROTOTYPE(strmap_impl, strmap_entry_t, node, strmap_entry_hash,
              strmap_entries_eq)
 HT_GENERATE2(strmap_impl, strmap_entry_t, node, strmap_entry_hash,
@@ -1060,194 +1076,278 @@ HT_PROTOTYPE(digestmap_impl, digestmap_entry_t, node, digestmap_entry_hash,
 HT_GENERATE2(digestmap_impl, digestmap_entry_t, node, digestmap_entry_hash,
              digestmap_entries_eq, 0.6, tor_reallocarray_, tor_free_)
 
-/** Constructor to create a new empty map from strings to void*'s.
- */
-MOCK_IMPL(strmap_t *,
-strmap_new,(void))
+HT_PROTOTYPE(digest256map_impl, digest256map_entry_t, node,
+             digest256map_entry_hash,
+             digest256map_entries_eq)
+HT_GENERATE2(digest256map_impl, digest256map_entry_t, node,
+             digest256map_entry_hash,
+             digest256map_entries_eq, 0.6, tor_reallocarray_, tor_free_)
+
+static INLINE void
+strmap_entry_free(strmap_entry_t *ent)
 {
-  strmap_t *result;
-  result = tor_malloc(sizeof(strmap_t));
-  HT_INIT(strmap_impl, &result->head);
-  return result;
+  tor_free(ent->key);
+  tor_free(ent);
 }
-
-/** Constructor to create a new empty map from digests to void*'s.
- */
-MOCK_IMPL(digestmap_t *,
-digestmap_new,(void))
+static INLINE void
+digestmap_entry_free(digestmap_entry_t *ent)
 {
-  digestmap_t *result;
-  result = tor_malloc(sizeof(digestmap_t));
-  HT_INIT(digestmap_impl, &result->head);
-  return result;
+  tor_free(ent);
 }
-
-/** Set the current value for <b>key</b> to <b>val</b>.  Returns the previous
- * value for <b>key</b> if one was set, or NULL if one was not.
- *
- * This function makes a copy of <b>key</b> if necessary, but not of
- * <b>val</b>.
- */
-void *
-strmap_set(strmap_t *map, const char *key, void *val)
-{
-  strmap_entry_t *resolve;
-  strmap_entry_t search;
-  void *oldval;
-  tor_assert(map);
-  tor_assert(key);
-  tor_assert(val);
-  search.key = (char*)key;
-  resolve = HT_FIND(strmap_impl, &map->head, &search);
-  if (resolve) {
-    oldval = resolve->val;
-    resolve->val = val;
-    return oldval;
-  } else {
-    resolve = tor_malloc_zero(sizeof(strmap_entry_t));
-    resolve->key = tor_strdup(key);
-    resolve->val = val;
-    tor_assert(!HT_FIND(strmap_impl, &map->head, resolve));
-    HT_INSERT(strmap_impl, &map->head, resolve);
-    return NULL;
-  }
+static INLINE void
+digest256map_entry_free(digest256map_entry_t *ent)
+{
+  tor_free(ent);
 }
 
-#define OPTIMIZED_DIGESTMAP_SET
-
-/** Like strmap_set() above but for digestmaps. */
-void *
-digestmap_set(digestmap_t *map, const char *key, void *val)
+static INLINE void
+strmap_assign_tmp_key(strmap_entry_t *ent, const char *key)
 {
-#ifndef OPTIMIZED_DIGESTMAP_SET
-  digestmap_entry_t *resolve;
-#endif
-  digestmap_entry_t search;
-  void *oldval;
-  tor_assert(map);
-  tor_assert(key);
-  tor_assert(val);
-  memcpy(&search.key, key, DIGEST_LEN);
-#ifndef OPTIMIZED_DIGESTMAP_SET
-  resolve = HT_FIND(digestmap_impl, &map->head, &search);
-  if (resolve) {
-    oldval = resolve->val;
-    resolve->val = val;
-    return oldval;
-  } else {
-    resolve = tor_malloc_zero(sizeof(digestmap_entry_t));
-    memcpy(resolve->key, key, DIGEST_LEN);
-    resolve->val = val;
-    HT_INSERT(digestmap_impl, &map->head, resolve);
-    return NULL;
-  }
-#else
-  /* We spend up to 5% of our time in this function, so the code below is
-   * meant to optimize the check/alloc/set cycle by avoiding the two trips to
-   * the hash table that we do in the unoptimized code above.  (Each of
-   * HT_INSERT and HT_FIND calls HT_SET_HASH and HT_FIND_P.)
-   */
-  HT_FIND_OR_INSERT_(digestmap_impl, node, digestmap_entry_hash, &(map->head),
-         digestmap_entry_t, &search, ptr,
-         {
-            /* we found an entry. */
-            oldval = (*ptr)->val;
-            (*ptr)->val = val;
-            return oldval;
-         },
-         {
-           /* We didn't find the entry. */
-           digestmap_entry_t *newent =
-             tor_malloc_zero(sizeof(digestmap_entry_t));
-           memcpy(newent->key, key, DIGEST_LEN);
-           newent->val = val;
-           HT_FOI_INSERT_(node, &(map->head), &search, newent, ptr);
-           return NULL;
-         });
-#endif
+  ent->key = (char*)key;
 }
-
-/** Return the current value associated with <b>key</b>, or NULL if no
- * value is set.
- */
-void *
-strmap_get(const strmap_t *map, const char *key)
-{
-  strmap_entry_t *resolve;
-  strmap_entry_t search;
-  tor_assert(map);
-  tor_assert(key);
-  search.key = (char*)key;
-  resolve = HT_FIND(strmap_impl, &map->head, &search);
-  if (resolve) {
-    return resolve->val;
-  } else {
-    return NULL;
-  }
+static INLINE void
+digestmap_assign_tmp_key(digestmap_entry_t *ent, const char *key)
+{
+  memcpy(ent->key, key, DIGEST_LEN);
 }
-
-/** Like strmap_get() above but for digestmaps. */
-void *
-digestmap_get(const digestmap_t *map, const char *key)
-{
-  digestmap_entry_t *resolve;
-  digestmap_entry_t search;
-  tor_assert(map);
-  tor_assert(key);
-  memcpy(&search.key, key, DIGEST_LEN);
-  resolve = HT_FIND(digestmap_impl, &map->head, &search);
-  if (resolve) {
-    return resolve->val;
-  } else {
-    return NULL;
-  }
+static INLINE void
+digest256map_assign_tmp_key(digest256map_entry_t *ent, const uint8_t *key)
+{
+  memcpy(ent->key, key, DIGEST256_LEN);
+}
+static INLINE void
+strmap_assign_key(strmap_entry_t *ent, const char *key)
+{
+  ent->key = tor_strdup(key);
+}
+static INLINE void
+digestmap_assign_key(digestmap_entry_t *ent, const char *key)
+{
+  memcpy(ent->key, key, DIGEST_LEN);
+}
+static INLINE void
+digest256map_assign_key(digest256map_entry_t *ent, const uint8_t *key)
+{
+  memcpy(ent->key, key, DIGEST256_LEN);
 }
 
-/** Remove the value currently associated with <b>key</b> from the map.
- * Return the value if one was set, or NULL if there was no entry for
- * <b>key</b>.
- *
- * Note: you must free any storage associated with the returned value.
+/**
+ * Macro: implement all the functions for a map that are declared in
+ * container.h by the DECLARE_MAP_FNS() macro.  You must additionally define a
+ * prefix_entry_free_() function to free entries (and their keys), a
+ * prefix_assign_tmp_key() function to temporarily set a stack-allocated
+ * entry to hold a key, and a prefix_assign_key() function to set a
+ * heap-allocated entry to hold a key.
  */
-void *
-strmap_remove(strmap_t *map, const char *key)
-{
-  strmap_entry_t *resolve;
-  strmap_entry_t search;
-  void *oldval;
-  tor_assert(map);
-  tor_assert(key);
-  search.key = (char*)key;
-  resolve = HT_REMOVE(strmap_impl, &map->head, &search);
-  if (resolve) {
-    oldval = resolve->val;
-    tor_free(resolve->key);
-    tor_free(resolve);
-    return oldval;
-  } else {
-    return NULL;
+#define IMPLEMENT_MAP_FNS(maptype, keytype, prefix)                     \
+  /** Create and return a new empty map. */                             \
+  MOCK_IMPL(maptype *,                                                  \
+  prefix##_new,(void))                                                  \
+  {                                                                     \
+    maptype *result;                                                    \
+    result = tor_malloc(sizeof(maptype));                               \
+    HT_INIT(prefix##_impl, &result->head);                              \
+    return result;                                                      \
+  }                                                                     \
+                                                                        \
+  /** Return the item from <b>map</b> whose key matches <b>key</b>, or  \
+   * NULL if no such value exists. */                                   \
+  void *                                                                \
+  prefix##_get(const maptype *map, const keytype key)                   \
+  {                                                                     \
+    prefix ##_entry_t *resolve;                                         \
+    prefix ##_entry_t search;                                           \
+    tor_assert(map);                                                    \
+    tor_assert(key);                                                    \
+    prefix ##_assign_tmp_key(&search, key);                             \
+    resolve = HT_FIND(prefix ##_impl, &map->head, &search);             \
+    if (resolve) {                                                      \
+      return resolve->val;                                              \
+    } else {                                                            \
+      return NULL;                                                      \
+    }                                                                   \
+  }                                                                     \
+                                                                        \
+  /** Add an entry to <b>map</b> mapping <b>key</b> to <b>val</b>;      \
+   * return the previous value, or NULL if no such value existed. */     \
+  void *                                                                \
+  prefix##_set(maptype *map, const keytype key, void *val)              \
+  {                                                                     \
+    prefix##_entry_t search;                                            \
+    void *oldval;                                                       \
+    tor_assert(map);                                                    \
+    tor_assert(key);                                                    \
+    tor_assert(val);                                                    \
+    prefix##_assign_tmp_key(&search, key);                              \
+    /* We a lot of our time in this function, so the code below is */   \
+    /* meant to optimize the check/alloc/set cycle by avoiding the two */\
+    /* trips to the hash table that we would do in the unoptimized */   \
+    /* version of this code. (Each of HT_INSERT and HT_FIND calls */     \
+    /* HT_SET_HASH and HT_FIND_P.) */                                   \
+    HT_FIND_OR_INSERT_(prefix##_impl, node, prefix##_entry_hash,        \
+                       &(map->head),                                    \
+                       prefix##_entry_t, &search, ptr,                  \
+                       {                                                \
+                         /* we found an entry. */                       \
+                         oldval = (*ptr)->val;                          \
+                         (*ptr)->val = val;                             \
+                         return oldval;                                 \
+                       },                                               \
+                       {                                                \
+                         /* We didn't find the entry. */                \
+                         prefix##_entry_t *newent =                     \
+                           tor_malloc_zero(sizeof(prefix##_entry_t));   \
+                         prefix##_assign_key(newent, key);              \
+                         newent->val = val;                             \
+                         HT_FOI_INSERT_(node, &(map->head),             \
+                            &search, newent, ptr);                      \
+                         return NULL;                                   \
+    });                                                                 \
+  }                                                                     \
+                                                                        \
+  /** Remove the value currently associated with <b>key</b> from the map. \
+   * Return the value if one was set, or NULL if there was no entry for \
+   * <b>key</b>.                                                        \
+   *                                                                    \
+   * Note: you must free any storage associated with the returned value. \
+   */                                                                   \
+  void *                                                                \
+  prefix##_remove(maptype *map, const keytype key)                      \
+  {                                                                     \
+    prefix##_entry_t *resolve;                                          \
+    prefix##_entry_t search;                                            \
+    void *oldval;                                                       \
+    tor_assert(map);                                                    \
+    tor_assert(key);                                                    \
+    prefix##_assign_tmp_key(&search, key);                              \
+    resolve = HT_REMOVE(prefix##_impl, &map->head, &search);            \
+    if (resolve) {                                                      \
+      oldval = resolve->val;                                            \
+      prefix##_entry_free(resolve);                                     \
+      return oldval;                                                    \
+    } else {                                                            \
+      return NULL;                                                      \
+    }                                                                   \
+  }                                                                     \
+                                                                        \
+  /** Return the number of elements in <b>map</b>. */                   \
+  int                                                                   \
+  prefix##_size(const maptype *map)                                     \
+  {                                                                     \
+    return HT_SIZE(&map->head);                                         \
+  }                                                                     \
+                                                                        \
+  /** Return true iff <b>map</b> has no entries. */                     \
+  int                                                                   \
+  prefix##_isempty(const maptype *map)                                  \
+  {                                                                     \
+    return HT_EMPTY(&map->head);                                        \
+  }                                                                     \
+                                                                        \
+  /** Assert that <b>map</b> is not corrupt. */                         \
+  void                                                                  \
+  prefix##_assert_ok(const maptype *map)                                \
+  {                                                                     \
+    tor_assert(!prefix##_impl_HT_REP_IS_BAD_(&map->head));              \
+  }                                                                     \
+                                                                        \
+  /** Remove all entries from <b>map</b>, and deallocate storage for    \
+   * those entries.  If free_val is provided, invoked it every value in \
+   * <b>map</b>. */                                                     \
+  MOCK_IMPL(void,                                                       \
+  prefix##_free, (maptype *map, void (*free_val)(void*)))               \
+  {                                                                     \
+    prefix##_entry_t **ent, **next, *this;                              \
+    if (!map)                                                           \
+      return;                                                           \
+    for (ent = HT_START(prefix##_impl, &map->head); ent != NULL;        \
+         ent = next) {                                                  \
+      this = *ent;                                                      \
+      next = HT_NEXT_RMV(prefix##_impl, &map->head, ent);               \
+      if (free_val)                                                     \
+        free_val(this->val);                                            \
+      prefix##_entry_free(this);                                        \
+    }                                                                   \
+    tor_assert(HT_EMPTY(&map->head));                                   \
+    HT_CLEAR(prefix##_impl, &map->head);                                \
+    tor_free(map);                                                      \
+  }                                                                     \
+                                                                        \
+  /** return an <b>iterator</b> pointer to the front of a map.          \
+   *                                                                    \
+   * Iterator example:                                                  \
+   *                                                                    \
+   * \code                                                              \
+   * // uppercase values in "map", removing empty values.               \
+   *                                                                    \
+   * strmap_iter_t *iter;                                               \
+   * const char *key;                                                   \
+   * void *val;                                                         \
+   * char *cp;                                                          \
+   *                                                                    \
+   * for (iter = strmap_iter_init(map); !strmap_iter_done(iter); ) {    \
+   *    strmap_iter_get(iter, &key, &val);                              \
+   *    cp = (char*)val;                                                \
+   *    if (!*cp) {                                                     \
+   *       iter = strmap_iter_next_rmv(map,iter);                       \
+   *       free(val);                                                   \
+   *    } else {                                                        \
+   *       for (;*cp;cp++) *cp = TOR_TOUPPER(*cp);                      \
+   */                                                                   \
+  prefix##_iter_t *                                                     \
+  prefix##_iter_init(maptype *map)                                      \
+  {                                                                     \
+    tor_assert(map);                                                    \
+    return HT_START(prefix##_impl, &map->head);                         \
+  }                                                                     \
+                                                                        \
+  /** Advance <b>iter</b> a single step to the next entry, and return   \
+   * its new value. */                                                  \
+  prefix##_iter_t *                                                     \
+  prefix##_iter_next(maptype *map, prefix##_iter_t *iter)               \
+  {                                                                     \
+    tor_assert(map);                                                    \
+    tor_assert(iter);                                                   \
+    return HT_NEXT(prefix##_impl, &map->head, iter);                    \
+  }                                                                     \
+  /** Advance <b>iter</b> a single step to the next entry, removing the \
+   * current entry, and return its new value. */                        \
+  prefix##_iter_t *                                                     \
+  prefix##_iter_next_rmv(maptype *map, prefix##_iter_t *iter)           \
+  {                                                                     \
+    prefix##_entry_t *rmv;                                              \
+    tor_assert(map);                                                    \
+    tor_assert(iter);                                                   \
+    tor_assert(*iter);                                                  \
+    rmv = *iter;                                                        \
+    iter = HT_NEXT_RMV(prefix##_impl, &map->head, iter);                \
+    prefix##_entry_free(rmv);                                           \
+    return iter;                                                        \
+  }                                                                     \
+  /** Set *<b>keyp</b> and *<b>valp</b> to the current entry pointed    \
+   * to by iter. */                                                     \
+  void                                                                  \
+  prefix##_iter_get(prefix##_iter_t *iter, const keytype *keyp,         \
+                    void **valp)                                        \
+  {                                                                     \
+    tor_assert(iter);                                                   \
+    tor_assert(*iter);                                                  \
+    tor_assert(keyp);                                                   \
+    tor_assert(valp);                                                   \
+    *keyp = (*iter)->key;                                               \
+    *valp = (*iter)->val;                                               \
+  }                                                                     \
+  /** Return true iff <b>iter</b> has advanced past the last entry of   \
+   * <b>map</b>. */                                                     \
+  int                                                                   \
+  prefix##_iter_done(prefix##_iter_t *iter)                             \
+  {                                                                     \
+    return iter == NULL;                                                \
   }
-}
 
-/** Like strmap_remove() above but for digestmaps. */
-void *
-digestmap_remove(digestmap_t *map, const char *key)
-{
-  digestmap_entry_t *resolve;
-  digestmap_entry_t search;
-  void *oldval;
-  tor_assert(map);
-  tor_assert(key);
-  memcpy(&search.key, key, DIGEST_LEN);
-  resolve = HT_REMOVE(digestmap_impl, &map->head, &search);
-  if (resolve) {
-    oldval = resolve->val;
-    tor_free(resolve);
-    return oldval;
-  } else {
-    return NULL;
-  }
-}
+IMPLEMENT_MAP_FNS(strmap_t, char *, strmap)
+IMPLEMENT_MAP_FNS(digestmap_t, char *, digestmap)
+IMPLEMENT_MAP_FNS(digest256map_t, uint8_t *, digest256map)
 
 /** Same as strmap_set, but first converts <b>key</b> to lowercase. */
 void *
@@ -1287,231 +1387,6 @@ strmap_remove_lc(strmap_t *map, const char *key)
   return v;
 }
 
-/** return an <b>iterator</b> pointer to the front of a map.
- *
- * Iterator example:
- *
- * \code
- * // uppercase values in "map", removing empty values.
- *
- * strmap_iter_t *iter;
- * const char *key;
- * void *val;
- * char *cp;
- *
- * for (iter = strmap_iter_init(map); !strmap_iter_done(iter); ) {
- *    strmap_iter_get(iter, &key, &val);
- *    cp = (char*)val;
- *    if (!*cp) {
- *       iter = strmap_iter_next_rmv(map,iter);
- *       free(val);
- *    } else {
- *       for (;*cp;cp++) *cp = TOR_TOUPPER(*cp);
- *       iter = strmap_iter_next(map,iter);
- *    }
- * }
- * \endcode
- *
- */
-strmap_iter_t *
-strmap_iter_init(strmap_t *map)
-{
-  tor_assert(map);
-  return HT_START(strmap_impl, &map->head);
-}
-
-/** Start iterating through <b>map</b>.  See strmap_iter_init() for example. */
-digestmap_iter_t *
-digestmap_iter_init(digestmap_t *map)
-{
-  tor_assert(map);
-  return HT_START(digestmap_impl, &map->head);
-}
-
-/** Advance the iterator <b>iter</b> for <b>map</b> a single step to the next
- * entry, and return its new value. */
-strmap_iter_t *
-strmap_iter_next(strmap_t *map, strmap_iter_t *iter)
-{
-  tor_assert(map);
-  tor_assert(iter);
-  return HT_NEXT(strmap_impl, &map->head, iter);
-}
-
-/** Advance the iterator <b>iter</b> for map a single step to the next entry,
- * and return its new value. */
-digestmap_iter_t *
-digestmap_iter_next(digestmap_t *map, digestmap_iter_t *iter)
-{
-  tor_assert(map);
-  tor_assert(iter);
-  return HT_NEXT(digestmap_impl, &map->head, iter);
-}
-
-/** Advance the iterator <b>iter</b> a single step to the next entry, removing
- * the current entry, and return its new value.
- */
-strmap_iter_t *
-strmap_iter_next_rmv(strmap_t *map, strmap_iter_t *iter)
-{
-  strmap_entry_t *rmv;
-  tor_assert(map);
-  tor_assert(iter);
-  tor_assert(*iter);
-  rmv = *iter;
-  iter = HT_NEXT_RMV(strmap_impl, &map->head, iter);
-  tor_free(rmv->key);
-  tor_free(rmv);
-  return iter;
-}
-
-/** Advance the iterator <b>iter</b> a single step to the next entry, removing
- * the current entry, and return its new value.
- */
-digestmap_iter_t *
-digestmap_iter_next_rmv(digestmap_t *map, digestmap_iter_t *iter)
-{
-  digestmap_entry_t *rmv;
-  tor_assert(map);
-  tor_assert(iter);
-  tor_assert(*iter);
-  rmv = *iter;
-  iter = HT_NEXT_RMV(digestmap_impl, &map->head, iter);
-  tor_free(rmv);
-  return iter;
-}
-
-/** Set *<b>keyp</b> and *<b>valp</b> to the current entry pointed to by
- * iter. */
-void
-strmap_iter_get(strmap_iter_t *iter, const char **keyp, void **valp)
-{
-  tor_assert(iter);
-  tor_assert(*iter);
-  tor_assert(keyp);
-  tor_assert(valp);
-  *keyp = (*iter)->key;
-  *valp = (*iter)->val;
-}
-
-/** Set *<b>keyp</b> and *<b>valp</b> to the current entry pointed to by
- * iter. */
-void
-digestmap_iter_get(digestmap_iter_t *iter, const char **keyp, void **valp)
-{
-  tor_assert(iter);
-  tor_assert(*iter);
-  tor_assert(keyp);
-  tor_assert(valp);
-  *keyp = (*iter)->key;
-  *valp = (*iter)->val;
-}
-
-/** Return true iff <b>iter</b> has advanced past the last entry of
- * <b>map</b>. */
-int
-strmap_iter_done(strmap_iter_t *iter)
-{
-  return iter == NULL;
-}
-
-/** Return true iff <b>iter</b> has advanced past the last entry of
- * <b>map</b>. */
-int
-digestmap_iter_done(digestmap_iter_t *iter)
-{
-  return iter == NULL;
-}
-
-/** Remove all entries from <b>map</b>, and deallocate storage for those
- * entries.  If free_val is provided, it is invoked on every value in
- * <b>map</b>.
- */
-MOCK_IMPL(void,
-strmap_free,(strmap_t *map, void (*free_val)(void*)))
-{
-  strmap_entry_t **ent, **next, *this;
-  if (!map)
-    return;
-
-  for (ent = HT_START(strmap_impl, &map->head); ent != NULL; ent = next) {
-    this = *ent;
-    next = HT_NEXT_RMV(strmap_impl, &map->head, ent);
-    tor_free(this->key);
-    if (free_val)
-      free_val(this->val);
-    tor_free(this);
-  }
-  tor_assert(HT_EMPTY(&map->head));
-  HT_CLEAR(strmap_impl, &map->head);
-  tor_free(map);
-}
-
-/** Remove all entries from <b>map</b>, and deallocate storage for those
- * entries.  If free_val is provided, it is invoked on every value in
- * <b>map</b>.
- */
-MOCK_IMPL(void,
-digestmap_free, (digestmap_t *map, void (*free_val)(void*)))
-{
-  digestmap_entry_t **ent, **next, *this;
-  if (!map)
-    return;
-  for (ent = HT_START(digestmap_impl, &map->head); ent != NULL; ent = next) {
-    this = *ent;
-    next = HT_NEXT_RMV(digestmap_impl, &map->head, ent);
-    if (free_val)
-      free_val(this->val);
-    tor_free(this);
-  }
-  tor_assert(HT_EMPTY(&map->head));
-  HT_CLEAR(digestmap_impl, &map->head);
-  tor_free(map);
-}
-
-/** Fail with an assertion error if anything has gone wrong with the internal
- * representation of <b>map</b>. */
-void
-strmap_assert_ok(const strmap_t *map)
-{
-  tor_assert(!strmap_impl_HT_REP_IS_BAD_(&map->head));
-}
-/** Fail with an assertion error if anything has gone wrong with the internal
- * representation of <b>map</b>. */
-void
-digestmap_assert_ok(const digestmap_t *map)
-{
-  tor_assert(!digestmap_impl_HT_REP_IS_BAD_(&map->head));
-}
-
-/** Return true iff <b>map</b> has no entries. */
-int
-strmap_isempty(const strmap_t *map)
-{
-  return HT_EMPTY(&map->head);
-}
-
-/** Return true iff <b>map</b> has no entries. */
-int
-digestmap_isempty(const digestmap_t *map)
-{
-  return HT_EMPTY(&map->head);
-}
-
-/** Return the number of items in <b>map</b>. */
-int
-strmap_size(const strmap_t *map)
-{
-  return HT_SIZE(&map->head);
-}
-
-/** Return the number of items in <b>map</b>. */
-int
-digestmap_size(const digestmap_t *map)
-{
-  return HT_SIZE(&map->head);
-}
-
 /** Declare a function called <b>funcname</b> that acts as a find_nth_FOO
  * function for an array of type <b>elt_t</b>*.
  *
diff --git a/src/common/container.h b/src/common/container.h
index def3d76..d3d20af 100644
--- a/src/common/container.h
+++ b/src/common/container.h
@@ -346,6 +346,9 @@ char *smartlist_join_strings2(smartlist_t *sl, const char *join,
 DECLARE_MAP_FNS(strmap_t, const char *, strmap_);
 /* Map from const char[DIGEST_LEN] to void *. Implemented with a hash table. */
 DECLARE_MAP_FNS(digestmap_t, const char *, digestmap_);
+/* Map from const uint8_t[DIGEST_LEN] to void *. Implemented with a hash
+ * table. */
+DECLARE_MAP_FNS(digest256map_t, const uint8_t *, digest256map_);
 
 #undef DECLARE_MAP_FNS
 
@@ -461,6 +464,13 @@ DECLARE_MAP_FNS(digestmap_t, const char *, digestmap_);
 /** Used to end a DIGESTMAP_FOREACH() block. */
 #define DIGESTMAP_FOREACH_END MAP_FOREACH_END
 
+#define DIGEST256MAP_FOREACH(map, keyvar, valtype, valvar)               \
+  MAP_FOREACH(digest256map_, map, const uint8_t *, keyvar, valtype, valvar)
+#define DIGEST256MAP_FOREACH_MODIFY(map, keyvar, valtype, valvar)       \
+  MAP_FOREACH_MODIFY(digest256map_, map, const uint8_t *,               \
+                     keyvar, valtype, valvar)
+#define DIGEST256MAP_FOREACH_END MAP_FOREACH_END
+
 #define STRMAP_FOREACH(map, keyvar, valtype, valvar)                 \
   MAP_FOREACH(strmap_, map, const char *, keyvar, valtype, valvar)
 #define STRMAP_FOREACH_MODIFY(map, keyvar, valtype, valvar)          \





More information about the tor-commits mailing list