map.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. /* Copyright (c) 2003-2004, Roger Dingledine
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2018, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. /**
  6. * \file container.c
  7. * \brief Hash table implementations of a string-to-void* map, and of
  8. * a digest-to-void* map.
  9. **/
  10. #include "lib/container/map.h"
  11. #include "lib/ctime/di_ops.h"
  12. #include "lib/defs/digest_sizes.h"
  13. #include "lib/string/util_string.h"
  14. #include "lib/malloc/util_malloc.h"
  15. #include "lib/log/util_bug.h"
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include "ht.h"
  19. /** Helper: Declare an entry type and a map type to implement a mapping using
  20. * ht.h. The map type will be called <b>maptype</b>. The key part of each
  21. * entry is declared using the C declaration <b>keydecl</b>. All functions
  22. * and types associated with the map get prefixed with <b>prefix</b> */
  23. #define DEFINE_MAP_STRUCTS(maptype, keydecl, prefix) \
  24. typedef struct prefix ## entry_t { \
  25. HT_ENTRY(prefix ## entry_t) node; \
  26. void *val; \
  27. keydecl; \
  28. } prefix ## entry_t; \
  29. struct maptype { \
  30. HT_HEAD(prefix ## impl, prefix ## entry_t) head; \
  31. }
  32. DEFINE_MAP_STRUCTS(strmap_t, char *key, strmap_);
  33. DEFINE_MAP_STRUCTS(digestmap_t, char key[DIGEST_LEN], digestmap_);
  34. DEFINE_MAP_STRUCTS(digest256map_t, uint8_t key[DIGEST256_LEN], digest256map_);
  35. /** Helper: compare strmap_entry_t objects by key value. */
  36. static inline int
  37. strmap_entries_eq(const strmap_entry_t *a, const strmap_entry_t *b)
  38. {
  39. return !strcmp(a->key, b->key);
  40. }
  41. /** Helper: return a hash value for a strmap_entry_t. */
  42. static inline unsigned int
  43. strmap_entry_hash(const strmap_entry_t *a)
  44. {
  45. return (unsigned) siphash24g(a->key, strlen(a->key));
  46. }
  47. /** Helper: compare digestmap_entry_t objects by key value. */
  48. static inline int
  49. digestmap_entries_eq(const digestmap_entry_t *a, const digestmap_entry_t *b)
  50. {
  51. return tor_memeq(a->key, b->key, DIGEST_LEN);
  52. }
  53. /** Helper: return a hash value for a digest_map_t. */
  54. static inline unsigned int
  55. digestmap_entry_hash(const digestmap_entry_t *a)
  56. {
  57. return (unsigned) siphash24g(a->key, DIGEST_LEN);
  58. }
  59. /** Helper: compare digestmap_entry_t objects by key value. */
  60. static inline int
  61. digest256map_entries_eq(const digest256map_entry_t *a,
  62. const digest256map_entry_t *b)
  63. {
  64. return tor_memeq(a->key, b->key, DIGEST256_LEN);
  65. }
  66. /** Helper: return a hash value for a digest_map_t. */
  67. static inline unsigned int
  68. digest256map_entry_hash(const digest256map_entry_t *a)
  69. {
  70. return (unsigned) siphash24g(a->key, DIGEST256_LEN);
  71. }
  72. HT_PROTOTYPE(strmap_impl, strmap_entry_t, node, strmap_entry_hash,
  73. strmap_entries_eq)
  74. HT_GENERATE2(strmap_impl, strmap_entry_t, node, strmap_entry_hash,
  75. strmap_entries_eq, 0.6, tor_reallocarray_, tor_free_)
  76. HT_PROTOTYPE(digestmap_impl, digestmap_entry_t, node, digestmap_entry_hash,
  77. digestmap_entries_eq)
  78. HT_GENERATE2(digestmap_impl, digestmap_entry_t, node, digestmap_entry_hash,
  79. digestmap_entries_eq, 0.6, tor_reallocarray_, tor_free_)
  80. HT_PROTOTYPE(digest256map_impl, digest256map_entry_t, node,
  81. digest256map_entry_hash,
  82. digest256map_entries_eq)
  83. HT_GENERATE2(digest256map_impl, digest256map_entry_t, node,
  84. digest256map_entry_hash,
  85. digest256map_entries_eq, 0.6, tor_reallocarray_, tor_free_)
  86. #define strmap_entry_free(ent) \
  87. FREE_AND_NULL(strmap_entry_t, strmap_entry_free_, (ent))
  88. #define digestmap_entry_free(ent) \
  89. FREE_AND_NULL(digestmap_entry_t, digestmap_entry_free_, (ent))
  90. #define digest256map_entry_free(ent) \
  91. FREE_AND_NULL(digest256map_entry_t, digest256map_entry_free_, (ent))
  92. static inline void
  93. strmap_entry_free_(strmap_entry_t *ent)
  94. {
  95. tor_free(ent->key);
  96. tor_free(ent);
  97. }
  98. static inline void
  99. digestmap_entry_free_(digestmap_entry_t *ent)
  100. {
  101. tor_free(ent);
  102. }
  103. static inline void
  104. digest256map_entry_free_(digest256map_entry_t *ent)
  105. {
  106. tor_free(ent);
  107. }
  108. static inline void
  109. strmap_assign_tmp_key(strmap_entry_t *ent, const char *key)
  110. {
  111. ent->key = (char*)key;
  112. }
  113. static inline void
  114. digestmap_assign_tmp_key(digestmap_entry_t *ent, const char *key)
  115. {
  116. memcpy(ent->key, key, DIGEST_LEN);
  117. }
  118. static inline void
  119. digest256map_assign_tmp_key(digest256map_entry_t *ent, const uint8_t *key)
  120. {
  121. memcpy(ent->key, key, DIGEST256_LEN);
  122. }
  123. static inline void
  124. strmap_assign_key(strmap_entry_t *ent, const char *key)
  125. {
  126. ent->key = tor_strdup(key);
  127. }
  128. static inline void
  129. digestmap_assign_key(digestmap_entry_t *ent, const char *key)
  130. {
  131. memcpy(ent->key, key, DIGEST_LEN);
  132. }
  133. static inline void
  134. digest256map_assign_key(digest256map_entry_t *ent, const uint8_t *key)
  135. {
  136. memcpy(ent->key, key, DIGEST256_LEN);
  137. }
  138. /**
  139. * Macro: implement all the functions for a map that are declared in
  140. * map.h by the DECLARE_MAP_FNS() macro. You must additionally define a
  141. * prefix_entry_free_() function to free entries (and their keys), a
  142. * prefix_assign_tmp_key() function to temporarily set a stack-allocated
  143. * entry to hold a key, and a prefix_assign_key() function to set a
  144. * heap-allocated entry to hold a key.
  145. */
  146. #define IMPLEMENT_MAP_FNS(maptype, keytype, prefix) \
  147. /** Create and return a new empty map. */ \
  148. MOCK_IMPL(maptype *, \
  149. prefix##_new,(void)) \
  150. { \
  151. maptype *result; \
  152. result = tor_malloc(sizeof(maptype)); \
  153. HT_INIT(prefix##_impl, &result->head); \
  154. return result; \
  155. } \
  156. \
  157. /** Return the item from <b>map</b> whose key matches <b>key</b>, or \
  158. * NULL if no such value exists. */ \
  159. void * \
  160. prefix##_get(const maptype *map, const keytype key) \
  161. { \
  162. prefix ##_entry_t *resolve; \
  163. prefix ##_entry_t search; \
  164. tor_assert(map); \
  165. tor_assert(key); \
  166. prefix ##_assign_tmp_key(&search, key); \
  167. resolve = HT_FIND(prefix ##_impl, &map->head, &search); \
  168. if (resolve) { \
  169. return resolve->val; \
  170. } else { \
  171. return NULL; \
  172. } \
  173. } \
  174. \
  175. /** Add an entry to <b>map</b> mapping <b>key</b> to <b>val</b>; \
  176. * return the previous value, or NULL if no such value existed. */ \
  177. void * \
  178. prefix##_set(maptype *map, const keytype key, void *val) \
  179. { \
  180. prefix##_entry_t search; \
  181. void *oldval; \
  182. tor_assert(map); \
  183. tor_assert(key); \
  184. tor_assert(val); \
  185. prefix##_assign_tmp_key(&search, key); \
  186. /* We a lot of our time in this function, so the code below is */ \
  187. /* meant to optimize the check/alloc/set cycle by avoiding the two */\
  188. /* trips to the hash table that we would do in the unoptimized */ \
  189. /* version of this code. (Each of HT_INSERT and HT_FIND calls */ \
  190. /* HT_SET_HASH and HT_FIND_P.) */ \
  191. HT_FIND_OR_INSERT_(prefix##_impl, node, prefix##_entry_hash, \
  192. &(map->head), \
  193. prefix##_entry_t, &search, ptr, \
  194. { \
  195. /* we found an entry. */ \
  196. oldval = (*ptr)->val; \
  197. (*ptr)->val = val; \
  198. return oldval; \
  199. }, \
  200. { \
  201. /* We didn't find the entry. */ \
  202. prefix##_entry_t *newent = \
  203. tor_malloc_zero(sizeof(prefix##_entry_t)); \
  204. prefix##_assign_key(newent, key); \
  205. newent->val = val; \
  206. HT_FOI_INSERT_(node, &(map->head), \
  207. &search, newent, ptr); \
  208. return NULL; \
  209. }); \
  210. } \
  211. \
  212. /** Remove the value currently associated with <b>key</b> from the map. \
  213. * Return the value if one was set, or NULL if there was no entry for \
  214. * <b>key</b>. \
  215. * \
  216. * Note: you must free any storage associated with the returned value. \
  217. */ \
  218. void * \
  219. prefix##_remove(maptype *map, const keytype key) \
  220. { \
  221. prefix##_entry_t *resolve; \
  222. prefix##_entry_t search; \
  223. void *oldval; \
  224. tor_assert(map); \
  225. tor_assert(key); \
  226. prefix##_assign_tmp_key(&search, key); \
  227. resolve = HT_REMOVE(prefix##_impl, &map->head, &search); \
  228. if (resolve) { \
  229. oldval = resolve->val; \
  230. prefix##_entry_free(resolve); \
  231. return oldval; \
  232. } else { \
  233. return NULL; \
  234. } \
  235. } \
  236. \
  237. /** Return the number of elements in <b>map</b>. */ \
  238. int \
  239. prefix##_size(const maptype *map) \
  240. { \
  241. return HT_SIZE(&map->head); \
  242. } \
  243. \
  244. /** Return true iff <b>map</b> has no entries. */ \
  245. int \
  246. prefix##_isempty(const maptype *map) \
  247. { \
  248. return HT_EMPTY(&map->head); \
  249. } \
  250. \
  251. /** Assert that <b>map</b> is not corrupt. */ \
  252. void \
  253. prefix##_assert_ok(const maptype *map) \
  254. { \
  255. tor_assert(!prefix##_impl_HT_REP_IS_BAD_(&map->head)); \
  256. } \
  257. \
  258. /** Remove all entries from <b>map</b>, and deallocate storage for \
  259. * those entries. If free_val is provided, invoked it every value in \
  260. * <b>map</b>. */ \
  261. MOCK_IMPL(void, \
  262. prefix##_free_, (maptype *map, void (*free_val)(void*))) \
  263. { \
  264. prefix##_entry_t **ent, **next, *this; \
  265. if (!map) \
  266. return; \
  267. for (ent = HT_START(prefix##_impl, &map->head); ent != NULL; \
  268. ent = next) { \
  269. this = *ent; \
  270. next = HT_NEXT_RMV(prefix##_impl, &map->head, ent); \
  271. if (free_val) \
  272. free_val(this->val); \
  273. prefix##_entry_free(this); \
  274. } \
  275. tor_assert(HT_EMPTY(&map->head)); \
  276. HT_CLEAR(prefix##_impl, &map->head); \
  277. tor_free(map); \
  278. } \
  279. \
  280. /** return an <b>iterator</b> pointer to the front of a map. \
  281. * \
  282. * Iterator example: \
  283. * \
  284. * \code \
  285. * // uppercase values in "map", removing empty values. \
  286. * \
  287. * strmap_iter_t *iter; \
  288. * const char *key; \
  289. * void *val; \
  290. * char *cp; \
  291. * \
  292. * for (iter = strmap_iter_init(map); !strmap_iter_done(iter); ) { \
  293. * strmap_iter_get(iter, &key, &val); \
  294. * cp = (char*)val; \
  295. * if (!*cp) { \
  296. * iter = strmap_iter_next_rmv(map,iter); \
  297. * free(val); \
  298. * } else { \
  299. * for (;*cp;cp++) *cp = TOR_TOUPPER(*cp); \
  300. */ \
  301. prefix##_iter_t * \
  302. prefix##_iter_init(maptype *map) \
  303. { \
  304. tor_assert(map); \
  305. return HT_START(prefix##_impl, &map->head); \
  306. } \
  307. \
  308. /** Advance <b>iter</b> a single step to the next entry, and return \
  309. * its new value. */ \
  310. prefix##_iter_t * \
  311. prefix##_iter_next(maptype *map, prefix##_iter_t *iter) \
  312. { \
  313. tor_assert(map); \
  314. tor_assert(iter); \
  315. return HT_NEXT(prefix##_impl, &map->head, iter); \
  316. } \
  317. /** Advance <b>iter</b> a single step to the next entry, removing the \
  318. * current entry, and return its new value. */ \
  319. prefix##_iter_t * \
  320. prefix##_iter_next_rmv(maptype *map, prefix##_iter_t *iter) \
  321. { \
  322. prefix##_entry_t *rmv; \
  323. tor_assert(map); \
  324. tor_assert(iter); \
  325. tor_assert(*iter); \
  326. rmv = *iter; \
  327. iter = HT_NEXT_RMV(prefix##_impl, &map->head, iter); \
  328. prefix##_entry_free(rmv); \
  329. return iter; \
  330. } \
  331. /** Set *<b>keyp</b> and *<b>valp</b> to the current entry pointed \
  332. * to by iter. */ \
  333. void \
  334. prefix##_iter_get(prefix##_iter_t *iter, const keytype *keyp, \
  335. void **valp) \
  336. { \
  337. tor_assert(iter); \
  338. tor_assert(*iter); \
  339. tor_assert(keyp); \
  340. tor_assert(valp); \
  341. *keyp = (*iter)->key; \
  342. *valp = (*iter)->val; \
  343. } \
  344. /** Return true iff <b>iter</b> has advanced past the last entry of \
  345. * <b>map</b>. */ \
  346. int \
  347. prefix##_iter_done(prefix##_iter_t *iter) \
  348. { \
  349. return iter == NULL; \
  350. }
  351. IMPLEMENT_MAP_FNS(strmap_t, char *, strmap)
  352. IMPLEMENT_MAP_FNS(digestmap_t, char *, digestmap)
  353. IMPLEMENT_MAP_FNS(digest256map_t, uint8_t *, digest256map)
  354. /** Same as strmap_set, but first converts <b>key</b> to lowercase. */
  355. void *
  356. strmap_set_lc(strmap_t *map, const char *key, void *val)
  357. {
  358. /* We could be a little faster by using strcasecmp instead, and a separate
  359. * type, but I don't think it matters. */
  360. void *v;
  361. char *lc_key = tor_strdup(key);
  362. tor_strlower(lc_key);
  363. v = strmap_set(map,lc_key,val);
  364. tor_free(lc_key);
  365. return v;
  366. }
  367. /** Same as strmap_get, but first converts <b>key</b> to lowercase. */
  368. void *
  369. strmap_get_lc(const strmap_t *map, const char *key)
  370. {
  371. void *v;
  372. char *lc_key = tor_strdup(key);
  373. tor_strlower(lc_key);
  374. v = strmap_get(map,lc_key);
  375. tor_free(lc_key);
  376. return v;
  377. }
  378. /** Same as strmap_remove, but first converts <b>key</b> to lowercase */
  379. void *
  380. strmap_remove_lc(strmap_t *map, const char *key)
  381. {
  382. void *v;
  383. char *lc_key = tor_strdup(key);
  384. tor_strlower(lc_key);
  385. v = strmap_remove(map,lc_key);
  386. tor_free(lc_key);
  387. return v;
  388. }