container.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871
  1. /* Copyright 2003-2004 Roger Dingledine
  2. Copyright 2004-2005 Roger Dingledine, Nick Mathewson */
  3. /* See LICENSE for licensing information */
  4. /* $Id$ */
  5. const char container_c_id[] =
  6. "$Id$";
  7. /**
  8. * \file container.c
  9. * \brief Implements a smartlist (a resizable array) along
  10. * with helper functions to use smartlists. Also includes
  11. * hash table implementations of a string-to-void* map, and of
  12. * a digest-to-void* map.
  13. **/
  14. #include "compat.h"
  15. #include "util.h"
  16. #include "log.h"
  17. #include "container.h"
  18. #include "crypto.h"
  19. #ifdef HAVE_CTYPE_H
  20. #include <ctype.h>
  21. #endif
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <assert.h>
  25. #include "ht.h"
  26. /* All newly allocated smartlists have this capacity.
  27. */
  28. #define SMARTLIST_DEFAULT_CAPACITY 32
  29. /** Allocate and return an empty smartlist.
  30. */
  31. smartlist_t *
  32. smartlist_create(void)
  33. {
  34. smartlist_t *sl = tor_malloc(sizeof(smartlist_t));
  35. sl->num_used = 0;
  36. sl->capacity = SMARTLIST_DEFAULT_CAPACITY;
  37. sl->list = tor_malloc(sizeof(void *) * sl->capacity);
  38. return sl;
  39. }
  40. /** Deallocate a smartlist. Does not release storage associated with the
  41. * list's elements.
  42. */
  43. void
  44. smartlist_free(smartlist_t *sl)
  45. {
  46. tor_free(sl->list);
  47. tor_free(sl);
  48. }
  49. /** Change the capacity of the smartlist to <b>n</b>, so that we can grow
  50. * the list up to <b>n</b> elements with no further reallocation or wasted
  51. * space. If <b>n</b> is less than or equal to the number of elements
  52. * currently in the list, reduce the list's capacity as much as
  53. * possible without losing elements.
  54. */
  55. void
  56. smartlist_set_capacity(smartlist_t *sl, int n)
  57. {
  58. if (n < sl->num_used)
  59. n = sl->num_used;
  60. if (sl->capacity != n) {
  61. sl->capacity = n;
  62. sl->list = tor_realloc(sl->list, sizeof(void*)*sl->capacity);
  63. }
  64. }
  65. /** Remove all elements from the list.
  66. */
  67. void
  68. smartlist_clear(smartlist_t *sl)
  69. {
  70. sl->num_used = 0;
  71. }
  72. /** Append element to the end of the list. */
  73. void
  74. smartlist_add(smartlist_t *sl, void *element)
  75. {
  76. if (sl->num_used >= sl->capacity) {
  77. int higher = sl->capacity * 2;
  78. tor_assert(higher > sl->capacity); /* detect overflow */
  79. sl->capacity = higher;
  80. sl->list = tor_realloc(sl->list, sizeof(void*)*sl->capacity);
  81. }
  82. sl->list[sl->num_used++] = element;
  83. }
  84. /** Append each element from S2 to the end of S1. */
  85. void
  86. smartlist_add_all(smartlist_t *sl, const smartlist_t *s2)
  87. {
  88. int n2 = sl->num_used + s2->num_used;
  89. if (n2 > sl->capacity) {
  90. int higher = sl->capacity * 2;
  91. while (n2 > higher)
  92. higher *= 2;
  93. sl->capacity = higher;
  94. sl->list = tor_realloc(sl->list, sizeof(void*)*sl->capacity);
  95. }
  96. memcpy(sl->list + sl->num_used, s2->list, s2->num_used*sizeof(void*));
  97. sl->num_used += s2->num_used;
  98. }
  99. /** Remove all elements E from sl such that E==element. Preserve
  100. * the order of any elements before E, but elements after E can be
  101. * rearranged.
  102. */
  103. void
  104. smartlist_remove(smartlist_t *sl, const void *element)
  105. {
  106. int i;
  107. if (element == NULL)
  108. return;
  109. for (i=0; i < sl->num_used; i++)
  110. if (sl->list[i] == element) {
  111. sl->list[i] = sl->list[--sl->num_used]; /* swap with the end */
  112. i--; /* so we process the new i'th element */
  113. }
  114. }
  115. /** If there are any strings in sl equal to element, remove and free them.
  116. * Does not preserve order. */
  117. void
  118. smartlist_string_remove(smartlist_t *sl, const char *element)
  119. {
  120. int i;
  121. tor_assert(sl);
  122. tor_assert(element);
  123. for (i = 0; i < sl->num_used; ++i) {
  124. if (!strcmp(element, sl->list[i])) {
  125. tor_free(sl->list[i]);
  126. sl->list[i] = sl->list[--sl->num_used]; /* swap with the end */
  127. i--; /* so we process the new i'th element */
  128. }
  129. }
  130. }
  131. /** Return true iff some element E of sl has E==element.
  132. */
  133. int
  134. smartlist_isin(const smartlist_t *sl, const void *element)
  135. {
  136. int i;
  137. for (i=0; i < sl->num_used; i++)
  138. if (sl->list[i] == element)
  139. return 1;
  140. return 0;
  141. }
  142. /** Return true iff <b>sl</b> has some element E such that
  143. * !strcmp(E,<b>element</b>)
  144. */
  145. int
  146. smartlist_string_isin(const smartlist_t *sl, const char *element)
  147. {
  148. int i;
  149. if (!sl) return 0;
  150. for (i=0; i < sl->num_used; i++)
  151. if (strcmp((const char*)sl->list[i],element)==0)
  152. return 1;
  153. return 0;
  154. }
  155. /** Return true iff <b>sl</b> has some element E such that E is equal
  156. * to the decimal encoding of <b>num</b>.
  157. */
  158. int
  159. smartlist_string_num_isin(const smartlist_t *sl, int num)
  160. {
  161. char buf[16];
  162. tor_snprintf(buf,sizeof(buf),"%d", num);
  163. return smartlist_string_isin(sl, buf);
  164. }
  165. /** Return true iff some element E of sl2 has smartlist_isin(sl1,E).
  166. */
  167. int
  168. smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2)
  169. {
  170. int i;
  171. for (i=0; i < sl2->num_used; i++)
  172. if (smartlist_isin(sl1, sl2->list[i]))
  173. return 1;
  174. return 0;
  175. }
  176. /** Remove every element E of sl1 such that !smartlist_isin(sl2,E).
  177. * Does not preserve the order of sl1.
  178. */
  179. void
  180. smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2)
  181. {
  182. int i;
  183. for (i=0; i < sl1->num_used; i++)
  184. if (!smartlist_isin(sl2, sl1->list[i])) {
  185. sl1->list[i] = sl1->list[--sl1->num_used]; /* swap with the end */
  186. i--; /* so we process the new i'th element */
  187. }
  188. }
  189. /** Remove every element E of sl1 such that smartlist_isin(sl2,E).
  190. * Does not preserve the order of sl1.
  191. */
  192. void
  193. smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2)
  194. {
  195. int i;
  196. for (i=0; i < sl2->num_used; i++)
  197. smartlist_remove(sl1, sl2->list[i]);
  198. }
  199. /** Remove the <b>idx</b>th element of sl; if idx is not the last
  200. * element, swap the last element of sl into the <b>idx</b>th space.
  201. * Return the old value of the <b>idx</b>th element.
  202. */
  203. void
  204. smartlist_del(smartlist_t *sl, int idx)
  205. {
  206. tor_assert(sl);
  207. tor_assert(idx>=0);
  208. tor_assert(idx < sl->num_used);
  209. sl->list[idx] = sl->list[--sl->num_used];
  210. }
  211. /** Remove the <b>idx</b>th element of sl; if idx is not the last element,
  212. * moving all subsequent elements back one space. Return the old value
  213. * of the <b>idx</b>th element.
  214. */
  215. void
  216. smartlist_del_keeporder(smartlist_t *sl, int idx)
  217. {
  218. tor_assert(sl);
  219. tor_assert(idx>=0);
  220. tor_assert(idx < sl->num_used);
  221. --sl->num_used;
  222. if (idx < sl->num_used)
  223. memmove(sl->list+idx, sl->list+idx+1, sizeof(void*)*(sl->num_used-idx));
  224. }
  225. /** Insert the value <b>val</b> as the new <b>idx</b>th element of
  226. * <b>sl</b>, moving all items previously at <b>idx</b> or later
  227. * forward one space.
  228. */
  229. void
  230. smartlist_insert(smartlist_t *sl, int idx, void *val)
  231. {
  232. tor_assert(sl);
  233. tor_assert(idx>=0);
  234. tor_assert(idx <= sl->num_used);
  235. if (idx == sl->num_used) {
  236. smartlist_add(sl, val);
  237. } else {
  238. /* Ensure sufficient capacity */
  239. if (sl->num_used >= sl->capacity) {
  240. sl->capacity *= 2;
  241. sl->list = tor_realloc(sl->list, sizeof(void*)*sl->capacity);
  242. }
  243. /* Move other elements away */
  244. if (idx < sl->num_used)
  245. memmove(sl->list + idx + 1, sl->list + idx,
  246. sizeof(void*)*(sl->num_used-idx));
  247. sl->num_used++;
  248. sl->list[idx] = val;
  249. }
  250. }
  251. /**
  252. * Split a string <b>str</b> along all occurrences of <b>sep</b>,
  253. * adding the split strings, in order, to <b>sl</b>. If
  254. * <b>flags</b>&amp;SPLIT_SKIP_SPACE is true, remove initial and
  255. * trailing space from each entry. If
  256. * <b>flags</b>&amp;SPLIT_IGNORE_BLANK is true, remove any entries of
  257. * length 0. If max>0, divide the string into no more than <b>max</b>
  258. * pieces. If <b>sep</b> is NULL, split on any sequence of horizontal space.
  259. */
  260. int
  261. smartlist_split_string(smartlist_t *sl, const char *str, const char *sep,
  262. int flags, int max)
  263. {
  264. const char *cp, *end, *next;
  265. int n = 0;
  266. tor_assert(sl);
  267. tor_assert(str);
  268. cp = str;
  269. while (1) {
  270. if (flags&SPLIT_SKIP_SPACE) {
  271. while (TOR_ISSPACE(*cp)) ++cp;
  272. }
  273. if (max>0 && n == max-1) {
  274. end = strchr(cp,'\0');
  275. } else if (sep) {
  276. end = strstr(cp,sep);
  277. if (!end)
  278. end = strchr(cp,'\0');
  279. } else {
  280. for (end = cp; *end && *end != '\t' && *end != ' '; ++end)
  281. ;
  282. }
  283. if (!*end) {
  284. next = NULL;
  285. } else if (sep) {
  286. next = end+strlen(sep);
  287. } else {
  288. next = end+1;
  289. while (*next == '\t' || *next == ' ')
  290. ++next;
  291. }
  292. if (flags&SPLIT_SKIP_SPACE) {
  293. while (end > cp && TOR_ISSPACE(*(end-1)))
  294. --end;
  295. }
  296. if (end != cp || !(flags&SPLIT_IGNORE_BLANK)) {
  297. smartlist_add(sl, tor_strndup(cp, end-cp));
  298. ++n;
  299. }
  300. if (!next)
  301. break;
  302. cp = next;
  303. }
  304. return n;
  305. }
  306. /** Allocate and return a new string containing the concatenation of
  307. * the elements of <b>sl</b>, in order, separated by <b>join</b>. If
  308. * <b>terminate</b> is true, also terminate the string with <b>join</b>.
  309. * If <b>len_out</b> is not NULL, set <b>len_out</b> to the length of
  310. * the returned string. Requires that every element of <b>sl</b> is
  311. * NUL-terminated string.
  312. */
  313. char *
  314. smartlist_join_strings(smartlist_t *sl, const char *join,
  315. int terminate, size_t *len_out)
  316. {
  317. return smartlist_join_strings2(sl,join,strlen(join),terminate,len_out);
  318. }
  319. /** As smartlist_join_strings, but instead of separating/terminated with a
  320. * NUL-terminated string <b>join</b>, uses the <b>join_len</b>-byte sequence
  321. * at <b>join</b>. (Useful for generating a sequence of NUL-terminated
  322. * strings.)
  323. */
  324. char *
  325. smartlist_join_strings2(smartlist_t *sl, const char *join,
  326. size_t join_len, int terminate, size_t *len_out)
  327. {
  328. int i;
  329. size_t n = 0;
  330. char *r = NULL, *dst, *src;
  331. tor_assert(sl);
  332. tor_assert(join);
  333. if (terminate)
  334. n = join_len;
  335. for (i = 0; i < sl->num_used; ++i) {
  336. n += strlen(sl->list[i]);
  337. if (i+1 < sl->num_used) /* avoid double-counting the last one */
  338. n += join_len;
  339. }
  340. dst = r = tor_malloc(n+1);
  341. for (i = 0; i < sl->num_used; ) {
  342. for (src = sl->list[i]; *src; )
  343. *dst++ = *src++;
  344. if (++i < sl->num_used) {
  345. memcpy(dst, join, join_len);
  346. dst += join_len;
  347. }
  348. }
  349. if (terminate) {
  350. memcpy(dst, join, join_len);
  351. dst += join_len;
  352. }
  353. *dst = '\0';
  354. if (len_out)
  355. *len_out = dst-r;
  356. return r;
  357. }
  358. /** Sort the members of <b>sl</b> into an order defined by
  359. * the ordering function <b>compare</b>, which returns less then 0 if a
  360. * precedes b, greater than 0 if b precedes a, and 0 if a 'equals' b.
  361. */
  362. void
  363. smartlist_sort(smartlist_t *sl, int (*compare)(const void **a, const void **b))
  364. {
  365. if (!sl->num_used)
  366. return;
  367. qsort(sl->list, sl->num_used, sizeof(void*),
  368. (int (*)(const void *,const void*))compare);
  369. }
  370. /** Assuming the members of <b>sl</b> are in order, return a pointer to the
  371. * member which matches <b>key</b>. Ordering and matching are defined by a
  372. * <b>compare</b> function, which returns 0 on a match; less than 0 if key is
  373. * less than member, and greater than 0 if key is greater then member.
  374. */
  375. void *
  376. smartlist_bsearch(smartlist_t *sl, const void *key,
  377. int (*compare)(const void *key, const void **member))
  378. {
  379. void ** r;
  380. if (!sl->num_used)
  381. return NULL;
  382. r = bsearch(key, sl->list, sl->num_used, sizeof(void*),
  383. (int (*)(const void *, const void *))compare);
  384. return r ? *r : NULL;
  385. }
  386. /** Helper: compare two const char **s. */
  387. static int
  388. _compare_string_ptrs(const void **_a, const void **_b)
  389. {
  390. return strcmp((const char*)*_a, (const char*)*_b);
  391. }
  392. /** Sort a smartlist <b>sl</b> containing strings into lexically ascending
  393. * order. */
  394. void
  395. smartlist_sort_strings(smartlist_t *sl)
  396. {
  397. smartlist_sort(sl, _compare_string_ptrs);
  398. }
  399. #define DEFINE_MAP_STRUCTS(maptype, keydecl, prefix) \
  400. typedef struct prefix ## entry_t { \
  401. HT_ENTRY(prefix ## entry_t) node; \
  402. keydecl; \
  403. void *val; \
  404. } prefix ## entry_t; \
  405. struct maptype { \
  406. HT_HEAD(prefix ## impl, prefix ## entry_t) head; \
  407. };
  408. DEFINE_MAP_STRUCTS(strmap_t, char *key, strmap_);
  409. DEFINE_MAP_STRUCTS(digestmap_t, char key[DIGEST_LEN], digestmap_);
  410. /** Helper: compare strmap_t_entry objects by key value. */
  411. static INLINE int
  412. strmap_entries_eq(strmap_entry_t *a, strmap_entry_t *b)
  413. {
  414. return !strcmp(a->key, b->key);
  415. }
  416. static INLINE unsigned int
  417. strmap_entry_hash(strmap_entry_t *a)
  418. {
  419. return ht_string_hash(a->key);
  420. }
  421. /** Helper: compare digestmap_entry_t objects by key value. */
  422. static INLINE int
  423. digestmap_entries_eq(digestmap_entry_t *a, digestmap_entry_t *b)
  424. {
  425. return !memcmp(a->key, b->key, DIGEST_LEN);
  426. }
  427. static INLINE unsigned int
  428. digestmap_entry_hash(digestmap_entry_t *a)
  429. {
  430. uint32_t *p = (uint32_t*)a->key;
  431. return ht_improve_hash(p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4]);
  432. }
  433. HT_PROTOTYPE(strmap_impl, strmap_entry_t, node, strmap_entry_hash,
  434. strmap_entries_eq);
  435. HT_GENERATE(strmap_impl, strmap_entry_t, node, strmap_entry_hash,
  436. strmap_entries_eq, 0.6, malloc, realloc, free);
  437. HT_PROTOTYPE(digestmap_impl, digestmap_entry_t, node, digestmap_entry_hash,
  438. digestmap_entries_eq);
  439. HT_GENERATE(digestmap_impl, digestmap_entry_t, node, digestmap_entry_hash,
  440. digestmap_entries_eq, 0.6, malloc, realloc, free);
  441. /** Constructor to create a new empty map from strings to void*'s.
  442. */
  443. strmap_t *
  444. strmap_new(void)
  445. {
  446. strmap_t *result;
  447. result = tor_malloc(sizeof(strmap_t));
  448. HT_INIT(&result->head);
  449. return result;
  450. }
  451. /** Constructor to create a new empty map from digests to void*'s.
  452. */
  453. digestmap_t *
  454. digestmap_new(void)
  455. {
  456. digestmap_t *result;
  457. result = tor_malloc(sizeof(digestmap_t));
  458. HT_INIT(&result->head);
  459. return result;
  460. }
  461. /** Set the current value for <b>key</b> to <b>val</b>. Returns the previous
  462. * value for <b>key</b> if one was set, or NULL if one was not.
  463. *
  464. * This function makes a copy of <b>key</b> if necessary, but not of
  465. * <b>val</b>.
  466. */
  467. void *
  468. strmap_set(strmap_t *map, const char *key, void *val)
  469. {
  470. strmap_entry_t *resolve;
  471. strmap_entry_t search;
  472. void *oldval;
  473. tor_assert(map);
  474. tor_assert(key);
  475. tor_assert(val);
  476. search.key = (char*)key;
  477. resolve = HT_FIND(strmap_impl, &map->head, &search);
  478. if (resolve) {
  479. oldval = resolve->val;
  480. resolve->val = val;
  481. return oldval;
  482. } else {
  483. resolve = tor_malloc_zero(sizeof(strmap_entry_t));
  484. resolve->key = tor_strdup(key);
  485. resolve->val = val;
  486. tor_assert(!HT_FIND(strmap_impl, &map->head, resolve));
  487. HT_INSERT(strmap_impl, &map->head, resolve);
  488. return NULL;
  489. }
  490. }
  491. /** Like strmap_set() above but for digestmaps. */
  492. void *
  493. digestmap_set(digestmap_t *map, const char *key, void *val)
  494. {
  495. digestmap_entry_t *resolve;
  496. digestmap_entry_t search;
  497. void *oldval;
  498. tor_assert(map);
  499. tor_assert(key);
  500. tor_assert(val);
  501. memcpy(&search.key, key, DIGEST_LEN);
  502. resolve = HT_FIND(digestmap_impl, &map->head, &search);
  503. if (resolve) {
  504. oldval = resolve->val;
  505. resolve->val = val;
  506. return oldval;
  507. } else {
  508. resolve = tor_malloc_zero(sizeof(digestmap_entry_t));
  509. memcpy(resolve->key, key, DIGEST_LEN);
  510. resolve->val = val;
  511. HT_INSERT(digestmap_impl, &map->head, resolve);
  512. return NULL;
  513. }
  514. }
  515. /** Return the current value associated with <b>key</b>, or NULL if no
  516. * value is set.
  517. */
  518. void *
  519. strmap_get(strmap_t *map, const char *key)
  520. {
  521. strmap_entry_t *resolve;
  522. strmap_entry_t search;
  523. tor_assert(map);
  524. tor_assert(key);
  525. search.key = (char*)key;
  526. resolve = HT_FIND(strmap_impl, &map->head, &search);
  527. if (resolve) {
  528. return resolve->val;
  529. } else {
  530. return NULL;
  531. }
  532. }
  533. /** Like strmap_get() above but for digestmaps. */
  534. void *
  535. digestmap_get(digestmap_t *map, const char *key)
  536. {
  537. digestmap_entry_t *resolve;
  538. digestmap_entry_t search;
  539. tor_assert(map);
  540. tor_assert(key);
  541. memcpy(&search.key, key, DIGEST_LEN);
  542. resolve = HT_FIND(digestmap_impl, &map->head, &search);
  543. if (resolve) {
  544. return resolve->val;
  545. } else {
  546. return NULL;
  547. }
  548. }
  549. /** Remove the value currently associated with <b>key</b> from the map.
  550. * Return the value if one was set, or NULL if there was no entry for
  551. * <b>key</b>.
  552. *
  553. * Note: you must free any storage associated with the returned value.
  554. */
  555. void *
  556. strmap_remove(strmap_t *map, const char *key)
  557. {
  558. strmap_entry_t *resolve;
  559. strmap_entry_t search;
  560. void *oldval;
  561. tor_assert(map);
  562. tor_assert(key);
  563. search.key = (char*)key;
  564. resolve = HT_REMOVE(strmap_impl, &map->head, &search);
  565. if (resolve) {
  566. oldval = resolve->val;
  567. tor_free(resolve->key);
  568. tor_free(resolve);
  569. return oldval;
  570. } else {
  571. return NULL;
  572. }
  573. }
  574. /** Like strmap_remove() above but for digestmaps. */
  575. void *
  576. digestmap_remove(digestmap_t *map, const char *key)
  577. {
  578. digestmap_entry_t *resolve;
  579. digestmap_entry_t search;
  580. void *oldval;
  581. tor_assert(map);
  582. tor_assert(key);
  583. memcpy(&search.key, key, DIGEST_LEN);
  584. resolve = HT_REMOVE(digestmap_impl, &map->head, &search);
  585. if (resolve) {
  586. oldval = resolve->val;
  587. tor_free(resolve);
  588. return oldval;
  589. } else {
  590. return NULL;
  591. }
  592. }
  593. /** Same as strmap_set, but first converts <b>key</b> to lowercase. */
  594. void *
  595. strmap_set_lc(strmap_t *map, const char *key, void *val)
  596. {
  597. /* We could be a little faster by using strcasecmp instead, and a separate
  598. * type, but I don't think it matters. */
  599. void *v;
  600. char *lc_key = tor_strdup(key);
  601. tor_strlower(lc_key);
  602. v = strmap_set(map,lc_key,val);
  603. tor_free(lc_key);
  604. return v;
  605. }
  606. /** Same as strmap_get, but first converts <b>key</b> to lowercase. */
  607. void *
  608. strmap_get_lc(strmap_t *map, const char *key)
  609. {
  610. void *v;
  611. char *lc_key = tor_strdup(key);
  612. tor_strlower(lc_key);
  613. v = strmap_get(map,lc_key);
  614. tor_free(lc_key);
  615. return v;
  616. }
  617. /** Same as strmap_remove, but first converts <b>key</b> to lowercase */
  618. void *
  619. strmap_remove_lc(strmap_t *map, const char *key)
  620. {
  621. void *v;
  622. char *lc_key = tor_strdup(key);
  623. tor_strlower(lc_key);
  624. v = strmap_remove(map,lc_key);
  625. tor_free(lc_key);
  626. return v;
  627. }
  628. /** return an <b>iterator</b> pointer to the front of a map.
  629. *
  630. * Iterator example:
  631. *
  632. * \code
  633. * // uppercase values in "map", removing empty values.
  634. *
  635. * strmap_iter_t *iter;
  636. * const char *key;
  637. * void *val;
  638. * char *cp;
  639. *
  640. * for (iter = strmap_iter_init(map); !strmap_iter_done(iter); ) {
  641. * strmap_iter_get(iter, &key, &val);
  642. * cp = (char*)val;
  643. * if (!*cp) {
  644. * iter = strmap_iter_next_rmv(iter);
  645. * free(val);
  646. * } else {
  647. * for (;*cp;cp++) *cp = toupper(*cp);
  648. * iter = strmap_iter_next(iter);
  649. * }
  650. * }
  651. * \endcode
  652. *
  653. */
  654. strmap_iter_t *
  655. strmap_iter_init(strmap_t *map)
  656. {
  657. tor_assert(map);
  658. return HT_START(strmap_impl, &map->head);
  659. }
  660. digestmap_iter_t *
  661. digestmap_iter_init(digestmap_t *map)
  662. {
  663. tor_assert(map);
  664. return HT_START(digestmap_impl, &map->head);
  665. }
  666. /** Advance the iterator <b>iter</b> for map a single step to the next entry.
  667. */
  668. strmap_iter_t *
  669. strmap_iter_next(strmap_t *map, strmap_iter_t *iter)
  670. {
  671. tor_assert(map);
  672. tor_assert(iter);
  673. return HT_NEXT(strmap_impl, &map->head, iter);
  674. }
  675. digestmap_iter_t *
  676. digestmap_iter_next(digestmap_t *map, digestmap_iter_t *iter)
  677. {
  678. tor_assert(map);
  679. tor_assert(iter);
  680. return HT_NEXT(digestmap_impl, &map->head, iter);
  681. }
  682. /** Advance the iterator <b>iter</b> a single step to the next entry, removing
  683. * the current entry.
  684. */
  685. strmap_iter_t *
  686. strmap_iter_next_rmv(strmap_t *map, strmap_iter_t *iter)
  687. {
  688. strmap_entry_t *rmv;
  689. tor_assert(map);
  690. tor_assert(iter);
  691. tor_assert(*iter);
  692. rmv = *iter;
  693. iter = HT_NEXT_RMV(strmap_impl, &map->head, iter);
  694. tor_free(rmv->key);
  695. tor_free(rmv);
  696. return iter;
  697. }
  698. digestmap_iter_t *
  699. digestmap_iter_next_rmv(digestmap_t *map, digestmap_iter_t *iter)
  700. {
  701. digestmap_entry_t *rmv;
  702. tor_assert(map);
  703. tor_assert(iter);
  704. tor_assert(*iter);
  705. rmv = *iter;
  706. iter = HT_NEXT_RMV(digestmap_impl, &map->head, iter);
  707. tor_free(rmv);
  708. return iter;
  709. }
  710. /** Set *keyp and *valp to the current entry pointed to by iter.
  711. */
  712. void
  713. strmap_iter_get(strmap_iter_t *iter, const char **keyp, void **valp)
  714. {
  715. tor_assert(iter);
  716. tor_assert(*iter);
  717. tor_assert(keyp);
  718. tor_assert(valp);
  719. *keyp = (*iter)->key;
  720. *valp = (*iter)->val;
  721. }
  722. void
  723. digestmap_iter_get(digestmap_iter_t *iter, const char **keyp, void **valp)
  724. {
  725. tor_assert(iter);
  726. tor_assert(*iter);
  727. tor_assert(keyp);
  728. tor_assert(valp);
  729. *keyp = (*iter)->key;
  730. *valp = (*iter)->val;
  731. }
  732. /** Return true iff iter has advanced past the last entry of map.
  733. */
  734. int
  735. strmap_iter_done(strmap_iter_t *iter)
  736. {
  737. return iter == NULL;
  738. }
  739. int
  740. digestmap_iter_done(digestmap_iter_t *iter)
  741. {
  742. return iter == NULL;
  743. }
  744. /** Remove all entries from <b>map</b>, and deallocate storage for those
  745. * entries. If free_val is provided, it is invoked on every value in
  746. * <b>map</b>.
  747. */
  748. void
  749. strmap_free(strmap_t *map, void (*free_val)(void*))
  750. {
  751. strmap_entry_t **ent, **next, *this;
  752. for (ent = HT_START(strmap_impl, &map->head); ent != NULL; ent = next) {
  753. this = *ent;
  754. next = HT_NEXT_RMV(strmap_impl, &map->head, ent);
  755. tor_free(this->key);
  756. if (free_val)
  757. free_val(this->val);
  758. tor_free(this);
  759. }
  760. tor_assert(HT_EMPTY(&map->head));
  761. HT_CLEAR(strmap_impl, &map->head);
  762. tor_free(map);
  763. }
  764. void
  765. digestmap_free(digestmap_t *map, void (*free_val)(void*))
  766. {
  767. digestmap_entry_t **ent, **next, *this;
  768. for (ent = HT_START(digestmap_impl, &map->head); ent != NULL; ent = next) {
  769. this = *ent;
  770. next = HT_NEXT_RMV(digestmap_impl, &map->head, ent);
  771. if (free_val)
  772. free_val(this->val);
  773. tor_free(this);
  774. }
  775. tor_assert(HT_EMPTY(&map->head));
  776. HT_CLEAR(digestmap_impl, &map->head);
  777. tor_free(map);
  778. }
  779. /** Return true iff <b>map</b> has no entries. */
  780. int
  781. strmap_isempty(strmap_t *map)
  782. {
  783. return HT_EMPTY(&map->head);
  784. }
  785. int
  786. digestmap_isempty(digestmap_t *map)
  787. {
  788. return HT_EMPTY(&map->head);
  789. }
  790. int
  791. strmap_size(strmap_t *map)
  792. {
  793. return HT_SIZE(&map->head);
  794. }
  795. int
  796. digestmap_size(digestmap_t *map)
  797. {
  798. return HT_SIZE(&map->head);
  799. }