ferret 0.9.6 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (295) hide show
  1. data/MIT-LICENSE +1 -1
  2. data/README +12 -24
  3. data/Rakefile +38 -54
  4. data/TODO +14 -17
  5. data/ext/analysis.c +982 -823
  6. data/ext/analysis.h +133 -76
  7. data/ext/array.c +96 -58
  8. data/ext/array.h +40 -13
  9. data/ext/bitvector.c +476 -118
  10. data/ext/bitvector.h +264 -22
  11. data/ext/compound_io.c +217 -229
  12. data/ext/defines.h +49 -0
  13. data/ext/document.c +107 -317
  14. data/ext/document.h +31 -65
  15. data/ext/except.c +81 -36
  16. data/ext/except.h +117 -55
  17. data/ext/extconf.rb +2 -9
  18. data/ext/ferret.c +211 -104
  19. data/ext/ferret.h +22 -11
  20. data/ext/filter.c +97 -82
  21. data/ext/fs_store.c +348 -367
  22. data/ext/global.c +226 -188
  23. data/ext/global.h +44 -26
  24. data/ext/hash.c +474 -391
  25. data/ext/hash.h +441 -68
  26. data/ext/hashset.c +124 -96
  27. data/ext/hashset.h +169 -20
  28. data/ext/helper.c +56 -5
  29. data/ext/helper.h +7 -0
  30. data/ext/inc/lang.h +29 -49
  31. data/ext/inc/threading.h +31 -0
  32. data/ext/ind.c +288 -278
  33. data/ext/ind.h +68 -0
  34. data/ext/index.c +5688 -0
  35. data/ext/index.h +663 -616
  36. data/ext/lang.h +29 -49
  37. data/ext/libstemmer.c +3 -3
  38. data/ext/mem_pool.c +84 -0
  39. data/ext/mem_pool.h +35 -0
  40. data/ext/posh.c +1006 -0
  41. data/ext/posh.h +1007 -0
  42. data/ext/priorityqueue.c +117 -194
  43. data/ext/priorityqueue.h +135 -39
  44. data/ext/q_boolean.c +1305 -1108
  45. data/ext/q_const_score.c +106 -93
  46. data/ext/q_filtered_query.c +138 -135
  47. data/ext/q_fuzzy.c +206 -242
  48. data/ext/q_match_all.c +94 -80
  49. data/ext/q_multi_term.c +663 -0
  50. data/ext/q_parser.c +667 -593
  51. data/ext/q_phrase.c +992 -555
  52. data/ext/q_prefix.c +72 -61
  53. data/ext/q_range.c +235 -210
  54. data/ext/q_span.c +1480 -1166
  55. data/ext/q_term.c +273 -246
  56. data/ext/q_wildcard.c +127 -114
  57. data/ext/r_analysis.c +1720 -711
  58. data/ext/r_index.c +3049 -0
  59. data/ext/r_qparser.c +433 -146
  60. data/ext/r_search.c +2934 -1993
  61. data/ext/r_store.c +372 -143
  62. data/ext/r_utils.c +941 -0
  63. data/ext/ram_store.c +330 -326
  64. data/ext/search.c +1291 -668
  65. data/ext/search.h +403 -702
  66. data/ext/similarity.c +91 -113
  67. data/ext/similarity.h +45 -30
  68. data/ext/sort.c +721 -484
  69. data/ext/stopwords.c +361 -273
  70. data/ext/store.c +556 -58
  71. data/ext/store.h +706 -126
  72. data/ext/tags +3578 -2780
  73. data/ext/term_vectors.c +352 -0
  74. data/ext/threading.h +31 -0
  75. data/ext/win32.h +54 -0
  76. data/lib/ferret.rb +5 -17
  77. data/lib/ferret/document.rb +130 -2
  78. data/lib/ferret/index.rb +577 -26
  79. data/lib/ferret/number_tools.rb +157 -0
  80. data/lib/ferret_version.rb +3 -0
  81. data/test/test_helper.rb +5 -13
  82. data/test/unit/analysis/tc_analyzer.rb +513 -1
  83. data/test/unit/analysis/{ctc_tokenstream.rb → tc_token_stream.rb} +23 -0
  84. data/test/unit/index/tc_index.rb +183 -240
  85. data/test/unit/index/tc_index_reader.rb +312 -479
  86. data/test/unit/index/tc_index_writer.rb +397 -13
  87. data/test/unit/index/th_doc.rb +269 -206
  88. data/test/unit/query_parser/tc_query_parser.rb +40 -33
  89. data/test/unit/search/tc_filter.rb +59 -71
  90. data/test/unit/search/tc_fuzzy_query.rb +24 -16
  91. data/test/unit/search/tc_index_searcher.rb +23 -201
  92. data/test/unit/search/tc_multi_searcher.rb +78 -226
  93. data/test/unit/search/tc_search_and_sort.rb +93 -81
  94. data/test/unit/search/tc_sort.rb +23 -23
  95. data/test/unit/search/tc_sort_field.rb +7 -7
  96. data/test/unit/search/tc_spans.rb +51 -47
  97. data/test/unit/search/tm_searcher.rb +339 -0
  98. data/test/unit/store/tc_fs_store.rb +1 -1
  99. data/test/unit/store/tm_store_lock.rb +3 -3
  100. data/test/unit/tc_document.rb +81 -0
  101. data/test/unit/ts_analysis.rb +1 -1
  102. data/test/unit/ts_utils.rb +1 -1
  103. data/test/unit/utils/tc_bit_vector.rb +288 -0
  104. data/test/unit/utils/tc_number_tools.rb +117 -0
  105. data/test/unit/utils/tc_priority_queue.rb +106 -0
  106. metadata +140 -301
  107. data/CHANGELOG +0 -9
  108. data/ext/dummy.exe +0 -0
  109. data/ext/field.c +0 -408
  110. data/ext/frtio.h +0 -13
  111. data/ext/inc/except.h +0 -90
  112. data/ext/index_io.c +0 -382
  113. data/ext/index_rw.c +0 -2658
  114. data/ext/lang.c +0 -41
  115. data/ext/nix_io.c +0 -134
  116. data/ext/q_multi_phrase.c +0 -380
  117. data/ext/r_doc.c +0 -582
  118. data/ext/r_index_io.c +0 -1021
  119. data/ext/r_term.c +0 -219
  120. data/ext/term.c +0 -820
  121. data/ext/termdocs.c +0 -611
  122. data/ext/vector.c +0 -637
  123. data/ext/w32_io.c +0 -150
  124. data/lib/ferret/analysis.rb +0 -11
  125. data/lib/ferret/analysis/analyzers.rb +0 -112
  126. data/lib/ferret/analysis/standard_tokenizer.rb +0 -71
  127. data/lib/ferret/analysis/token.rb +0 -100
  128. data/lib/ferret/analysis/token_filters.rb +0 -86
  129. data/lib/ferret/analysis/token_stream.rb +0 -26
  130. data/lib/ferret/analysis/tokenizers.rb +0 -112
  131. data/lib/ferret/analysis/word_list_loader.rb +0 -27
  132. data/lib/ferret/document/document.rb +0 -152
  133. data/lib/ferret/document/field.rb +0 -312
  134. data/lib/ferret/index/compound_file_io.rb +0 -338
  135. data/lib/ferret/index/document_writer.rb +0 -289
  136. data/lib/ferret/index/field_infos.rb +0 -279
  137. data/lib/ferret/index/fields_io.rb +0 -181
  138. data/lib/ferret/index/index.rb +0 -675
  139. data/lib/ferret/index/index_file_names.rb +0 -33
  140. data/lib/ferret/index/index_reader.rb +0 -503
  141. data/lib/ferret/index/index_writer.rb +0 -534
  142. data/lib/ferret/index/multi_reader.rb +0 -377
  143. data/lib/ferret/index/multiple_term_doc_pos_enum.rb +0 -98
  144. data/lib/ferret/index/segment_infos.rb +0 -130
  145. data/lib/ferret/index/segment_merge_info.rb +0 -49
  146. data/lib/ferret/index/segment_merge_queue.rb +0 -16
  147. data/lib/ferret/index/segment_merger.rb +0 -358
  148. data/lib/ferret/index/segment_reader.rb +0 -412
  149. data/lib/ferret/index/segment_term_enum.rb +0 -169
  150. data/lib/ferret/index/segment_term_vector.rb +0 -58
  151. data/lib/ferret/index/term.rb +0 -53
  152. data/lib/ferret/index/term_buffer.rb +0 -83
  153. data/lib/ferret/index/term_doc_enum.rb +0 -291
  154. data/lib/ferret/index/term_enum.rb +0 -52
  155. data/lib/ferret/index/term_info.rb +0 -37
  156. data/lib/ferret/index/term_infos_io.rb +0 -321
  157. data/lib/ferret/index/term_vector_offset_info.rb +0 -20
  158. data/lib/ferret/index/term_vectors_io.rb +0 -553
  159. data/lib/ferret/query_parser.rb +0 -312
  160. data/lib/ferret/query_parser/query_parser.tab.rb +0 -928
  161. data/lib/ferret/search.rb +0 -50
  162. data/lib/ferret/search/boolean_clause.rb +0 -100
  163. data/lib/ferret/search/boolean_query.rb +0 -299
  164. data/lib/ferret/search/boolean_scorer.rb +0 -294
  165. data/lib/ferret/search/caching_wrapper_filter.rb +0 -40
  166. data/lib/ferret/search/conjunction_scorer.rb +0 -99
  167. data/lib/ferret/search/disjunction_sum_scorer.rb +0 -205
  168. data/lib/ferret/search/exact_phrase_scorer.rb +0 -32
  169. data/lib/ferret/search/explanation.rb +0 -41
  170. data/lib/ferret/search/field_cache.rb +0 -215
  171. data/lib/ferret/search/field_doc.rb +0 -31
  172. data/lib/ferret/search/field_sorted_hit_queue.rb +0 -184
  173. data/lib/ferret/search/filter.rb +0 -11
  174. data/lib/ferret/search/filtered_query.rb +0 -130
  175. data/lib/ferret/search/filtered_term_enum.rb +0 -79
  176. data/lib/ferret/search/fuzzy_query.rb +0 -154
  177. data/lib/ferret/search/fuzzy_term_enum.rb +0 -247
  178. data/lib/ferret/search/hit_collector.rb +0 -34
  179. data/lib/ferret/search/hit_queue.rb +0 -11
  180. data/lib/ferret/search/index_searcher.rb +0 -200
  181. data/lib/ferret/search/match_all_query.rb +0 -104
  182. data/lib/ferret/search/multi_phrase_query.rb +0 -216
  183. data/lib/ferret/search/multi_searcher.rb +0 -261
  184. data/lib/ferret/search/multi_term_query.rb +0 -65
  185. data/lib/ferret/search/non_matching_scorer.rb +0 -22
  186. data/lib/ferret/search/phrase_positions.rb +0 -55
  187. data/lib/ferret/search/phrase_query.rb +0 -214
  188. data/lib/ferret/search/phrase_scorer.rb +0 -152
  189. data/lib/ferret/search/prefix_query.rb +0 -54
  190. data/lib/ferret/search/query.rb +0 -140
  191. data/lib/ferret/search/query_filter.rb +0 -51
  192. data/lib/ferret/search/range_filter.rb +0 -103
  193. data/lib/ferret/search/range_query.rb +0 -139
  194. data/lib/ferret/search/req_excl_scorer.rb +0 -125
  195. data/lib/ferret/search/req_opt_sum_scorer.rb +0 -70
  196. data/lib/ferret/search/score_doc.rb +0 -38
  197. data/lib/ferret/search/score_doc_comparator.rb +0 -114
  198. data/lib/ferret/search/scorer.rb +0 -91
  199. data/lib/ferret/search/similarity.rb +0 -278
  200. data/lib/ferret/search/sloppy_phrase_scorer.rb +0 -47
  201. data/lib/ferret/search/sort.rb +0 -112
  202. data/lib/ferret/search/sort_comparator.rb +0 -60
  203. data/lib/ferret/search/sort_field.rb +0 -91
  204. data/lib/ferret/search/spans.rb +0 -12
  205. data/lib/ferret/search/spans/near_spans_enum.rb +0 -304
  206. data/lib/ferret/search/spans/span_first_query.rb +0 -79
  207. data/lib/ferret/search/spans/span_near_query.rb +0 -108
  208. data/lib/ferret/search/spans/span_not_query.rb +0 -130
  209. data/lib/ferret/search/spans/span_or_query.rb +0 -176
  210. data/lib/ferret/search/spans/span_query.rb +0 -25
  211. data/lib/ferret/search/spans/span_scorer.rb +0 -74
  212. data/lib/ferret/search/spans/span_term_query.rb +0 -105
  213. data/lib/ferret/search/spans/span_weight.rb +0 -84
  214. data/lib/ferret/search/spans/spans_enum.rb +0 -44
  215. data/lib/ferret/search/term_query.rb +0 -128
  216. data/lib/ferret/search/term_scorer.rb +0 -183
  217. data/lib/ferret/search/top_docs.rb +0 -36
  218. data/lib/ferret/search/top_field_docs.rb +0 -17
  219. data/lib/ferret/search/weight.rb +0 -54
  220. data/lib/ferret/search/wildcard_query.rb +0 -26
  221. data/lib/ferret/search/wildcard_term_enum.rb +0 -61
  222. data/lib/ferret/stemmers.rb +0 -1
  223. data/lib/ferret/stemmers/porter_stemmer.rb +0 -218
  224. data/lib/ferret/store.rb +0 -5
  225. data/lib/ferret/store/buffered_index_io.rb +0 -190
  226. data/lib/ferret/store/directory.rb +0 -141
  227. data/lib/ferret/store/fs_store.rb +0 -381
  228. data/lib/ferret/store/index_io.rb +0 -245
  229. data/lib/ferret/store/ram_store.rb +0 -286
  230. data/lib/ferret/utils.rb +0 -8
  231. data/lib/ferret/utils/bit_vector.rb +0 -123
  232. data/lib/ferret/utils/date_tools.rb +0 -138
  233. data/lib/ferret/utils/number_tools.rb +0 -91
  234. data/lib/ferret/utils/parameter.rb +0 -41
  235. data/lib/ferret/utils/priority_queue.rb +0 -120
  236. data/lib/ferret/utils/string_helper.rb +0 -47
  237. data/lib/ferret/utils/thread_local.rb +0 -28
  238. data/lib/ferret/utils/weak_key_hash.rb +0 -60
  239. data/lib/rferret.rb +0 -37
  240. data/rake_utils/code_statistics.rb +0 -106
  241. data/test/benchmark/tb_ram_store.rb +0 -76
  242. data/test/benchmark/tb_rw_vint.rb +0 -26
  243. data/test/functional/thread_safety_index_test.rb +0 -81
  244. data/test/functional/thread_safety_test.rb +0 -137
  245. data/test/longrunning/tc_numbertools.rb +0 -60
  246. data/test/longrunning/tm_store.rb +0 -19
  247. data/test/unit/analysis/ctc_analyzer.rb +0 -532
  248. data/test/unit/analysis/data/wordfile +0 -6
  249. data/test/unit/analysis/rtc_letter_tokenizer.rb +0 -20
  250. data/test/unit/analysis/rtc_lower_case_filter.rb +0 -20
  251. data/test/unit/analysis/rtc_lower_case_tokenizer.rb +0 -27
  252. data/test/unit/analysis/rtc_per_field_analyzer_wrapper.rb +0 -39
  253. data/test/unit/analysis/rtc_porter_stem_filter.rb +0 -16
  254. data/test/unit/analysis/rtc_standard_analyzer.rb +0 -20
  255. data/test/unit/analysis/rtc_standard_tokenizer.rb +0 -20
  256. data/test/unit/analysis/rtc_stop_analyzer.rb +0 -20
  257. data/test/unit/analysis/rtc_stop_filter.rb +0 -14
  258. data/test/unit/analysis/rtc_white_space_analyzer.rb +0 -21
  259. data/test/unit/analysis/rtc_white_space_tokenizer.rb +0 -20
  260. data/test/unit/analysis/rtc_word_list_loader.rb +0 -32
  261. data/test/unit/analysis/tc_token.rb +0 -25
  262. data/test/unit/document/rtc_field.rb +0 -28
  263. data/test/unit/document/tc_document.rb +0 -47
  264. data/test/unit/document/tc_field.rb +0 -98
  265. data/test/unit/index/rtc_compound_file_io.rb +0 -107
  266. data/test/unit/index/rtc_field_infos.rb +0 -127
  267. data/test/unit/index/rtc_fields_io.rb +0 -167
  268. data/test/unit/index/rtc_multiple_term_doc_pos_enum.rb +0 -83
  269. data/test/unit/index/rtc_segment_infos.rb +0 -74
  270. data/test/unit/index/rtc_segment_term_docs.rb +0 -17
  271. data/test/unit/index/rtc_segment_term_enum.rb +0 -60
  272. data/test/unit/index/rtc_segment_term_vector.rb +0 -71
  273. data/test/unit/index/rtc_term_buffer.rb +0 -57
  274. data/test/unit/index/rtc_term_info.rb +0 -19
  275. data/test/unit/index/rtc_term_infos_io.rb +0 -192
  276. data/test/unit/index/rtc_term_vectors_io.rb +0 -108
  277. data/test/unit/index/tc_term.rb +0 -27
  278. data/test/unit/index/tc_term_voi.rb +0 -18
  279. data/test/unit/search/rtc_similarity.rb +0 -37
  280. data/test/unit/search/rtc_sort_field.rb +0 -14
  281. data/test/unit/search/tc_multi_searcher2.rb +0 -126
  282. data/test/unit/store/rtc_fs_store.rb +0 -62
  283. data/test/unit/store/rtc_ram_store.rb +0 -15
  284. data/test/unit/store/rtm_store.rb +0 -150
  285. data/test/unit/store/rtm_store_lock.rb +0 -2
  286. data/test/unit/ts_document.rb +0 -2
  287. data/test/unit/utils/rtc_bit_vector.rb +0 -73
  288. data/test/unit/utils/rtc_date_tools.rb +0 -50
  289. data/test/unit/utils/rtc_number_tools.rb +0 -59
  290. data/test/unit/utils/rtc_parameter.rb +0 -40
  291. data/test/unit/utils/rtc_priority_queue.rb +0 -62
  292. data/test/unit/utils/rtc_string_helper.rb +0 -21
  293. data/test/unit/utils/rtc_thread.rb +0 -61
  294. data/test/unit/utils/rtc_weak_key_hash.rb +0 -25
  295. data/test/utils/number_to_spoken.rb +0 -132
data/ext/global.h CHANGED
@@ -1,38 +1,36 @@
1
1
  #ifndef FRT_GLOBAL_H
2
2
  #define FRT_GLOBAL_H
3
3
 
4
+ #include "defines.h"
5
+ #include "except.h"
6
+ #include "lang.h"
4
7
  #include <stdlib.h>
5
8
  #include <stdio.h>
6
- #include <assert.h>
7
- /*
8
- #define DEBUG
9
- #define VALGRIND
10
- */
11
- #define false 0
12
- #define true 1
9
+ #include <stdarg.h>
13
10
 
14
- typedef unsigned int bool;
15
- typedef unsigned char uchar;
16
- typedef unsigned int uint;
11
+ #define MAX_WORD_SIZE 255
12
+ #define MAX_FILE_PATH 1024
17
13
 
18
14
  typedef void (*free_ft)(void *key);
19
15
 
20
- #include "lang.h"
21
- #include "except.h"
22
-
23
- #define ref(obj) obj->ref_cnt++
24
- #define deref(obj) obj->ref_cnt--
16
+ #define NELEMS(array) ((int)(sizeof(array)/sizeof(array[0])))
25
17
 
26
- #define MAX_WORD_SIZE 255
27
- #define MAX_FILE_PATH 1024
28
- #define MAX_BUFFER_SIZE 1024
29
- #define ARRAY_INIT_SIZE 4
30
18
 
31
- #define NELEMS(array) sizeof(array)/sizeof(array[0])
19
+ #define ZEROSET(ptr, type) memset(ptr, 0, sizeof(type))
20
+ #define ZEROSET_N(ptr, type, n) memset(ptr, 0, sizeof(type)*(n))
32
21
 
33
- #define ZEROSET(ptr, type, n) memset(ptr, 0, sizeof(type)*(n))
22
+ /*
34
23
  #define ALLOC_AND_ZERO(type) (type*)memset(emalloc(sizeof(type)), 0, sizeof(type))
35
- #define ALLOC_AND_ZERO_N(type,n) (type*)ZEROSET(emalloc(sizeof(type)*(n)), type, n)
24
+ #define ALLOC_AND_ZERO_N(type,n) (type*)memset(emalloc(sizeof(type)*(n)), 0, sizeof(type)*(n))
25
+ */
26
+ #define ALLOC_AND_ZERO(type) (type*)frt_calloc(sizeof(type))
27
+ #define ALLOC_AND_ZERO_N(type,n) (type*)frt_calloc(sizeof(type)*(n))
28
+
29
+ #define REF(a) (a)->ref_cnt++
30
+ #define DEREF(a) (a)->ref_cnt--
31
+
32
+ #define NEXT_NUM(index, size) (((index) + 1) % (size))
33
+ #define PREV_NUM(index, size) (((index) + (size) - 1) % (size))
36
34
 
37
35
  #define MIN(a, b) ((a) < (b) ? (a) : (b))
38
36
  #define MAX(a, b) ((a) > (b) ? (a) : (b))
@@ -43,8 +41,8 @@ typedef void (*free_ft)(void *key);
43
41
  #define RECAPA(self, len, capa, ptr, type) \
44
42
  do {\
45
43
  if (self->len >= self->capa) {\
46
- if (self->capa) {\
47
- self->capa *= 2;\
44
+ if (self->capa > 0) {\
45
+ self->capa <<= 1;\
48
46
  } else {\
49
47
  self->capa = 4;\
50
48
  }\
@@ -55,10 +53,13 @@ typedef void (*free_ft)(void *key);
55
53
  #define Jx fprintf(stderr,"%s, %d: %s\n", __FILE__, __LINE__, __func__);
56
54
  #define Xj fprintf(stdout,"%s, %d: %s\n", __FILE__, __LINE__, __func__);
57
55
 
56
+ extern char *progname();
57
+ extern void setprogname(const char *str);
58
+
58
59
  extern void *emalloc(size_t n);
60
+ extern void *ecalloc(size_t n);
59
61
  extern void *erealloc(void *ptr, size_t n);
60
62
  extern char *estrdup(const char *s);
61
- extern char *epstrdup(const char *fmt, int len, ...);
62
63
  extern char *estrcat(char *str, char *str_cat);
63
64
 
64
65
  extern const char *EMPTY_STRING;
@@ -73,6 +74,23 @@ extern int max2(int a, int b);
73
74
  extern int max3(int a, int b, int c);
74
75
 
75
76
  extern char *dbl_to_s(char *buf, double num);
76
- extern void lower_str(char *str);
77
77
  extern char *strfmt(const char *fmt, ...);
78
+ extern char *vstrfmt(const char *fmt, va_list args);
79
+
80
+ /**
81
+ * A dummy function which can be passed to functions which expect a free
82
+ * function such as h_new() if you don't want the free functions to do anything.
83
+ * This function will do nothing.
84
+ *
85
+ * @param p the object which this function will be called on.
86
+ */
87
+ extern void dummy_free(void *p);
88
+
89
+ #ifdef DEBUG
90
+ extern bool x_do_logging;
91
+ #define xlog if (x_do_logging) printf
92
+ #else
93
+ #define xlog()
94
+ #endif
95
+
78
96
  #endif
data/ext/hash.c CHANGED
@@ -1,477 +1,560 @@
1
- #include <hash.h>
2
- #include <global.h>
1
+ #include "hash.h"
2
+ #include "global.h"
3
3
  #include <string.h>
4
4
 
5
- unsigned int hash(const char *str)
6
- {
7
- register unsigned int h;
8
- register unsigned char *p;
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 = "";
9
14
 
10
- h = 0;
11
- for (p = (unsigned char *) str; *p != '\0'; p++)
12
- h = MULTIPLIER * h + *p;
15
+ #define PERTURB_SHIFT 5
16
+ #define MAX_FREE_HASH_TABLES 80
13
17
 
14
- return h % NUM_ENTRIES;
18
+ static HashTable *free_hts[MAX_FREE_HASH_TABLES];
19
+ static int num_free_hts = 0;
20
+
21
+ ulong *imalloc(ulong value)
22
+ {
23
+ ulong *p = ALLOC(ulong);
24
+ *p = value;
25
+ return p;
15
26
  }
16
27
 
17
- HashEntry **ht_create()
28
+ ulong str_hash(const char *const str)
18
29
  {
19
- int i;
20
- HashEntry **new_ht = ALLOC_N(HashEntry *, NUM_ENTRIES);
30
+ register ulong h = 0;
31
+ register unsigned char *p = (unsigned char *) str;
21
32
 
22
- for (i = 0; i < NUM_ENTRIES; i++)
23
- new_ht[i] = NULL;
33
+ for (; *p; p++) {
34
+ h = 37 * h + *p;
35
+ }
24
36
 
25
- return new_ht;
37
+ return h;
26
38
  }
27
39
 
28
- int ht_count(HashEntry **ht)
40
+ static int int_eq(const void *q1, const void *q2)
29
41
  {
30
- int i, cnt=0;
31
- HashEntry *he;
32
- for (i = 0; i < NUM_ENTRIES; i++) {
33
- for (he = ht[i]; he != NULL; he = he->next) {
34
- cnt++;
35
- }
36
- }
37
- return cnt;
42
+ (void)q1;
43
+ (void)q2;
44
+ return true;
38
45
  }
39
46
 
40
- void ht_destroy_all(HashEntry **ht, void (*fn)(void *))
47
+ static ulong int_hash(const void *i)
41
48
  {
42
- int i;
43
- HashEntry *he, *he_tmp;
44
- for (i = 0; i < NUM_ENTRIES; i++) {
45
- for (he = ht[i]; he != NULL;) {
46
- he_tmp = he;
47
- he = he->next;
48
- fn(he_tmp->value);
49
- free(he_tmp->name);
50
- free(he_tmp);
51
- }
52
- }
53
- free(ht);
49
+ return *((ulong *)i);
54
50
  }
55
51
 
56
- void ht_destroy(HashEntry **ht)
52
+ typedef HashEntry *(*lookup_ft)(struct HashTable *ht, register const void *key);
53
+
54
+ /**
55
+ * Fast lookup function for resizing as we know there are no equal elements or
56
+ * deletes to worry about.
57
+ *
58
+ * @param ht the HashTable to do the fast lookup in
59
+ * @param the hashkey we are looking for
60
+ */
61
+ static inline HashEntry *h_resize_lookup(HashTable *ht, register const ulong hash)
57
62
  {
58
- int i;
59
- HashEntry *he, *he_tmp;
60
- for (i = 0; i < NUM_ENTRIES; i++) {
61
- for (he = ht[i]; he != NULL;) {
62
- he_tmp = he;
63
- he = he->next;
64
- free(he_tmp->name);
65
- free(he_tmp);
66
- }
67
- }
68
- free(ht);
63
+ register ulong perturb;
64
+ register int mask = ht->mask;
65
+ register HashEntry *he0 = ht->table;
66
+ register int i = hash & mask;
67
+ register HashEntry *he = &he0[i];
68
+
69
+ if (he->key == NULL) {
70
+ he->hash = hash;
71
+ return he;
72
+ }
73
+
74
+ for (perturb = hash;; perturb >>= PERTURB_SHIFT) {
75
+ i = (i << 2) + i + perturb + 1;
76
+ he = &he0[i & mask];
77
+ if (he->key == NULL) {
78
+ he->hash = hash;
79
+ return he;
80
+ }
81
+ }
69
82
  }
70
83
 
71
- void *ht_get(HashEntry **ht, char *name)
84
+ HashEntry *h_lookup_int(HashTable *ht, const void *key)
72
85
  {
73
- HashEntry *he;
74
- int h = hash(name);
75
-
76
- for (he = ht[h]; he != NULL; he = he->next) {
77
- if (strcmp(name, he->name) == 0) {
78
- return he->value;
86
+ register ulong hash = *((int *)key);
87
+ register ulong perturb;
88
+ register int mask = ht->mask;
89
+ register HashEntry *he0 = ht->table;
90
+ register int i = hash & mask;
91
+ register HashEntry *he = &he0[i];
92
+ register HashEntry *freeslot = NULL;
93
+
94
+ if (he->key == NULL || he->hash == hash) {
95
+ he->hash = hash;
96
+ return he;
97
+ }
98
+ if (he->key == dummy_key) {
99
+ freeslot = he;
79
100
  }
80
- }
81
101
 
82
- return NULL;
102
+ for (perturb = hash;; perturb >>= PERTURB_SHIFT) {
103
+ i = (i << 2) + i + perturb + 1;
104
+ he = &he0[i & mask];
105
+ if (he->key == NULL) {
106
+ if (freeslot != NULL) {
107
+ he = freeslot;
108
+ }
109
+ he->hash = hash;
110
+ return he;
111
+ }
112
+ if (he->hash == hash) {
113
+ return he;
114
+ }
115
+ if (he->key == dummy_key && freeslot == NULL) {
116
+ freeslot = he;
117
+ }
118
+ }
83
119
  }
84
120
 
85
- void ht_set(HashEntry **ht, char *name, void *value)
121
+ HashEntry *h_lookup_str(HashTable *ht, register const char *key)
86
122
  {
87
- HashEntry *he;
88
- int h = hash(name);
89
-
90
- for (he = ht[h]; he != NULL; he = he->next) {
91
- if (strcmp(name, he->name) == 0) {
92
- he->value = value;
93
- return;
94
- }
95
- }
96
-
97
- he = ALLOC(HashEntry);
98
- he->name = estrdup(name);
99
- he->value = value;
100
- he->next = ht[h];
101
- ht[h] = he;
102
- return;
123
+ register ulong hash = str_hash(key);
124
+ register ulong perturb;
125
+ register int mask = ht->mask;
126
+ register HashEntry *he0 = ht->table;
127
+ register int i = hash & mask;
128
+ register HashEntry *he = &he0[i];
129
+ register HashEntry *freeslot;
130
+
131
+ if (he->key == NULL || he->key == key) {
132
+ he->hash = hash;
133
+ return he;
134
+ }
135
+ if (he->key == dummy_key) {
136
+ freeslot = he;
137
+ }
138
+ else {
139
+ if ((he->hash == hash) && (strcmp(he->key, key) == 0)) {
140
+ return he;
141
+ }
142
+ freeslot = NULL;
143
+ }
144
+
145
+ for (perturb = hash;; perturb >>= PERTURB_SHIFT) {
146
+ i = (i << 2) + i + perturb + 1;
147
+ he = &he0[i & mask];
148
+ if (he->key == NULL) {
149
+ if (freeslot != NULL) {
150
+ he = freeslot;
151
+ }
152
+ he->hash = hash;
153
+ return he;
154
+ }
155
+ if (he->key == key
156
+ || (he->hash == hash
157
+ && he->key != dummy_key && strcmp(he->key, key) == 0)) {
158
+ return he;
159
+ }
160
+ if (he->key == dummy_key && freeslot == NULL) {
161
+ freeslot = he;
162
+ }
163
+ }
103
164
  }
104
165
 
105
- void *ht_delete(HashEntry **ht, char *name)
166
+ HashEntry *h_lookup(HashTable *ht, register const void *key)
106
167
  {
107
- HashEntry *he, *tmp;
108
- void *rval;
109
-
110
- int h = hash(name);
111
-
112
- if (ht[h] == NULL)
113
- return NULL;
114
-
115
- if (strcmp(ht[h]->name, name) == 0) {
116
- tmp = ht[h];
117
- ht[h] = tmp->next;
118
- rval = tmp->value;
119
- free(tmp->name);
120
- free(tmp);
121
- return rval;
122
- }
123
-
124
- for (he = ht[h]; he != NULL; he = he->next) {
125
- if (he->next != NULL && strcmp(name, he->next->name) == 0) {
126
- tmp = he->next;
127
- he->next = tmp->next;
128
- rval = tmp->value;
129
- free(tmp->name);
130
- free(tmp);
131
- return rval;
132
- }
133
- }
134
- return NULL;
168
+ register unsigned int hash = ht->hash_i(key);
169
+ register unsigned int perturb;
170
+ register int mask = ht->mask;
171
+ register HashEntry *he0 = ht->table;
172
+ register int i = hash & mask;
173
+ register HashEntry *he = &he0[i];
174
+ register HashEntry *freeslot;
175
+ eq_ft eq = ht->eq_i;
176
+
177
+ if (he->key == NULL || he->key == key) {
178
+ he->hash = hash;
179
+ return he;
180
+ }
181
+ if (he->key == dummy_key) {
182
+ freeslot = he;
183
+ }
184
+ else {
185
+ if ((he->hash == hash) && eq(he->key, key)) {
186
+ return he;
187
+ }
188
+ freeslot = NULL;
189
+ }
190
+
191
+ for (perturb = hash;; perturb >>= PERTURB_SHIFT) {
192
+ i = (i << 2) + i + perturb + 1;
193
+ he = &he0[i & mask];
194
+ if (he->key == NULL) {
195
+ if (freeslot != NULL) {
196
+ he = freeslot;
197
+ }
198
+ he->hash = hash;
199
+ return he;
200
+ }
201
+ if (he->key == key
202
+ || (he->hash == hash
203
+ && he->key != dummy_key && eq(he->key, key))) {
204
+ return he;
205
+ }
206
+ if (he->key == dummy_key && freeslot == NULL) {
207
+ freeslot = he;
208
+ }
209
+ }
135
210
  }
136
211
 
137
- /****************************************************************************
138
- *
139
- * HshTable
140
- *
141
- ****************************************************************************/
212
+ HashTable *h_new_str(free_ft free_key, free_ft free_value)
213
+ {
214
+ HashTable *ht;
215
+ if (num_free_hts > 0) {
216
+ ht = free_hts[--num_free_hts];
217
+ }
218
+ else {
219
+ ht = ALLOC(HashTable);
220
+ }
221
+ ht->fill = 0;
222
+ ht->size = 0;
223
+ ht->mask = HASH_MINSIZE - 1;
224
+ ht->table = ht->smalltable;
225
+ memset(ht->smalltable, 0, sizeof(ht->smalltable));
226
+ ht->lookup_i = (lookup_ft)&h_lookup_str;
227
+
228
+ ht->free_key_i = free_key != NULL ? free_key : &dummy_free;
229
+ ht->free_value_i = free_value != NULL ? free_value : &dummy_free;
230
+ return ht;
231
+ }
142
232
 
143
- char *dummy_key = "";
233
+ HashTable *h_new_int(free_ft free_value)
234
+ {
235
+ HashTable *ht = h_new_str(NULL, free_value);
236
+ ht->lookup_i = &h_lookup_int;
237
+ ht->eq_i = int_eq;
238
+ ht->hash_i = int_hash;
239
+ return ht;
240
+ }
144
241
 
145
- #define PERTURB_SHIFT 5
242
+ HashTable *h_new(hash_ft hash, eq_ft eq, free_ft free_key, free_ft free_value)
243
+ {
244
+ HashTable *ht = h_new_str(free_key, free_value);
146
245
 
147
- #ifdef VALGRIND
148
- #define MAX_FREE_HASH_TABLES 0
149
- #else
150
- #define MAX_FREE_HASH_TABLES 80
151
- #endif
246
+ ht->lookup_i = &h_lookup;
247
+ ht->eq_i = eq;
248
+ ht->hash_i = hash;
249
+ return ht;
250
+ }
152
251
 
153
- static HshTable *free_hts[MAX_FREE_HASH_TABLES];
154
- static int num_free_hts = 0;
252
+ void h_clear(HashTable *ht)
253
+ {
254
+ int i;
255
+ HashEntry *he;
256
+ free_ft free_key = ht->free_key_i;
257
+ free_ft free_value = ht->free_value_i;
258
+
259
+ /* Clear all the hash values and keys as necessary */
260
+ if (free_key != dummy_free || free_value != dummy_free) {
261
+ for (i = 0; i <= ht->mask; i++) {
262
+ he = &ht->table[i];
263
+ if (he->key != NULL && he->key != dummy_key) {
264
+ free_value(he->value);
265
+ free_key(he->key);
266
+ }
267
+ he->key = NULL;
268
+ }
269
+ }
270
+ ZEROSET_N(ht->table, HashEntry, ht->mask + 1);
271
+ ht->size = 0;
272
+ ht->fill = 0;
273
+ }
155
274
 
156
- inline unsigned int str_hash(const char *const str)
275
+ void h_destroy(HashTable *ht)
157
276
  {
158
- register unsigned int h=0;
159
- register unsigned char *p = (unsigned char *)str;
277
+ h_clear(ht);
160
278
 
161
- for (; *p; p++)
162
- h = 37 * h + *p;
279
+ /* if a new table was created, be sure to free it */
280
+ if (ht->table != ht->smalltable) {
281
+ free(ht->table);
282
+ }
163
283
 
164
- return h;
284
+ #ifdef DEBUG
285
+ free(ht);
286
+ #else
287
+ if (num_free_hts < MAX_FREE_HASH_TABLES) {
288
+ free_hts[num_free_hts++] = ht;
289
+ }
290
+ else {
291
+ free(ht);
292
+ }
293
+ #endif
165
294
  }
166
295
 
167
- HshEntry *h_lookup_str(HshTable *ht, register const void *key_p)
296
+ void *h_get(HashTable *ht, const void *key)
168
297
  {
169
- register char *key = (char *)key_p;
170
- register unsigned int hash = str_hash(key);
171
- register unsigned int perturb;
172
- register int mask = ht->mask;
173
- register HshEntry *he0 = ht->table;
174
- register int i = hash & mask;
175
- register HshEntry *he = &he0[i];
176
- register HshEntry *freeslot;
177
-
178
- if (he->key == NULL || he->key == key) {
179
- he->hash = hash;
180
- return he;
181
- }
182
- if (he->key == dummy_key) {
183
- freeslot = he;
184
- } else {
185
- if ((he->hash == hash) && (strcmp(he->key, key) == 0)) {
186
- return he;
187
- }
188
- freeslot = NULL;
189
- }
190
-
191
- for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {
192
- i = (i << 2) + i + perturb + 1;
193
- he = &he0[i & mask];
194
- if (he->key == NULL) {
195
- if (freeslot != NULL) he = freeslot;
196
- he->hash = hash;
197
- return he;
198
- }
199
- if (he->key == key
200
- || (he->hash == hash
201
- && he->key != dummy_key
202
- && strcmp(he->key, key) == 0))
203
- return he;
204
- if (he->key == dummy_key && freeslot == NULL)
205
- freeslot = he;
206
- }
298
+ /* Note: lookup_i will never return NULL. */
299
+ return ht->lookup_i(ht, key)->value;
207
300
  }
208
301
 
209
- typedef int (*eq_func)(const void *key1, const void *key2);
210
-
211
- HshEntry *h_lookup(HshTable *ht, register const void *key)
302
+ int h_del(HashTable *ht, const void *key)
212
303
  {
213
- register unsigned int hash = ht->hash(key);
214
- register unsigned int perturb;
215
- register int mask = ht->mask;
216
- register HshEntry *he0 = ht->table;
217
- register int i = hash & mask;
218
- register HshEntry *he = &he0[i];
219
- register HshEntry *freeslot;
220
- eq_func eq = ht->eq;
221
-
222
- if (he->key == NULL || he->key == key) {
223
- he->hash = hash;
224
- return he;
225
- }
226
- if (he->key == dummy_key) {
227
- freeslot = he;
228
- } else {
229
- if ((he->hash == hash) && eq(he->key, key))
230
- return he;
231
- freeslot = NULL;
232
- }
233
-
234
- for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {
235
- i = (i << 2) + i + perturb + 1;
236
- he = &he0[i & mask];
237
- if (he->key == NULL) {
238
- if (freeslot != NULL) he = freeslot;
239
- he->hash = hash;
240
- return he;
241
- }
242
- if (he->key == key
243
- || (he->hash == hash
244
- && he->key != dummy_key
245
- && eq(he->key, key)))
246
- return he;
247
- if (he->key == dummy_key && freeslot == NULL)
248
- freeslot = he;
249
- }
304
+ HashEntry *he = ht->lookup_i(ht, key);
305
+
306
+ if (he->key != NULL && he->key != dummy_key) {
307
+ ht->free_key_i(he->key);
308
+ ht->free_value_i(he->value);
309
+ he->key = dummy_key;
310
+ he->value = NULL;
311
+ ht->size--;
312
+ return true;
313
+ }
314
+ else {
315
+ return false;
316
+ }
250
317
  }
251
318
 
252
- typedef void (*free_func)(void *);
253
- void dummy_free(void *p)
254
- { }
319
+ void *h_rem(HashTable *ht, const void *key, bool destroy_key)
320
+ {
321
+ void *val;
322
+ HashEntry *he = ht->lookup_i(ht, key);
255
323
 
256
- HshTable *h_new_str(free_ft free_key, free_ft free_value)
324
+ if (he->key != NULL && he->key != dummy_key) {
325
+ if (destroy_key) {
326
+ ht->free_key_i(he->key);
327
+ }
328
+
329
+ he->key = dummy_key;
330
+ val = he->value;
331
+ he->value = NULL;
332
+ ht->size--;
333
+ return val;
334
+ }
335
+ else {
336
+ return NULL;
337
+ }
338
+ }
339
+
340
+ static int h_resize(HashTable *ht, int min_newsize)
257
341
  {
258
- HshTable *ht;
259
- if (num_free_hts > 0) {
260
- ht = free_hts[--num_free_hts];
261
- } else {
262
- ht = ALLOC(HshTable);
263
- }
264
- ht->fill = 0;
265
- ht->used = 0;
266
- ht->mask = Hsh_MINSIZE - 1;
267
- ht->table = ht->smalltable;
268
- memset(ht->smalltable, 0, sizeof(ht->smalltable));
269
- ht->lookup = &h_lookup_str;
270
- ht->free_key = free_key != NULL ? free_key : &dummy_free;
271
- ht->free_value = free_value != NULL ? free_value : &dummy_free;
272
- return ht;
342
+ HashEntry smallcopy[HASH_MINSIZE];
343
+ HashEntry *oldtable;
344
+ HashEntry *he_old, *he_new;
345
+ int newsize, num_active;
346
+
347
+ /* newsize will be a power of two */
348
+ for (newsize = HASH_MINSIZE; newsize < min_newsize; newsize <<= 1) {
349
+ }
350
+
351
+ oldtable = ht->table;
352
+ if (newsize == HASH_MINSIZE) {
353
+ if (ht->table == ht->smalltable) {
354
+ /* need to copy the d*(int *)ata out so we can rebuild the table into
355
+ * the same space */
356
+ memcpy(smallcopy, ht->smalltable, sizeof(smallcopy));
357
+ oldtable = smallcopy;
358
+ }
359
+ else {
360
+ ht->table = ht->smalltable;
361
+ }
362
+ }
363
+ else {
364
+ ht->table = ALLOC_N(HashEntry, newsize);
365
+ }
366
+ memset(ht->table, 0, sizeof(HashEntry) * newsize);
367
+ ht->fill = ht->size;
368
+ ht->mask = newsize - 1;
369
+
370
+ for (num_active = ht->size, he_old = oldtable; num_active > 0; he_old++) {
371
+ if (he_old->key && he_old->key != dummy_key) { /* active entry */
372
+ /*he_new = ht->lookup_i(ht, he_old->key); */
373
+ he_new = h_resize_lookup(ht, he_old->hash);
374
+ he_new->key = he_old->key;
375
+ he_new->value = he_old->value;
376
+ num_active--;
377
+ } /* else empty entry so nothing to do */
378
+ }
379
+ if (oldtable != smallcopy && oldtable != ht->smalltable) {
380
+ free(oldtable);
381
+ }
382
+ return 0;
273
383
  }
274
384
 
275
- HshTable *h_new(hash_ft hash, eq_ft eq, free_ft free_key, free_ft free_value)
385
+ int h_set(HashTable *ht, const void *key, void *value)
276
386
  {
277
- HshTable *ht = h_new_str(free_key, free_value);
387
+ int ret_val = HASH_KEY_DOES_NOT_EXIST;
388
+ HashEntry *he = ht->lookup_i(ht, key);
389
+ if (he->key == NULL) {
390
+ if (ht->fill * 3 > ht->mask * 2) {
391
+ h_resize(ht, ht->size * ((ht->size > SLOW_DOWN) ? 4 : 2));
392
+ he = ht->lookup_i(ht, key);
393
+ }
394
+ ht->fill++;
395
+ ht->size++;
396
+ }
397
+ else if (he->key == dummy_key) {
398
+ ht->size++;
399
+ }
400
+ else if (he->key != key) {
401
+ ht->free_key_i(he->key);
402
+ if (he->value != value) {
403
+ ht->free_value_i(he->value);
404
+ }
405
+ ret_val = HASH_KEY_EQUAL;
406
+ }
407
+ else {
408
+ /* safety check. Only free old value if it isn't the new value */
409
+ if (he->value != value) {
410
+ ht->free_value_i(he->value);
411
+ }
412
+ ret_val = HASH_KEY_SAME;
413
+ }
414
+ he->key = (void *)key;
415
+ he->value = value;
278
416
 
279
- ht->lookup = &h_lookup;
280
- ht->eq = eq;
281
- ht->hash = hash;
282
- return ht;
417
+ /*
418
+ if ((ht->fill > fill) && (ht->fill * 3 > ht->mask * 2)) {
419
+ h_resize(ht, ht->size * ((ht->size > SLOW_DOWN) ? 4 : 2));
420
+ }
421
+ */
422
+ return ret_val;
283
423
  }
284
424
 
285
- void h_clear(HshTable *ht)
425
+ HashEntry *h_set_ext(HashTable *ht, const void *key)
286
426
  {
287
- int i;
288
- HshEntry *he;
289
- free_func free_key = ht->free_key;
290
- free_func free_value = ht->free_value;
291
-
292
- /* Clear all the hash values and keys as necessary */
293
- for (i = 0; i <= ht->mask; i++) {
294
- he = &ht->table[i];
295
- if (he->key != NULL && he->key != dummy_key) {
296
- free_value(he->value);
297
- free_key(he->key);
298
- }
299
- he->key = NULL;
300
- }
301
- ht->used = 0;
302
- ht->fill = 0;
303
- /* for some reason the following line doesn't seem to help */
304
- /* ZEROSET(ht->table, HshEntry, ht->mask + 1); */
427
+ HashEntry *he = ht->lookup_i(ht, key);
428
+ if (he->key == NULL) {
429
+ if (ht->fill * 3 > ht->mask * 2) {
430
+ h_resize(ht, ht->size * ((ht->size > SLOW_DOWN) ? 4 : 2));
431
+ he = ht->lookup_i(ht, key);
432
+ }
433
+ ht->fill++;
434
+ ht->size++;
435
+ }
436
+ else if (he->key == dummy_key) {
437
+ ht->size++;
438
+ }
439
+
440
+ return he;
305
441
  }
306
442
 
307
- void h_destroy(HshTable *ht)
443
+ int h_set_safe(HashTable *ht, const void *key, void *value)
308
444
  {
309
- h_clear(ht);
445
+ HashEntry *he = ht->lookup_i(ht, key);
446
+ int fill = ht->fill;
447
+ if (he->key == NULL) {
448
+ ht->fill++;
449
+ ht->size++;
450
+ }
451
+ else if (he->key == dummy_key) {
452
+ ht->size++;
453
+ }
454
+ else {
455
+ return false;
456
+ }
457
+ he->key = (void *)key;
458
+ he->value = value;
310
459
 
311
- /* if a new table was created, be sure to free it */
312
- if (ht->table != ht->smalltable) free(ht->table);
460
+ if ((ht->fill > fill) && (ht->fill * 3 > ht->mask * 2)) {
461
+ h_resize(ht, ht->size * ((ht->size > SLOW_DOWN) ? 4 : 2));
462
+ }
463
+ return true;
464
+ }
313
465
 
314
- if (num_free_hts < MAX_FREE_HASH_TABLES) {
315
- free_hts[num_free_hts++] = ht;
316
- } else {
317
- free(ht);
318
- }
466
+ int h_has_key(HashTable *ht, const void *key)
467
+ {
468
+ HashEntry *he = ht->lookup_i(ht, key);
469
+ if (he->key == NULL || he->key == dummy_key) {
470
+ return HASH_KEY_DOES_NOT_EXIST;
471
+ }
472
+ else if (he->key == key) {
473
+ return HASH_KEY_SAME;
474
+ }
475
+ else {
476
+ return HASH_KEY_EQUAL;
477
+ }
319
478
  }
320
479
 
321
- void *h_get(HshTable *ht, const void *key)
480
+ void *h_get_int(HashTable *self, const ulong key)
322
481
  {
323
- return ht->lookup(ht, key)->value;
482
+ return h_get(self, &key);
324
483
  }
325
484
 
326
- int h_del(HshTable *ht, const void *key)
485
+ int h_del_int(HashTable *self, const ulong key)
327
486
  {
328
- HshEntry *he = ht->lookup(ht, key);
329
-
330
- if (he->key != NULL && he->key != dummy_key) {
331
- ht->free_key(he->key);
332
- ht->free_value(he->value);
333
- he->key = dummy_key;
334
- he->value = NULL;
335
- ht->used--;
336
- return true;
337
- } else {
338
- return false;
339
- }
487
+ return h_del(self, &key);
340
488
  }
341
489
 
342
- void *h_rem(HshTable *ht, const void *key, bool destory_key)
490
+ void *h_rem_int(HashTable *self, const ulong key)
343
491
  {
344
- void *val;
345
- HshEntry *he = ht->lookup(ht, key);
346
-
347
- if (he->key != NULL && he->key != dummy_key) {
348
- if (destory_key)
349
- ht->free_key(he->key);
350
-
351
- he->key = dummy_key;
352
- val = he->value;
353
- he->value = NULL;
354
- ht->used--;
355
- return val;
356
- } else {
357
- return NULL;
358
- }
492
+ return h_rem(self, &key, false);
359
493
  }
360
494
 
361
- int h_resize(HshTable *ht, int min_newsize) {
362
- HshEntry smallcopy[Hsh_MINSIZE];
363
- HshEntry *oldtable;
364
- HshEntry *he_old, *he_new;
365
- int newsize, i;
366
-
367
- for (newsize = Hsh_MINSIZE; newsize < min_newsize; newsize <<= 1)
368
- ;
369
-
370
- oldtable = ht->table;
371
- if (newsize == Hsh_MINSIZE) {
372
- if (ht->table == ht->smalltable) {
373
- /* need to copy the d*(int *)ata out so we can rebuild the table into
374
- * the same space */
375
- memcpy(smallcopy, ht->smalltable, sizeof(smallcopy));
376
- oldtable = smallcopy;
377
- } else {
378
- ht->table = ht->smalltable;
379
- }
380
- } else {
381
- ht->table = ALLOC_N(HshEntry, newsize);
382
- }
383
- memset(ht->table, 0, sizeof(HshEntry) * newsize);
384
- i = ht->used;
385
- ht->fill = ht->used;
386
- ht->mask = newsize - 1;
387
-
388
- for (he_old = oldtable; i > 0; he_old++) {
389
- if (he_old->value != NULL) {/* active entry */
390
- he_new = ht->lookup(ht, he_old->key);
391
- he_new->key = he_old->key;
392
- he_new->value = he_old->value;
393
- i--;
394
- } /* else empty entry so nothing to do */
395
- }
396
- if (oldtable != smallcopy && oldtable != ht->smalltable)
397
- free(oldtable);
398
- return 0;
495
+ int h_set_int(HashTable *self, const ulong key, void *value)
496
+ {
497
+ return h_set(self, &key, value);
399
498
  }
400
499
 
401
- int h_set(HshTable *ht, const void *key, void *value)
500
+ int h_set_safe_int(HashTable *self, const ulong key, void *value)
402
501
  {
403
- int ret_val = HASH_KEY_DOES_NOT_EXIST;
404
- HshEntry *he = ht->lookup(ht, key);
405
- int fill = ht->fill;
406
- if (he->key == NULL) {
407
- ht->fill++;
408
- ht->used++;
409
- } else if (he->key == dummy_key) {
410
- ht->used++;
411
- } else if (he->key != key) {
412
- ht->free_key(he->key);
413
- if (he->value != value) ht->free_value(he->value);
414
- ret_val = HASH_KEY_EQUAL;
415
- } else {
416
- if (he->value != value) ht->free_value(he->value);
417
- ret_val = HASH_KEY_SAME;
418
- }
419
- he->key = (void *)key;
420
- he->value = value;
421
- if ((ht->fill > fill) && (ht->fill * 3 > ht->mask * 2))
422
- h_resize(ht, ht->used * ((ht->used > SLOW_DOWN) ? 4 : 2));
423
- return ret_val;
502
+ return h_set_safe(self, &key, value);
424
503
  }
425
504
 
426
- int h_has_key(HshTable *ht, const void *key)
505
+ int h_has_key_int(HashTable *self, const ulong key)
427
506
  {
428
- HshEntry *he = ht->lookup(ht, key);
429
- if (he->key == NULL || he->key == dummy_key) {
430
- return HASH_KEY_DOES_NOT_EXIST;
431
- } else if (he->key == key) {
432
- return HASH_KEY_SAME;
433
- } else {
434
- return HASH_KEY_EQUAL;
435
- }
507
+ return h_has_key(self, &key);
436
508
  }
437
509
 
438
- void h_each(HshTable *ht,
439
- void (*each_kv)(void *key, void *value, void *arg),
440
- void *arg)
510
+ void h_each(HashTable *ht,
511
+ void (*each_kv) (void *key, void *value, void *arg), void *arg)
441
512
  {
442
- HshEntry *he;
443
- int i = ht->used;
444
- for (he = ht->table; i > 0; he++) {
445
- if (he->value != NULL) {/* active entry */
446
- each_kv(he->key, he->value, arg);
447
- i--;
448
- }
449
- }
513
+ HashEntry *he;
514
+ int i = ht->size;
515
+ for (he = ht->table; i > 0; he++) {
516
+ if (he->key && he->key != dummy_key) { /* active entry */
517
+ each_kv(he->key, he->value, arg);
518
+ i--;
519
+ }
520
+ }
450
521
  }
451
522
 
452
- HshTable *h_clone(HshTable *ht,
453
- h_clone_func_t clone_key,
454
- h_clone_func_t clone_value)
523
+ HashTable *h_clone(HashTable *ht,
524
+ h_clone_func_t clone_key, h_clone_func_t clone_value)
455
525
  {
456
- void *key, *value;
457
- HshEntry *he;
458
- int i = ht->used;
459
- HshTable *ht_clone;
460
-
461
- if (ht->lookup == &h_lookup_str) {
462
- ht_clone = h_new_str(ht->free_key, ht->free_value);
463
- } else {
464
- ht_clone = h_new(ht->hash, ht->eq, ht->free_key, ht->free_value);
465
- }
466
-
467
- for (he = ht->table; i > 0; he++) {
468
- if (he->value != NULL) {/* active entry */
469
- key = clone_key ? clone_key(he->key) : he->key;
470
- value = clone_value ? clone_value(he->value) : he->value;
471
- h_set(ht_clone, key, value);
472
- i--;
473
- }
474
- }
475
- return ht_clone;
526
+ void *key, *value;
527
+ HashEntry *he;
528
+ int i = ht->size;
529
+ HashTable *ht_clone;
530
+
531
+ if (ht->lookup_i == (lookup_ft)&h_lookup_str) {
532
+ ht_clone = h_new_str(ht->free_key_i, ht->free_value_i);
533
+ }
534
+ else {
535
+ ht_clone = h_new(ht->hash_i, ht->eq_i, ht->free_key_i, ht->free_value_i);
536
+ }
537
+
538
+ for (he = ht->table; i > 0; he++) {
539
+ if (he->key && he->key != dummy_key) { /* active entry */
540
+ key = clone_key ? clone_key(he->key) : he->key;
541
+ value = clone_value ? clone_value(he->value) : he->value;
542
+ h_set(ht_clone, key, value);
543
+ i--;
544
+ }
545
+ }
546
+ return ht_clone;
476
547
  }
477
548
 
549
+ void h_str_print_keys(HashTable *ht)
550
+ {
551
+ HashEntry *he;
552
+ int i = ht->size;
553
+ printf("keys:\n");
554
+ for (he = ht->table; i > 0; he++) {
555
+ if (he->key && he->key != dummy_key) { /* active entry */
556
+ printf("\t%s\n", (char *)he->key);
557
+ i--;
558
+ }
559
+ }
560
+ }