map.c 21 KB

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