| 
					
				 | 
			
			
				@@ -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>*. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * 
			 |