trie.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #include "trie.h"
  2. static Trie_entry *
  3. get_entry(Trie *trie, Trie_entry *prev, const void *dat, Nit_error *error)
  4. {
  5. Trie_entry *entry = malloc(sizeof(*entry));
  6. if (!entry)
  7. return NULL;
  8. entry->dat = (void *) dat;
  9. entry->prev = prev;
  10. if ((*error = map_init(&entry->map, &trie->disposer, 0))) {
  11. free(entry);
  12. return NULL;
  13. }
  14. return entry;
  15. }
  16. static void
  17. entry_dispose(void *dat, void *extra)
  18. {
  19. Trie_entry *entry = dat;
  20. Disposer *dat_disposer = extra;
  21. if (dat_disposer)
  22. dat_disposer->dispose(entry->dat, dat_disposer->extra);
  23. map_dispose(&entry->map);
  24. free(entry);
  25. }
  26. Nit_error
  27. trie_init(Trie *trie, Disposer *disposer, const void *root_dat)
  28. {
  29. Nit_error error;
  30. trie->disposer.extra = disposer;
  31. trie->disposer.dispose = entry_dispose;
  32. trie->root = get_entry(trie, NULL, root_dat, &error);
  33. return error;
  34. }
  35. void
  36. trie_dispose(Trie *trie)
  37. {
  38. entry_dispose(trie->root, trie->disposer.extra);
  39. }
  40. /* For single values */
  41. Trie_entry *
  42. trie_add(Trie *trie, Trie_entry *entry, uint32_t key_len,
  43. const void *key, const void *val)
  44. {
  45. Nit_error error;
  46. Trie_entry *tmp;
  47. if (!entry)
  48. entry = trie->root;
  49. if (!(tmp = get_entry(trie, entry, val, &error)))
  50. return NULL;
  51. if (map_add(&entry->map, key_len, key, tmp)) {
  52. entry_dispose(tmp, NULL);
  53. return NULL;
  54. }
  55. return tmp;
  56. }
  57. Nit_error
  58. trie_remove(Trie *trie, Trie_entry *entry, uint32_t key_len,
  59. const void *key, void **val)
  60. {
  61. entry = trie_get(entry ? entry : trie->root, key_len, key);
  62. if (!entry)
  63. return NIT_ERROR_NOT_FOUND;
  64. *val = entry->dat;
  65. entry->dat = NULL;
  66. if (!entry->map.size) {
  67. if (!entry->prev)
  68. trie->root = NULL;
  69. else
  70. map_remove(&entry->prev->map, key_len, key,
  71. (void **) &entry);
  72. entry_dispose(entry, NULL);
  73. }
  74. return NIT_ERROR_FINE;
  75. }
  76. Trie_entry *
  77. trie_get(Trie_entry *entry, uint32_t key_len, const void *key)
  78. {
  79. Trie_entry *tmp;
  80. if (!map_get(&entry->map, key_len, key, (void **) &tmp))
  81. return NULL;
  82. return tmp;
  83. }
  84. /* For lists of keys */
  85. Trie_entry *
  86. trie_list_add(Trie *trie, Trie_entry *entry, List *key_list, const void *val)
  87. {
  88. List_entry *lentry;
  89. int new_entries = 0;
  90. if (!entry)
  91. entry = trie->root;
  92. list_foreach (lentry, key_list) {
  93. Set_key *key = lentry->data;
  94. Trie_entry *tmp;
  95. Nit_error error;
  96. /* try getting trie entry if not adding new entries yet */
  97. if (!new_entries &&
  98. map_get(&entry->map, key->key_len, key->dat,
  99. (void **) &tmp)) {
  100. entry = tmp;
  101. continue;
  102. }
  103. new_entries = 1;
  104. if (!(tmp = get_entry(trie, entry, NULL, &error)))
  105. return NULL;
  106. if (map_add(&entry->map, key->key_len, key->dat, tmp)) {
  107. entry_dispose(tmp, NULL);
  108. return NULL;
  109. }
  110. entry = tmp;
  111. }
  112. entry->dat = (void *) val;
  113. return entry;
  114. }
  115. Nit_error
  116. trie_list_remove(Trie *trie, Trie_entry *entry, List *key_list, void **val)
  117. {
  118. entry = trie_list_get(entry ? entry : trie->root, key_list);
  119. if (!entry)
  120. return NIT_ERROR_NOT_FOUND;
  121. *val = entry->dat;
  122. entry->dat = NULL;
  123. if (!entry->map.size) {
  124. if (!entry->prev) {
  125. trie->root = NULL;
  126. } else {
  127. Set_key *key = key_list->tail->data;
  128. map_remove(&entry->prev->map, key->key_len, key->dat,
  129. (void **) &entry);
  130. }
  131. entry_dispose(entry, NULL);
  132. }
  133. return NIT_ERROR_FINE;
  134. }
  135. Trie_entry *
  136. trie_list_get(Trie_entry *entry, List *key_list)
  137. {
  138. List_entry *lentry;
  139. list_foreach (lentry, key_list) {
  140. Set_key *key = lentry->data;
  141. if (!(entry = trie_get(entry, key->key_len, key->dat)))
  142. return NULL;
  143. }
  144. return entry;
  145. }