|
@@ -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_);
|
|
|
|
|
|
|
|
|
static INLINE int
|
|
@@ -1050,6 +1051,21 @@ digestmap_entry_hash(const digestmap_entry_t *a)
|
|
|
return (unsigned) siphash24g(a->key, DIGEST_LEN);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+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);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+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_)
|
|
|
|
|
|
-
|
|
|
- */
|
|
|
-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);
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
- */
|
|
|
-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);
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
- * 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
|
|
|
-
|
|
|
-
|
|
|
-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
|
|
|
-
|
|
|
- * 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,
|
|
|
- {
|
|
|
-
|
|
|
- oldval = (*ptr)->val;
|
|
|
- (*ptr)->val = val;
|
|
|
- return oldval;
|
|
|
- },
|
|
|
- {
|
|
|
-
|
|
|
- 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;
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
- * 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);
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
-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);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- * 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) \
|
|
|
+ \
|
|
|
+ MOCK_IMPL(maptype *, \
|
|
|
+ prefix##_new,(void)) \
|
|
|
+ { \
|
|
|
+ maptype *result; \
|
|
|
+ result = tor_malloc(sizeof(maptype)); \
|
|
|
+ HT_INIT(prefix##_impl, &result->head); \
|
|
|
+ return result; \
|
|
|
+ } \
|
|
|
+ \
|
|
|
+
|
|
|
+ * 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; \
|
|
|
+ } \
|
|
|
+ } \
|
|
|
+ \
|
|
|
+
|
|
|
+ * 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); \
|
|
|
+ \
|
|
|
+ \
|
|
|
+ \
|
|
|
+ \
|
|
|
+ \
|
|
|
+ HT_FIND_OR_INSERT_(prefix##_impl, node, prefix##_entry_hash, \
|
|
|
+ &(map->head), \
|
|
|
+ prefix##_entry_t, &search, ptr, \
|
|
|
+ { \
|
|
|
+ \
|
|
|
+ oldval = (*ptr)->val; \
|
|
|
+ (*ptr)->val = val; \
|
|
|
+ return oldval; \
|
|
|
+ }, \
|
|
|
+ { \
|
|
|
+ \
|
|
|
+ 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; \
|
|
|
+ }); \
|
|
|
+ } \
|
|
|
+ \
|
|
|
+
|
|
|
+ * 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; \
|
|
|
+ } \
|
|
|
+ } \
|
|
|
+ \
|
|
|
+ \
|
|
|
+ int \
|
|
|
+ prefix##_size(const maptype *map) \
|
|
|
+ { \
|
|
|
+ return HT_SIZE(&map->head); \
|
|
|
+ } \
|
|
|
+ \
|
|
|
+ \
|
|
|
+ int \
|
|
|
+ prefix##_isempty(const maptype *map) \
|
|
|
+ { \
|
|
|
+ return HT_EMPTY(&map->head); \
|
|
|
+ } \
|
|
|
+ \
|
|
|
+ \
|
|
|
+ void \
|
|
|
+ prefix##_assert_ok(const maptype *map) \
|
|
|
+ { \
|
|
|
+ tor_assert(!prefix##_impl_HT_REP_IS_BAD_(&map->head)); \
|
|
|
+ } \
|
|
|
+ \
|
|
|
+
|
|
|
+ * 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); \
|
|
|
+ } \
|
|
|
+ \
|
|
|
+
|
|
|
+ * \
|
|
|
+ * Iterator example: \
|
|
|
+ * \
|
|
|
+ * \code \
|
|
|
+ *
|
|
|
+ * \
|
|
|
+ * 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); \
|
|
|
+ } \
|
|
|
+ \
|
|
|
+
|
|
|
+ * 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); \
|
|
|
+ } \
|
|
|
+
|
|
|
+ * 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; \
|
|
|
+ } \
|
|
|
+
|
|
|
+ * 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; \
|
|
|
+ } \
|
|
|
+
|
|
|
+ * <b>map</b>. */ \
|
|
|
+ int \
|
|
|
+ prefix##_iter_done(prefix##_iter_t *iter) \
|
|
|
+ { \
|
|
|
+ return iter == NULL; \
|
|
|
}
|
|
|
-}
|
|
|
|
|
|
-
|
|
|
-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)
|
|
|
|
|
|
|
|
|
void *
|
|
@@ -1287,231 +1387,6 @@ strmap_remove_lc(strmap_t *map, const char *key)
|
|
|
return v;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- *
|
|
|
- * Iterator example:
|
|
|
- *
|
|
|
- * \code
|
|
|
- *
|
|
|
- *
|
|
|
- * 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);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-digestmap_iter_t *
|
|
|
-digestmap_iter_init(digestmap_t *map)
|
|
|
-{
|
|
|
- tor_assert(map);
|
|
|
- return HT_START(digestmap_impl, &map->head);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
- * 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);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
- * 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);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
- * 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;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
- * 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;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
- * 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;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
- * 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;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
- * <b>map</b>. */
|
|
|
-int
|
|
|
-strmap_iter_done(strmap_iter_t *iter)
|
|
|
-{
|
|
|
- return iter == NULL;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
- * <b>map</b>. */
|
|
|
-int
|
|
|
-digestmap_iter_done(digestmap_iter_t *iter)
|
|
|
-{
|
|
|
- return iter == NULL;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
- * 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);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
- * 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);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
- * representation of <b>map</b>. */
|
|
|
-void
|
|
|
-strmap_assert_ok(const strmap_t *map)
|
|
|
-{
|
|
|
- tor_assert(!strmap_impl_HT_REP_IS_BAD_(&map->head));
|
|
|
-}
|
|
|
-
|
|
|
- * representation of <b>map</b>. */
|
|
|
-void
|
|
|
-digestmap_assert_ok(const digestmap_t *map)
|
|
|
-{
|
|
|
- tor_assert(!digestmap_impl_HT_REP_IS_BAD_(&map->head));
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-int
|
|
|
-strmap_isempty(const strmap_t *map)
|
|
|
-{
|
|
|
- return HT_EMPTY(&map->head);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-int
|
|
|
-digestmap_isempty(const digestmap_t *map)
|
|
|
-{
|
|
|
- return HT_EMPTY(&map->head);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-int
|
|
|
-strmap_size(const strmap_t *map)
|
|
|
-{
|
|
|
- return HT_SIZE(&map->head);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-int
|
|
|
-digestmap_size(const digestmap_t *map)
|
|
|
-{
|
|
|
- return HT_SIZE(&map->head);
|
|
|
-}
|
|
|
-
|
|
|
|
|
|
* function for an array of type <b>elt_t</b>*.
|
|
|
*
|