hashset.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. #include "precompile.h"
  2. #include "memutil.h"
  3. #include "hashset.h"
  4. #include "list.h"
  5. #include "hash.h"
  6. #include "dbgutil.h"
  7. #include <winpr/string.h>
  8. /* double hash , same with .netframework hashtable */
  9. // Table of prime numbers to use as hash table sizes.
  10. // The entry used for capacity is the smallest prime number in this aaray
  11. // that is larger than twice the previous capacity.
  12. /* Integer square root by Halleck's method, with Legalize's speedup */
  13. static int isqrt (int x)
  14. {
  15. int squaredbit, remainder, root;
  16. if (x<1) return 0;
  17. /* Load the binary constant 01 00 00 ... 00, where the number
  18. * of zero bits to the right of the single one bit
  19. * is even, and the one bit is as far left as is consistant
  20. * with that condition.)
  21. */
  22. squaredbit = (int) ((((unsigned int) ~0L) >> 1) &
  23. ~(((unsigned int) ~0L) >> 2));
  24. /* This portable load replaces the loop that used to be
  25. * here, and was donated by legalize@xmission.com
  26. */
  27. /* Form bits of the answer. */
  28. remainder = x; root = 0;
  29. while (squaredbit > 0) {
  30. if (remainder >= (squaredbit | root)) {
  31. remainder -= (squaredbit | root);
  32. root >>= 1; root |= squaredbit;
  33. } else {
  34. root >>= 1;
  35. }
  36. squaredbit >>= 2;
  37. }
  38. return root;
  39. }
  40. static int is_prime(int candidate)
  41. {
  42. if ((candidate & 1) != 0)
  43. {
  44. int divisor = 3;
  45. int limit = isqrt(candidate);
  46. while (divisor <= limit) {
  47. if ((candidate % divisor) == 0)
  48. return 0;
  49. divisor+=2;
  50. }
  51. }
  52. return candidate == 2;
  53. }
  54. TOOLKIT_API int hash_get_prime(int min)
  55. {
  56. const int primes[] = {
  57. 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919,
  58. 1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591,
  59. 17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437,
  60. 187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263,
  61. 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369
  62. };
  63. int i;
  64. TOOLKIT_ASSERT(min >= 0);
  65. for (i = 0; i < sizeof(primes) / sizeof(int); ++i) {
  66. int prime = primes[i];
  67. if (prime >= min) return prime;
  68. }
  69. //outside of our predefined table.
  70. //compute the hard way.
  71. for (i = (min | 1); i < INT_MAX;i+=2)
  72. {
  73. if (is_prime(i))
  74. return i;
  75. }
  76. return min;
  77. }
  78. TOOLKIT_API hashset_t *hashset_create(int node_offset,
  79. hashset_getkey getkey_fn,
  80. hashset_hash hash_fn,
  81. hashset_cmpkey cmp_fn)
  82. {
  83. return hashset_create2(0, 1.0, node_offset, getkey_fn, hash_fn, cmp_fn);
  84. }
  85. TOOLKIT_API hashset_t *hashset_create2(int init_size,
  86. float load_factor,
  87. int node_offset,
  88. hashset_getkey getkey_fn,
  89. hashset_hash hash_fn,
  90. hashset_cmpkey cmp_fn)
  91. {
  92. hashset_t *hs;
  93. TOOLKIT_ASSERT(node_offset >= 0);
  94. TOOLKIT_ASSERT(load_factor > 0.0f && load_factor <= 1.0f);
  95. TOOLKIT_ASSERT(getkey_fn);
  96. TOOLKIT_ASSERT(hash_fn);
  97. TOOLKIT_ASSERT(cmp_fn);
  98. hs = MALLOC_T(hashset_t);
  99. init_size = hash_get_prime(init_size <= 0 ? HASH_DEFAULT_INIT_HASH_SIZE : init_size);
  100. hs->buckets = ZALLOC(init_size*sizeof(struct hlist_head));
  101. if (!hs->buckets)
  102. return NULL;
  103. hs->size = init_size;
  104. hs->node_offset = node_offset;
  105. hs->load_factor = load_factor * HASH_DEFAULT_LOAD_FACTOR;
  106. hs->count = 0;
  107. hs->cmp_fn = cmp_fn;
  108. hs->getkey_fn = getkey_fn;
  109. hs->hash_fn = hash_fn;
  110. hs->default_iterator.ht = hs;
  111. hashset_iterator_reset(&hs->default_iterator);
  112. return hs;
  113. }
  114. static int hashset_check_expand(hashset_t *ht)
  115. {
  116. if ((ht->count+1)/(float)ht->size > ht->load_factor) { /* expand */
  117. int i;
  118. int new_size = hash_get_prime(ht->size * 2);
  119. struct hlist_head *new_buckets = (struct hlist_head *)ZALLOC(new_size*sizeof(struct hlist_head));
  120. if (!new_buckets)
  121. return -1;
  122. for (i = 0; i < ht->size; ++i) {
  123. struct hlist_node *n = ht->buckets[i].first;
  124. struct hlist_node *nn = n ? n->next : NULL;
  125. while (n) {
  126. void *o = ((char*)(n) + ht->node_offset);
  127. unsigned int new_slot = ht->hash_fn(ht->getkey_fn(o)) % new_size;
  128. hlist_del(n);
  129. hlist_add_head(n, &new_buckets[new_slot]);
  130. n = nn;
  131. nn = n ? n->next : NULL;
  132. }
  133. }
  134. free(ht->buckets);
  135. ht->buckets = new_buckets;
  136. ht->size = new_size;
  137. }
  138. return 0;
  139. }
  140. TOOLKIT_API void* hashset_find(hashset_t *ht, const void *key)
  141. {
  142. unsigned int slot;
  143. TOOLKIT_ASSERT(ht);
  144. slot = ht->hash_fn(key) % ht->size;
  145. if (ht->buckets[slot].first) {
  146. struct hlist_node *n = ht->buckets[slot].first;
  147. while (n) {
  148. void *o = ((char*)(n) - ht->node_offset);
  149. if (ht->cmp_fn(ht->getkey_fn(o), key) == 0)
  150. return o;
  151. n = n->next;
  152. }
  153. }
  154. return NULL;
  155. }
  156. TOOLKIT_API int hashset_add(hashset_t *ht, void *obj)
  157. {
  158. unsigned int slot;
  159. TOOLKIT_ASSERT(ht);
  160. TOOLKIT_ASSERT(obj);
  161. if (hashset_find(ht, ht->getkey_fn(obj)))
  162. return -1; /* already exist */
  163. if (hashset_check_expand(ht) != 0)
  164. return -1;
  165. slot = ht->hash_fn(ht->getkey_fn(obj)) % ht->size;
  166. hlist_add_head((struct hlist_node*)((char*)obj+ht->node_offset), &ht->buckets[slot]);
  167. ht->count++;
  168. return 0;
  169. }
  170. TOOLKIT_API int hashset_count(hashset_t *ht)
  171. {
  172. TOOLKIT_ASSERT(ht);
  173. return ht->count;
  174. }
  175. TOOLKIT_API void* hashset_remove(hashset_t *ht, const void *key)
  176. {
  177. void *obj;
  178. TOOLKIT_ASSERT(ht);
  179. //TOOLKIT_ASSERT(key);
  180. obj = hashset_find(ht, key);
  181. if (obj) {
  182. struct hlist_node *n = (struct hlist_node *)((char*)obj + ht->node_offset);
  183. hlist_del(n);
  184. ht->count--;
  185. }
  186. return obj;
  187. }
  188. TOOLKIT_API void hashset_destroy(hashset_t *ht)
  189. {
  190. TOOLKIT_ASSERT(ht);
  191. TOOLKIT_ASSERT(ht->count == 0);
  192. free(ht->buckets);
  193. free(ht);
  194. }
  195. TOOLKIT_API hashset_iterator *hashset_default_iterator(hashset_t *ht)
  196. {
  197. return hashset_iterator_reset(&ht->default_iterator);
  198. }
  199. TOOLKIT_API hashset_iterator *hashset_iteraor_create(hashset_t *ht)
  200. {
  201. hashset_iterator *iter;
  202. TOOLKIT_ASSERT(ht);
  203. iter = MALLOC_T(hashset_iterator);
  204. iter->ht = ht;
  205. iter->slot = -1;
  206. iter->pos = NULL;
  207. iter->pos_next = NULL;
  208. return iter;
  209. }
  210. TOOLKIT_API void hashset_iterator_destroy(hashset_iterator *iter)
  211. {
  212. TOOLKIT_ASSERT(iter);
  213. free(iter);
  214. }
  215. TOOLKIT_API int hashset_iterator_next(hashset_iterator *iter)
  216. {
  217. hashset_t *ht;
  218. TOOLKIT_ASSERT(iter);
  219. ht = iter->ht;
  220. if (iter->slot == -1) {
  221. while (++iter->slot < ht->size) {
  222. if (!hlist_empty(&ht->buckets[iter->slot])) {
  223. iter->pos = ht->buckets[iter->slot].first;
  224. iter->pos_next = iter->pos->next;
  225. return 0;
  226. }
  227. }
  228. } else {
  229. iter->pos = iter->pos_next;
  230. if (iter->pos == NULL) {
  231. while (iter->slot < ht->size) {
  232. if (iter->pos && iter->pos->next) {
  233. iter->pos = iter->pos->next;
  234. iter->pos_next = iter->pos->next;
  235. return 0;
  236. } else {
  237. ++iter->slot;
  238. if (iter->slot >= ht->size)
  239. break;
  240. iter->pos = ht->buckets[iter->slot].first;
  241. if (iter->pos) {
  242. iter->pos_next = iter->pos->next;
  243. return 0;
  244. }
  245. }
  246. }
  247. } else {
  248. iter->pos_next = iter->pos->next;
  249. return 0;
  250. }
  251. }
  252. return -1;
  253. }
  254. TOOLKIT_API void *hashset_iterator_get_object(hashset_iterator *iter)
  255. {
  256. hashset_t *ht;
  257. TOOLKIT_ASSERT(iter);
  258. ht = iter->ht;
  259. return (void*)((char*)iter->pos - ht->node_offset);
  260. }
  261. TOOLKIT_API hashset_iterator * hashset_iterator_reset(hashset_iterator *iter)
  262. {
  263. TOOLKIT_ASSERT(iter);
  264. iter->pos = iter->pos_next = NULL;
  265. iter->slot = -1;
  266. return iter;
  267. }
  268. /* map */
  269. #define DEFAULT_MAP_SIZE 15
  270. struct stringmap_kv_pair {
  271. struct hlist_node hnode;
  272. char *key;
  273. void *value;
  274. unsigned int h;
  275. };
  276. struct stringmap_iterator {
  277. stringmap_t *map;
  278. int slot;
  279. struct hlist_node *pos, *pos_next;
  280. };
  281. struct stringmap_t {
  282. struct hlist_head *buckets;
  283. int count;
  284. int size;
  285. stringmap_iterator default_iterator;
  286. };
  287. TOOLKIT_API const char* stringmap_kv_pair_get_key(stringmap_kv_pair *kv)
  288. {
  289. TOOLKIT_ASSERT(kv);
  290. return kv->key;
  291. }
  292. TOOLKIT_API void *stringmap_kv_pair_get_value(stringmap_kv_pair *kv)
  293. {
  294. TOOLKIT_ASSERT(kv);
  295. return kv->value;
  296. }
  297. TOOLKIT_API void *stringmap_kv_pair_set_value(stringmap_kv_pair *kv, void *newval)
  298. {
  299. void *old;
  300. TOOLKIT_ASSERT(kv);
  301. old = kv->value;
  302. kv->value = newval;
  303. return old;
  304. }
  305. TOOLKIT_API stringmap_t *stringmap_create(int init_size)
  306. {
  307. stringmap_t *map;
  308. if (init_size <= 0) {
  309. init_size = DEFAULT_MAP_SIZE;
  310. } else {
  311. int i = DEFAULT_MAP_SIZE;
  312. while (init_size > i)
  313. i = i * 2 + 1;
  314. init_size = i;
  315. }
  316. map = MALLOC_T(stringmap_t);
  317. map->count = 0;
  318. map->size = init_size;
  319. map->default_iterator.map = map;
  320. stringmap_iterator_reset(&map->default_iterator);
  321. map->buckets = (struct hlist_head*)ZALLOC(sizeof(struct hlist_head)*init_size);
  322. return map;
  323. }
  324. TOOLKIT_API void stringmap_destroy(stringmap_t *map)
  325. {
  326. TOOLKIT_ASSERT(map);
  327. if (map->count) {
  328. TOOLKIT_ASSERT(0);
  329. }
  330. TOOLKIT_ASSERT(map->count == 0);
  331. free(map->buckets);
  332. free(map);
  333. }
  334. // bool
  335. TOOLKIT_API stringmap_kv_pair *stringmap_find(stringmap_t *map, const char *key)
  336. {
  337. unsigned int slot, h;
  338. stringmap_kv_pair *tpos;
  339. struct hlist_node *pos;
  340. TOOLKIT_ASSERT(map);
  341. TOOLKIT_ASSERT(key);
  342. h = hash32_str(key, HASH32_STR_INIT);
  343. slot = h % map->size;
  344. hlist_for_each_entry(tpos, pos, &map->buckets[slot], stringmap_kv_pair, hnode) {
  345. if (tpos->h == h && !strcmp(key, tpos->key))
  346. return tpos;
  347. }
  348. return NULL; /* not found */
  349. }
  350. static void stringmap_check_expand(stringmap_t *map)
  351. {
  352. if ((map->count+1)/(float)map->size > HASH_DEFAULT_LOAD_FACTOR) { /* expand */
  353. int i;
  354. int new_size = map->size * 2 + 1;
  355. struct hlist_head *new_buckets = (struct hlist_head *)ZALLOC(new_size*sizeof(struct hlist_head));
  356. for (i = 0; i < map->size; ++i) {
  357. stringmap_kv_pair *tpos;
  358. struct hlist_node *pos, *n;
  359. hlist_for_each_entry_safe(tpos, pos, n, &map->buckets[i], stringmap_kv_pair, hnode) {
  360. unsigned int new_slot = tpos->h % new_size;
  361. hlist_del(pos);
  362. hlist_add_head(pos, &new_buckets[new_slot]);
  363. }
  364. }
  365. free(map->buckets);
  366. map->buckets = new_buckets;
  367. map->size = new_size;
  368. }
  369. }
  370. TOOLKIT_API int stringmap_add(stringmap_t *map, const char *key, void *value)
  371. {
  372. unsigned int slot, h;
  373. stringmap_kv_pair *tpos;
  374. struct hlist_node *pos;
  375. TOOLKIT_ASSERT(map);
  376. TOOLKIT_ASSERT(key);
  377. h = hash32_str(key, HASH32_STR_INIT);
  378. slot = h % map->size;
  379. hlist_for_each_entry(tpos, pos, &map->buckets[slot], stringmap_kv_pair, hnode) {
  380. if (tpos->h == h && !strcmp(key, tpos->key))
  381. return -1; /* already exist */
  382. }
  383. stringmap_check_expand(map);
  384. tpos = MALLOC_T(stringmap_kv_pair);
  385. tpos->h = h;
  386. tpos->key = _strdup(key);
  387. tpos->value = value;
  388. slot = h % map->size;
  389. hlist_add_head(&tpos->hnode, &map->buckets[slot]);
  390. map->count ++;
  391. return 0;
  392. }
  393. TOOLKIT_API void *stringmap_remove(stringmap_t *map, const char *key)
  394. {
  395. unsigned int h, slot;
  396. stringmap_kv_pair *tpos;
  397. struct hlist_node *pos, *n;
  398. TOOLKIT_ASSERT(map);
  399. TOOLKIT_ASSERT(key);
  400. h = hash32_str(key, HASH32_STR_INIT);
  401. slot = h % map->size;
  402. hlist_for_each_entry_safe(tpos, pos, n, &map->buckets[slot], stringmap_kv_pair, hnode) {
  403. if (tpos->h == h && !strcmp(key, tpos->key)) {
  404. void *value = tpos->value;
  405. hlist_del(pos);
  406. free(tpos->key);
  407. free(tpos);
  408. map->count--;
  409. return value;
  410. }
  411. }
  412. return NULL;
  413. }
  414. TOOLKIT_API int stringmap_count(stringmap_t *map)
  415. {
  416. TOOLKIT_ASSERT(map);
  417. return map->count;
  418. }
  419. TOOLKIT_API stringmap_iterator *stringmap_default_iterator(stringmap_t *map)
  420. {
  421. return stringmap_iterator_reset(&map->default_iterator);
  422. }
  423. TOOLKIT_API stringmap_iterator *stringmap_iterator_create(stringmap_t *map)
  424. {
  425. stringmap_iterator *iter;
  426. TOOLKIT_ASSERT(map);
  427. iter = MALLOC_T(stringmap_iterator);
  428. iter->map = map;
  429. iter->slot = -1;
  430. iter->pos = NULL;
  431. iter->pos_next = NULL;
  432. return iter;
  433. }
  434. TOOLKIT_API void stringmap_iterator_destroy(stringmap_iterator *iter)
  435. {
  436. TOOLKIT_ASSERT(iter);
  437. free(iter);
  438. }
  439. TOOLKIT_API int stringmap_iterator_next(stringmap_iterator *iter)
  440. {
  441. stringmap_t *map;
  442. TOOLKIT_ASSERT(iter);
  443. map = iter->map;
  444. if (iter->slot == -1) {
  445. while (++iter->slot < map->size) {
  446. if (!hlist_empty(&map->buckets[iter->slot])) {
  447. iter->pos = map->buckets[iter->slot].first;
  448. iter->pos_next = iter->pos->next;
  449. return 0;
  450. }
  451. }
  452. } else {
  453. iter->pos = iter->pos_next;
  454. if (iter->pos == NULL) {
  455. while (iter->slot < map->size) {
  456. if (iter->pos && iter->pos->next) {
  457. iter->pos = iter->pos->next;
  458. iter->pos_next = iter->pos->next;
  459. return 0;
  460. } else {
  461. ++iter->slot;
  462. if (iter->slot >= map->size)
  463. break;
  464. iter->pos = map->buckets[iter->slot].first;
  465. if (iter->pos) {
  466. iter->pos_next = iter->pos->next;
  467. return 0;
  468. }
  469. }
  470. }
  471. } else {
  472. iter->pos_next = iter->pos->next;
  473. return 0;
  474. }
  475. }
  476. return -1;
  477. }
  478. TOOLKIT_API const char *stringmap_iterator_get_key(stringmap_iterator *iter)
  479. {
  480. stringmap_kv_pair *pair;
  481. TOOLKIT_ASSERT(iter);
  482. pair = hlist_entry(iter->pos, stringmap_kv_pair, hnode);
  483. return pair->key;
  484. }
  485. TOOLKIT_API void *stringmap_iterator_get_value(stringmap_iterator *iter)
  486. {
  487. stringmap_kv_pair *pair;
  488. TOOLKIT_ASSERT(iter);
  489. pair = hlist_entry(iter->pos, stringmap_kv_pair, hnode);
  490. return pair->value;
  491. }
  492. TOOLKIT_API stringmap_iterator * stringmap_iterator_reset(stringmap_iterator *iter)
  493. {
  494. TOOLKIT_ASSERT(iter);
  495. iter->pos = iter->pos_next = NULL;
  496. iter->slot = -1;
  497. return iter;
  498. }
  499. TOOLKIT_API int htable_init(htable_t *ht, int init_size)
  500. {
  501. init_size = hash_get_prime(init_size <= 0 ? HASH_DEFAULT_INIT_HASH_SIZE : init_size);
  502. ht->size = init_size;
  503. ht->buckets = ZALLOC(init_size*sizeof(struct hlist_head));
  504. if (!ht->buckets)
  505. return -1;
  506. ht->count = 0;
  507. ht->size = init_size;
  508. return 0;
  509. }
  510. TOOLKIT_API void htable_term(htable_t *ht)
  511. {
  512. if (ht) {
  513. ht->size = ht->count = 0;
  514. free(ht->buckets);
  515. ht->buckets = NULL;
  516. }
  517. }
  518. TOOLKIT_API htable_t *htable_create(int init_size)
  519. {
  520. htable_t *ht = MALLOC_T(htable_t);
  521. if (ht) {
  522. if (htable_init(ht, init_size)) {
  523. free(ht);
  524. ht = NULL;
  525. }
  526. }
  527. return ht;
  528. }
  529. TOOLKIT_API void htable_destroy(htable_t *ht)
  530. {
  531. htable_term(ht);
  532. free(ht);
  533. }
  534. /*
  535. // test
  536. #include <stdio.h>
  537. #include <string.h>
  538. typedef struct student_data {
  539. char name[32];
  540. int score;
  541. struct hlist_node node;
  542. }student_data;
  543. static student_data* new_student()
  544. {
  545. return MALLOC_T(student_data);
  546. }
  547. static void delete_student(student_data *stu)
  548. {
  549. free(stu);
  550. }
  551. static const void* student_getkey(const void *obj)
  552. {
  553. student_data *stu = (student_data *)obj;
  554. return stu->name;
  555. }
  556. static unsigned int student_hash(const void *key)
  557. {
  558. return hash_str((const char*)key);
  559. }
  560. static int student_cmpkey(const void *key_x, const void *key_y)
  561. {
  562. const char *x = key_x;
  563. const char *y = key_y;
  564. return strcmp(x, y);
  565. }
  566. int test() // int main()
  567. {
  568. hashset_t hs;
  569. student_data *stu_a, *stu_b, *stu_c;
  570. if (hashset_create(offset_of(student_data, node),
  571. student_getkey, student_hash, student_cmpkey, &hs) != 0)
  572. return -1;
  573. stu_a = new_student();
  574. strcpy(stu_a->name, "stu_a");
  575. TOOLKIT_ASSERT(hashset_add(&hs, stu_a) == 0);
  576. stu_b = new_student();
  577. strcpy(stu_b->name, "stu_b");
  578. TOOLKIT_ASSERT(hashset_add(&hs, stu_b) == 0);
  579. stu_c = new_student();
  580. strcpy(stu_c->name, "stu_c");
  581. TOOLKIT_ASSERT(hashset_add(&hs, stu_c) == 0);
  582. printf("hashset_count = %d\n", hashset_count(&hs));
  583. {
  584. student_data *tpos;
  585. struct hlist_node *pos, *n;
  586. int slot;
  587. hashset_for_each_safe(tpos, pos, n, slot, &hs, student_data) {
  588. printf("%s ", tpos->name);
  589. hashset_remove(&hs, tpos->name);
  590. delete_student(tpos);
  591. }
  592. printf("\n");
  593. }
  594. printf("hashset_count = %d\n", hashset_count(&hs));
  595. getchar();
  596. return 0;
  597. }
  598. */
  599. /*
  600. int main()
  601. {
  602. stringmap_t *map;
  603. stringmap_iterator *it;
  604. map = stringmap_create(10);
  605. TOOLKIT_ASSERT(map);
  606. stringmap_add(map, "1", "1-23321");
  607. stringmap_add(map, "2", "2-23321");
  608. stringmap_add(map, "3", "3-23321");
  609. printf("map size = %d\n", stringmap_count(map));
  610. it = stringmap_iterator_create(map);
  611. while (stringmap_iterator_next(it) == 0) {
  612. const char *key = stringmap_iterator_get_key(it);
  613. const char *value = stringmap_iterator_get_value(it);
  614. printf("key: %s, value: %s\n", key, value);
  615. }
  616. stringmap_iterator_reset(it);
  617. while (stringmap_iterator_next(it) == 0) {
  618. const char *key = stringmap_iterator_get_key(it);
  619. stringmap_remove(map, key);
  620. }
  621. stringmap_iterator_destroy(it);
  622. stringmap_destroy(map);
  623. _CrtDumpMemoryLeaks();
  624. return 0;
  625. }
  626. */