sdsykes-ferret 0.11.6.19

Sign up to get free protection for your applications and to get access to all the features.
Files changed (195) hide show
  1. data/CHANGELOG +24 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README +102 -0
  4. data/Rakefile +338 -0
  5. data/TODO +17 -0
  6. data/TUTORIAL +231 -0
  7. data/bin/ferret-browser +79 -0
  8. data/ext/analysis.c +1555 -0
  9. data/ext/analysis.h +219 -0
  10. data/ext/api.c +69 -0
  11. data/ext/api.h +27 -0
  12. data/ext/array.c +123 -0
  13. data/ext/array.h +53 -0
  14. data/ext/bitvector.c +540 -0
  15. data/ext/bitvector.h +272 -0
  16. data/ext/compound_io.c +383 -0
  17. data/ext/config.h +42 -0
  18. data/ext/document.c +156 -0
  19. data/ext/document.h +53 -0
  20. data/ext/except.c +120 -0
  21. data/ext/except.h +168 -0
  22. data/ext/extconf.rb +14 -0
  23. data/ext/ferret.c +402 -0
  24. data/ext/ferret.h +91 -0
  25. data/ext/filter.c +156 -0
  26. data/ext/fs_store.c +483 -0
  27. data/ext/global.c +418 -0
  28. data/ext/global.h +117 -0
  29. data/ext/hash.c +567 -0
  30. data/ext/hash.h +473 -0
  31. data/ext/hashset.c +170 -0
  32. data/ext/hashset.h +187 -0
  33. data/ext/header.h +58 -0
  34. data/ext/helper.c +62 -0
  35. data/ext/helper.h +13 -0
  36. data/ext/inc/lang.h +48 -0
  37. data/ext/inc/threading.h +31 -0
  38. data/ext/index.c +6425 -0
  39. data/ext/index.h +961 -0
  40. data/ext/lang.h +66 -0
  41. data/ext/libstemmer.c +92 -0
  42. data/ext/libstemmer.h +79 -0
  43. data/ext/mempool.c +87 -0
  44. data/ext/mempool.h +35 -0
  45. data/ext/modules.h +162 -0
  46. data/ext/multimapper.c +310 -0
  47. data/ext/multimapper.h +51 -0
  48. data/ext/posh.c +1006 -0
  49. data/ext/posh.h +1007 -0
  50. data/ext/priorityqueue.c +151 -0
  51. data/ext/priorityqueue.h +143 -0
  52. data/ext/q_boolean.c +1608 -0
  53. data/ext/q_const_score.c +161 -0
  54. data/ext/q_filtered_query.c +209 -0
  55. data/ext/q_fuzzy.c +268 -0
  56. data/ext/q_match_all.c +148 -0
  57. data/ext/q_multi_term.c +677 -0
  58. data/ext/q_parser.c +2825 -0
  59. data/ext/q_phrase.c +1126 -0
  60. data/ext/q_prefix.c +100 -0
  61. data/ext/q_range.c +350 -0
  62. data/ext/q_span.c +2402 -0
  63. data/ext/q_term.c +337 -0
  64. data/ext/q_wildcard.c +171 -0
  65. data/ext/r_analysis.c +2575 -0
  66. data/ext/r_index.c +3472 -0
  67. data/ext/r_qparser.c +585 -0
  68. data/ext/r_search.c +4105 -0
  69. data/ext/r_store.c +513 -0
  70. data/ext/r_utils.c +963 -0
  71. data/ext/ram_store.c +471 -0
  72. data/ext/search.c +1741 -0
  73. data/ext/search.h +885 -0
  74. data/ext/similarity.c +150 -0
  75. data/ext/similarity.h +82 -0
  76. data/ext/sort.c +983 -0
  77. data/ext/stem_ISO_8859_1_danish.c +338 -0
  78. data/ext/stem_ISO_8859_1_danish.h +16 -0
  79. data/ext/stem_ISO_8859_1_dutch.c +635 -0
  80. data/ext/stem_ISO_8859_1_dutch.h +16 -0
  81. data/ext/stem_ISO_8859_1_english.c +1156 -0
  82. data/ext/stem_ISO_8859_1_english.h +16 -0
  83. data/ext/stem_ISO_8859_1_finnish.c +792 -0
  84. data/ext/stem_ISO_8859_1_finnish.h +16 -0
  85. data/ext/stem_ISO_8859_1_french.c +1276 -0
  86. data/ext/stem_ISO_8859_1_french.h +16 -0
  87. data/ext/stem_ISO_8859_1_german.c +512 -0
  88. data/ext/stem_ISO_8859_1_german.h +16 -0
  89. data/ext/stem_ISO_8859_1_italian.c +1091 -0
  90. data/ext/stem_ISO_8859_1_italian.h +16 -0
  91. data/ext/stem_ISO_8859_1_norwegian.c +296 -0
  92. data/ext/stem_ISO_8859_1_norwegian.h +16 -0
  93. data/ext/stem_ISO_8859_1_porter.c +776 -0
  94. data/ext/stem_ISO_8859_1_porter.h +16 -0
  95. data/ext/stem_ISO_8859_1_portuguese.c +1035 -0
  96. data/ext/stem_ISO_8859_1_portuguese.h +16 -0
  97. data/ext/stem_ISO_8859_1_spanish.c +1119 -0
  98. data/ext/stem_ISO_8859_1_spanish.h +16 -0
  99. data/ext/stem_ISO_8859_1_swedish.c +307 -0
  100. data/ext/stem_ISO_8859_1_swedish.h +16 -0
  101. data/ext/stem_KOI8_R_russian.c +701 -0
  102. data/ext/stem_KOI8_R_russian.h +16 -0
  103. data/ext/stem_UTF_8_danish.c +344 -0
  104. data/ext/stem_UTF_8_danish.h +16 -0
  105. data/ext/stem_UTF_8_dutch.c +653 -0
  106. data/ext/stem_UTF_8_dutch.h +16 -0
  107. data/ext/stem_UTF_8_english.c +1176 -0
  108. data/ext/stem_UTF_8_english.h +16 -0
  109. data/ext/stem_UTF_8_finnish.c +808 -0
  110. data/ext/stem_UTF_8_finnish.h +16 -0
  111. data/ext/stem_UTF_8_french.c +1296 -0
  112. data/ext/stem_UTF_8_french.h +16 -0
  113. data/ext/stem_UTF_8_german.c +526 -0
  114. data/ext/stem_UTF_8_german.h +16 -0
  115. data/ext/stem_UTF_8_italian.c +1113 -0
  116. data/ext/stem_UTF_8_italian.h +16 -0
  117. data/ext/stem_UTF_8_norwegian.c +302 -0
  118. data/ext/stem_UTF_8_norwegian.h +16 -0
  119. data/ext/stem_UTF_8_porter.c +794 -0
  120. data/ext/stem_UTF_8_porter.h +16 -0
  121. data/ext/stem_UTF_8_portuguese.c +1055 -0
  122. data/ext/stem_UTF_8_portuguese.h +16 -0
  123. data/ext/stem_UTF_8_russian.c +709 -0
  124. data/ext/stem_UTF_8_russian.h +16 -0
  125. data/ext/stem_UTF_8_spanish.c +1137 -0
  126. data/ext/stem_UTF_8_spanish.h +16 -0
  127. data/ext/stem_UTF_8_swedish.c +313 -0
  128. data/ext/stem_UTF_8_swedish.h +16 -0
  129. data/ext/stopwords.c +401 -0
  130. data/ext/store.c +692 -0
  131. data/ext/store.h +777 -0
  132. data/ext/term_vectors.c +352 -0
  133. data/ext/threading.h +31 -0
  134. data/ext/utilities.c +446 -0
  135. data/ext/win32.h +54 -0
  136. data/lib/ferret.rb +29 -0
  137. data/lib/ferret/browser.rb +246 -0
  138. data/lib/ferret/browser/s/global.js +192 -0
  139. data/lib/ferret/browser/s/style.css +148 -0
  140. data/lib/ferret/browser/views/document/list.rhtml +49 -0
  141. data/lib/ferret/browser/views/document/show.rhtml +27 -0
  142. data/lib/ferret/browser/views/error/index.rhtml +7 -0
  143. data/lib/ferret/browser/views/help/index.rhtml +8 -0
  144. data/lib/ferret/browser/views/home/index.rhtml +29 -0
  145. data/lib/ferret/browser/views/layout.rhtml +22 -0
  146. data/lib/ferret/browser/views/term-vector/index.rhtml +4 -0
  147. data/lib/ferret/browser/views/term/index.rhtml +199 -0
  148. data/lib/ferret/browser/views/term/termdocs.rhtml +1 -0
  149. data/lib/ferret/browser/webrick.rb +14 -0
  150. data/lib/ferret/document.rb +130 -0
  151. data/lib/ferret/field_infos.rb +44 -0
  152. data/lib/ferret/index.rb +786 -0
  153. data/lib/ferret/number_tools.rb +157 -0
  154. data/lib/ferret_version.rb +3 -0
  155. data/setup.rb +1555 -0
  156. data/test/test_all.rb +5 -0
  157. data/test/test_helper.rb +24 -0
  158. data/test/threading/number_to_spoken.rb +132 -0
  159. data/test/threading/thread_safety_index_test.rb +79 -0
  160. data/test/threading/thread_safety_read_write_test.rb +76 -0
  161. data/test/threading/thread_safety_test.rb +133 -0
  162. data/test/unit/analysis/tc_analyzer.rb +548 -0
  163. data/test/unit/analysis/tc_token_stream.rb +646 -0
  164. data/test/unit/index/tc_index.rb +762 -0
  165. data/test/unit/index/tc_index_reader.rb +699 -0
  166. data/test/unit/index/tc_index_writer.rb +437 -0
  167. data/test/unit/index/th_doc.rb +315 -0
  168. data/test/unit/largefile/tc_largefile.rb +46 -0
  169. data/test/unit/query_parser/tc_query_parser.rb +238 -0
  170. data/test/unit/search/tc_filter.rb +135 -0
  171. data/test/unit/search/tc_fuzzy_query.rb +147 -0
  172. data/test/unit/search/tc_index_searcher.rb +61 -0
  173. data/test/unit/search/tc_multi_searcher.rb +128 -0
  174. data/test/unit/search/tc_multiple_search_requests.rb +58 -0
  175. data/test/unit/search/tc_search_and_sort.rb +179 -0
  176. data/test/unit/search/tc_sort.rb +49 -0
  177. data/test/unit/search/tc_sort_field.rb +27 -0
  178. data/test/unit/search/tc_spans.rb +190 -0
  179. data/test/unit/search/tm_searcher.rb +384 -0
  180. data/test/unit/store/tc_fs_store.rb +77 -0
  181. data/test/unit/store/tc_ram_store.rb +35 -0
  182. data/test/unit/store/tm_store.rb +34 -0
  183. data/test/unit/store/tm_store_lock.rb +68 -0
  184. data/test/unit/tc_document.rb +81 -0
  185. data/test/unit/ts_analysis.rb +2 -0
  186. data/test/unit/ts_index.rb +2 -0
  187. data/test/unit/ts_largefile.rb +4 -0
  188. data/test/unit/ts_query_parser.rb +2 -0
  189. data/test/unit/ts_search.rb +2 -0
  190. data/test/unit/ts_store.rb +2 -0
  191. data/test/unit/ts_utils.rb +2 -0
  192. data/test/unit/utils/tc_bit_vector.rb +295 -0
  193. data/test/unit/utils/tc_number_tools.rb +117 -0
  194. data/test/unit/utils/tc_priority_queue.rb +106 -0
  195. metadata +285 -0
@@ -0,0 +1,567 @@
1
+ #include "hash.h"
2
+ #include "global.h"
3
+ #include <string.h>
4
+
5
+ /****************************************************************************
6
+ *
7
+ * HashTable
8
+ *
9
+ * This hash table is modeled after Python's dictobject and a description of
10
+ * the algorithm can be found in the file dictobject.c in Python's src
11
+ ****************************************************************************/
12
+
13
+ static char *dummy_key = "";
14
+
15
+ #define PERTURB_SHIFT 5
16
+ #define MAX_FREE_HASH_TABLES 80
17
+
18
+ static HashTable *free_hts[MAX_FREE_HASH_TABLES];
19
+ static int num_free_hts = 0;
20
+
21
+ unsigned long str_hash(const char *const str)
22
+ {
23
+ register unsigned long h = 0;
24
+ register unsigned char *p = (unsigned char *) str;
25
+
26
+ for (; *p; p++) {
27
+ h = 37 * h + *p;
28
+ }
29
+
30
+ return h;
31
+ }
32
+
33
+ unsigned long ptr_hash(const void *const ptr)
34
+ {
35
+ return (unsigned long)ptr;
36
+ }
37
+
38
+ int ptr_eq(const void *q1, const void *q2)
39
+ {
40
+ return q1 == q2;
41
+ }
42
+
43
+ static int int_eq(const void *q1, const void *q2)
44
+ {
45
+ (void)q1;
46
+ (void)q2;
47
+ return true;
48
+ }
49
+
50
+ static unsigned long int_hash(const void *i)
51
+ {
52
+ return *((unsigned long *)i);
53
+ }
54
+
55
+ typedef HashEntry *(*lookup_ft)(struct HashTable *ht, register const void *key);
56
+
57
+ /**
58
+ * Fast lookup function for resizing as we know there are no equal elements or
59
+ * deletes to worry about.
60
+ *
61
+ * @param ht the HashTable to do the fast lookup in
62
+ * @param the hashkey we are looking for
63
+ */
64
+ static INLINE HashEntry *h_resize_lookup(HashTable *ht,
65
+ register const unsigned long hash)
66
+ {
67
+ register unsigned long perturb;
68
+ register int mask = ht->mask;
69
+ register HashEntry *he0 = ht->table;
70
+ register int i = hash & mask;
71
+ register HashEntry *he = &he0[i];
72
+
73
+ if (he->key == NULL) {
74
+ he->hash = hash;
75
+ return he;
76
+ }
77
+
78
+ for (perturb = hash;; perturb >>= PERTURB_SHIFT) {
79
+ i = (i << 2) + i + perturb + 1;
80
+ he = &he0[i & mask];
81
+ if (he->key == NULL) {
82
+ he->hash = hash;
83
+ return he;
84
+ }
85
+ }
86
+ }
87
+
88
+ HashEntry *h_lookup_int(HashTable *ht, const void *key)
89
+ {
90
+ register unsigned long hash = *((int *)key);
91
+ register unsigned long perturb;
92
+ register int mask = ht->mask;
93
+ register HashEntry *he0 = ht->table;
94
+ register int i = hash & mask;
95
+ register HashEntry *he = &he0[i];
96
+ register HashEntry *freeslot = NULL;
97
+
98
+ if (he->key == NULL || he->hash == hash) {
99
+ he->hash = hash;
100
+ return he;
101
+ }
102
+ if (he->key == dummy_key) {
103
+ freeslot = he;
104
+ }
105
+
106
+ for (perturb = hash;; perturb >>= PERTURB_SHIFT) {
107
+ i = (i << 2) + i + perturb + 1;
108
+ he = &he0[i & mask];
109
+ if (he->key == NULL) {
110
+ if (freeslot != NULL) {
111
+ he = freeslot;
112
+ }
113
+ he->hash = hash;
114
+ return he;
115
+ }
116
+ if (he->hash == hash) {
117
+ return he;
118
+ }
119
+ if (he->key == dummy_key && freeslot == NULL) {
120
+ freeslot = he;
121
+ }
122
+ }
123
+ }
124
+
125
+ HashEntry *h_lookup_str(HashTable *ht, register const char *key)
126
+ {
127
+ register unsigned long hash = str_hash(key);
128
+ register unsigned long perturb;
129
+ register int mask = ht->mask;
130
+ register HashEntry *he0 = ht->table;
131
+ register int i = hash & mask;
132
+ register HashEntry *he = &he0[i];
133
+ register HashEntry *freeslot;
134
+
135
+ if (he->key == NULL || he->key == key) {
136
+ he->hash = hash;
137
+ return he;
138
+ }
139
+ if (he->key == dummy_key) {
140
+ freeslot = he;
141
+ }
142
+ else {
143
+ if ((he->hash == hash) && (strcmp(he->key, key) == 0)) {
144
+ return he;
145
+ }
146
+ freeslot = NULL;
147
+ }
148
+
149
+ for (perturb = hash;; perturb >>= PERTURB_SHIFT) {
150
+ i = (i << 2) + i + perturb + 1;
151
+ he = &he0[i & mask];
152
+ if (he->key == NULL) {
153
+ if (freeslot != NULL) {
154
+ he = freeslot;
155
+ }
156
+ he->hash = hash;
157
+ return he;
158
+ }
159
+ if (he->key == key
160
+ || (he->hash == hash
161
+ && he->key != dummy_key && strcmp(he->key, key) == 0)) {
162
+ return he;
163
+ }
164
+ if (he->key == dummy_key && freeslot == NULL) {
165
+ freeslot = he;
166
+ }
167
+ }
168
+ }
169
+
170
+ HashEntry *h_lookup(HashTable *ht, register const void *key)
171
+ {
172
+ register unsigned int hash = ht->hash_i(key);
173
+ register unsigned int perturb;
174
+ register int mask = ht->mask;
175
+ register HashEntry *he0 = ht->table;
176
+ register int i = hash & mask;
177
+ register HashEntry *he = &he0[i];
178
+ register HashEntry *freeslot;
179
+ eq_ft eq = ht->eq_i;
180
+
181
+ if (he->key == NULL || he->key == key) {
182
+ he->hash = hash;
183
+ return he;
184
+ }
185
+ if (he->key == dummy_key) {
186
+ freeslot = he;
187
+ }
188
+ else {
189
+ if ((he->hash == hash) && eq(he->key, key)) {
190
+ return he;
191
+ }
192
+ freeslot = NULL;
193
+ }
194
+
195
+ for (perturb = hash;; perturb >>= PERTURB_SHIFT) {
196
+ i = (i << 2) + i + perturb + 1;
197
+ he = &he0[i & mask];
198
+ if (he->key == NULL) {
199
+ if (freeslot != NULL) {
200
+ he = freeslot;
201
+ }
202
+ he->hash = hash;
203
+ return he;
204
+ }
205
+ if (he->key == key
206
+ || (he->hash == hash
207
+ && he->key != dummy_key && eq(he->key, key))) {
208
+ return he;
209
+ }
210
+ if (he->key == dummy_key && freeslot == NULL) {
211
+ freeslot = he;
212
+ }
213
+ }
214
+ }
215
+
216
+ HashTable *h_new_str(free_ft free_key, free_ft free_value)
217
+ {
218
+ HashTable *ht;
219
+ if (num_free_hts > 0) {
220
+ ht = free_hts[--num_free_hts];
221
+ }
222
+ else {
223
+ ht = ALLOC(HashTable);
224
+ }
225
+ ht->fill = 0;
226
+ ht->size = 0;
227
+ ht->mask = HASH_MINSIZE - 1;
228
+ ht->table = ht->smalltable;
229
+ memset(ht->smalltable, 0, sizeof(ht->smalltable));
230
+ ht->lookup_i = (lookup_ft)&h_lookup_str;
231
+
232
+ ht->free_key_i = free_key != NULL ? free_key : &dummy_free;
233
+ ht->free_value_i = free_value != NULL ? free_value : &dummy_free;
234
+ ht->ref_cnt = 1;
235
+ return ht;
236
+ }
237
+
238
+ HashTable *h_new_int(free_ft free_value)
239
+ {
240
+ HashTable *ht = h_new_str(NULL, free_value);
241
+ ht->lookup_i = &h_lookup_int;
242
+ ht->eq_i = int_eq;
243
+ ht->hash_i = int_hash;
244
+ return ht;
245
+ }
246
+
247
+ HashTable *h_new(hash_ft hash, eq_ft eq, free_ft free_key, free_ft free_value)
248
+ {
249
+ HashTable *ht = h_new_str(free_key, free_value);
250
+
251
+ ht->lookup_i = &h_lookup;
252
+ ht->eq_i = eq;
253
+ ht->hash_i = hash;
254
+ return ht;
255
+ }
256
+
257
+ void h_clear(HashTable *ht)
258
+ {
259
+ int i;
260
+ HashEntry *he;
261
+ free_ft free_key = ht->free_key_i;
262
+ free_ft free_value = ht->free_value_i;
263
+
264
+ /* Clear all the hash values and keys as necessary */
265
+ if (free_key != dummy_free || free_value != dummy_free) {
266
+ for (i = 0; i <= ht->mask; i++) {
267
+ he = &ht->table[i];
268
+ if (he->key != NULL && he->key != dummy_key) {
269
+ free_value(he->value);
270
+ free_key(he->key);
271
+ }
272
+ he->key = NULL;
273
+ }
274
+ }
275
+ ZEROSET_N(ht->table, HashEntry, ht->mask + 1);
276
+ ht->size = 0;
277
+ ht->fill = 0;
278
+ }
279
+
280
+ void h_destroy(HashTable *ht)
281
+ {
282
+ if (--(ht->ref_cnt) <= 0) {
283
+ h_clear(ht);
284
+
285
+ /* if a new table was created, be sure to free it */
286
+ if (ht->table != ht->smalltable) {
287
+ free(ht->table);
288
+ }
289
+
290
+ #ifdef DEBUG
291
+ free(ht);
292
+ #else
293
+ if (num_free_hts < MAX_FREE_HASH_TABLES) {
294
+ free_hts[num_free_hts++] = ht;
295
+ }
296
+ else {
297
+ free(ht);
298
+ }
299
+ #endif
300
+ }
301
+ }
302
+
303
+ void *h_get(HashTable *ht, const void *key)
304
+ {
305
+ /* Note: lookup_i will never return NULL. */
306
+ return ht->lookup_i(ht, key)->value;
307
+ }
308
+
309
+ int h_del(HashTable *ht, const void *key)
310
+ {
311
+ HashEntry *he = ht->lookup_i(ht, key);
312
+
313
+ if (he->key != NULL && he->key != dummy_key) {
314
+ ht->free_key_i(he->key);
315
+ ht->free_value_i(he->value);
316
+ he->key = dummy_key;
317
+ he->value = NULL;
318
+ ht->size--;
319
+ return true;
320
+ }
321
+ else {
322
+ return false;
323
+ }
324
+ }
325
+
326
+ void *h_rem(HashTable *ht, const void *key, bool destroy_key)
327
+ {
328
+ void *val;
329
+ HashEntry *he = ht->lookup_i(ht, key);
330
+
331
+ if (he->key != NULL && he->key != dummy_key) {
332
+ if (destroy_key) {
333
+ ht->free_key_i(he->key);
334
+ }
335
+
336
+ he->key = dummy_key;
337
+ val = he->value;
338
+ he->value = NULL;
339
+ ht->size--;
340
+ return val;
341
+ }
342
+ else {
343
+ return NULL;
344
+ }
345
+ }
346
+
347
+ static int h_resize(HashTable *ht, int min_newsize)
348
+ {
349
+ HashEntry smallcopy[HASH_MINSIZE];
350
+ HashEntry *oldtable;
351
+ HashEntry *he_old, *he_new;
352
+ int newsize, num_active;
353
+
354
+ /* newsize will be a power of two */
355
+ for (newsize = HASH_MINSIZE; newsize < min_newsize; newsize <<= 1) {
356
+ }
357
+
358
+ oldtable = ht->table;
359
+ if (newsize == HASH_MINSIZE) {
360
+ if (ht->table == ht->smalltable) {
361
+ /* need to copy the d*(int *)ata out so we can rebuild the table into
362
+ * the same space */
363
+ memcpy(smallcopy, ht->smalltable, sizeof(smallcopy));
364
+ oldtable = smallcopy;
365
+ }
366
+ else {
367
+ ht->table = ht->smalltable;
368
+ }
369
+ }
370
+ else {
371
+ ht->table = ALLOC_N(HashEntry, newsize);
372
+ }
373
+ memset(ht->table, 0, sizeof(HashEntry) * newsize);
374
+ ht->fill = ht->size;
375
+ ht->mask = newsize - 1;
376
+
377
+ for (num_active = ht->size, he_old = oldtable; num_active > 0; he_old++) {
378
+ if (he_old->key && he_old->key != dummy_key) { /* active entry */
379
+ /*he_new = ht->lookup_i(ht, he_old->key); */
380
+ he_new = h_resize_lookup(ht, he_old->hash);
381
+ he_new->key = he_old->key;
382
+ he_new->value = he_old->value;
383
+ num_active--;
384
+ } /* else empty entry so nothing to do */
385
+ }
386
+ if (oldtable != smallcopy && oldtable != ht->smalltable) {
387
+ free(oldtable);
388
+ }
389
+ return 0;
390
+ }
391
+
392
+ int h_set(HashTable *ht, const void *key, void *value)
393
+ {
394
+ int ret_val = HASH_KEY_DOES_NOT_EXIST;
395
+ HashEntry *he = ht->lookup_i(ht, key);
396
+ if (he->key == NULL) {
397
+ if (ht->fill * 3 > ht->mask * 2) {
398
+ h_resize(ht, ht->size * ((ht->size > SLOW_DOWN) ? 4 : 2));
399
+ he = ht->lookup_i(ht, key);
400
+ }
401
+ ht->fill++;
402
+ ht->size++;
403
+ }
404
+ else if (he->key == dummy_key) {
405
+ ht->size++;
406
+ }
407
+ else if (he->key != key) {
408
+ ht->free_key_i(he->key);
409
+ if (he->value != value) {
410
+ ht->free_value_i(he->value);
411
+ }
412
+ ret_val = HASH_KEY_EQUAL;
413
+ }
414
+ else {
415
+ /* safety check. Only free old value if it isn't the new value */
416
+ if (he->value != value) {
417
+ ht->free_value_i(he->value);
418
+ }
419
+ ret_val = HASH_KEY_SAME;
420
+ }
421
+ he->key = (void *)key;
422
+ he->value = value;
423
+
424
+ /*
425
+ if ((ht->fill > fill) && (ht->fill * 3 > ht->mask * 2)) {
426
+ h_resize(ht, ht->size * ((ht->size > SLOW_DOWN) ? 4 : 2));
427
+ }
428
+ */
429
+ return ret_val;
430
+ }
431
+
432
+ HashEntry *h_set_ext(HashTable *ht, const void *key)
433
+ {
434
+ HashEntry *he = ht->lookup_i(ht, key);
435
+ if (he->key == NULL) {
436
+ if (ht->fill * 3 > ht->mask * 2) {
437
+ h_resize(ht, ht->size * ((ht->size > SLOW_DOWN) ? 4 : 2));
438
+ he = ht->lookup_i(ht, key);
439
+ }
440
+ ht->fill++;
441
+ ht->size++;
442
+ }
443
+ else if (he->key == dummy_key) {
444
+ ht->size++;
445
+ }
446
+
447
+ return he;
448
+ }
449
+
450
+ int h_set_safe(HashTable *ht, const void *key, void *value)
451
+ {
452
+ HashEntry *he = ht->lookup_i(ht, key);
453
+ int fill = ht->fill;
454
+ if (he->key == NULL) {
455
+ ht->fill++;
456
+ ht->size++;
457
+ }
458
+ else if (he->key == dummy_key) {
459
+ ht->size++;
460
+ }
461
+ else {
462
+ return false;
463
+ }
464
+ he->key = (void *)key;
465
+ he->value = value;
466
+
467
+ if ((ht->fill > fill) && (ht->fill * 3 > ht->mask * 2)) {
468
+ h_resize(ht, ht->size * ((ht->size > SLOW_DOWN) ? 4 : 2));
469
+ }
470
+ return true;
471
+ }
472
+
473
+ int h_has_key(HashTable *ht, const void *key)
474
+ {
475
+ HashEntry *he = ht->lookup_i(ht, key);
476
+ if (he->key == NULL || he->key == dummy_key) {
477
+ return HASH_KEY_DOES_NOT_EXIST;
478
+ }
479
+ else if (he->key == key) {
480
+ return HASH_KEY_SAME;
481
+ }
482
+ else {
483
+ return HASH_KEY_EQUAL;
484
+ }
485
+ }
486
+
487
+ void *h_get_int(HashTable *self, const unsigned long key)
488
+ {
489
+ return h_get(self, &key);
490
+ }
491
+
492
+ int h_del_int(HashTable *self, const unsigned long key)
493
+ {
494
+ return h_del(self, &key);
495
+ }
496
+
497
+ void *h_rem_int(HashTable *self, const unsigned long key)
498
+ {
499
+ return h_rem(self, &key, false);
500
+ }
501
+
502
+ int h_set_int(HashTable *self, const unsigned long key, void *value)
503
+ {
504
+ return h_set(self, &key, value);
505
+ }
506
+
507
+ int h_set_safe_int(HashTable *self, const unsigned long key, void *value)
508
+ {
509
+ return h_set_safe(self, &key, value);
510
+ }
511
+
512
+ int h_has_key_int(HashTable *self, const unsigned long key)
513
+ {
514
+ return h_has_key(self, &key);
515
+ }
516
+
517
+ void h_each(HashTable *ht,
518
+ void (*each_kv) (void *key, void *value, void *arg), void *arg)
519
+ {
520
+ HashEntry *he;
521
+ int i = ht->size;
522
+ for (he = ht->table; i > 0; he++) {
523
+ if (he->key && he->key != dummy_key) { /* active entry */
524
+ each_kv(he->key, he->value, arg);
525
+ i--;
526
+ }
527
+ }
528
+ }
529
+
530
+ HashTable *h_clone(HashTable *ht,
531
+ h_clone_func_t clone_key, h_clone_func_t clone_value)
532
+ {
533
+ void *key, *value;
534
+ HashEntry *he;
535
+ int i = ht->size;
536
+ HashTable *ht_clone;
537
+
538
+ if (ht->lookup_i == (lookup_ft)&h_lookup_str) {
539
+ ht_clone = h_new_str(ht->free_key_i, ht->free_value_i);
540
+ }
541
+ else {
542
+ ht_clone = h_new(ht->hash_i, ht->eq_i, ht->free_key_i, ht->free_value_i);
543
+ }
544
+
545
+ for (he = ht->table; i > 0; he++) {
546
+ if (he->key && he->key != dummy_key) { /* active entry */
547
+ key = clone_key ? clone_key(he->key) : he->key;
548
+ value = clone_value ? clone_value(he->value) : he->value;
549
+ h_set(ht_clone, key, value);
550
+ i--;
551
+ }
552
+ }
553
+ return ht_clone;
554
+ }
555
+
556
+ void h_str_print_keys(HashTable *ht)
557
+ {
558
+ HashEntry *he;
559
+ int i = ht->size;
560
+ printf("keys:\n");
561
+ for (he = ht->table; i > 0; he++) {
562
+ if (he->key && he->key != dummy_key) { /* active entry */
563
+ printf("\t%s\n", (char *)he->key);
564
+ i--;
565
+ }
566
+ }
567
+ }