1
2
3
4
5
6
7
8
9
10#ifndef _GHASH_H
11#define _GHASH_H
12
13
14
15#define DEF_HASH_FUZZY_STRUCTS(NAME,HASHSIZE,TYPE) \
16\
17struct NAME##_table {\
18 TYPE * hashtable[HASHSIZE];\
19 TYPE * sorted_list;\
20 int nr_entries;\
21};\
22\
23struct NAME##_ptrs {\
24 TYPE * next_hash;\
25 TYPE * prev_hash;\
26 TYPE * next_sorted;\
27 TYPE * prev_sorted;\
28};
29
30#define DEF_HASH_FUZZY(LINKAGE,NAME,HASHSIZE,TYPE,PTRS,KEYTYPE,KEY,KEYCMP,KEYEQ,HASHFN)\
31\
32LINKAGE void insert_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)\
33{\
34 int ix = HASHFN(elem->KEY);\
35 TYPE ** base = &tbl->hashtable[ix];\
36 TYPE * ptr = *base;\
37 TYPE * prev = NULL;\
38\
39 tbl->nr_entries++;\
40 while(ptr && KEYCMP(ptr->KEY, elem->KEY)) {\
41 base = &ptr->PTRS.next_hash;\
42 prev = ptr;\
43 ptr = *base;\
44 }\
45 elem->PTRS.next_hash = ptr;\
46 elem->PTRS.prev_hash = prev;\
47 if(ptr) {\
48 ptr->PTRS.prev_hash = elem;\
49 }\
50 *base = elem;\
51\
52 ptr = prev;\
53 if(!ptr) {\
54 ptr = tbl->sorted_list;\
55 prev = NULL;\
56 } else {\
57 prev = ptr->PTRS.prev_sorted;\
58 }\
59 while(ptr) {\
60 TYPE * next = ptr->PTRS.next_hash;\
61 if(next && KEYCMP(next->KEY, elem->KEY)) {\
62 prev = ptr;\
63 ptr = next;\
64 } else if(KEYCMP(ptr->KEY, elem->KEY)) {\
65 prev = ptr;\
66 ptr = ptr->PTRS.next_sorted;\
67 } else\
68 break;\
69 }\
70 elem->PTRS.next_sorted = ptr;\
71 elem->PTRS.prev_sorted = prev;\
72 if(ptr) {\
73 ptr->PTRS.prev_sorted = elem;\
74 }\
75 if(prev) {\
76 prev->PTRS.next_sorted = elem;\
77 } else {\
78 tbl->sorted_list = elem;\
79 }\
80}\
81\
82LINKAGE void remove_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)\
83{\
84 TYPE * next = elem->PTRS.next_hash;\
85 TYPE * prev = elem->PTRS.prev_hash;\
86\
87 tbl->nr_entries--;\
88 if(next)\
89 next->PTRS.prev_hash = prev;\
90 if(prev)\
91 prev->PTRS.next_hash = next;\
92 else {\
93 int ix = HASHFN(elem->KEY);\
94 tbl->hashtable[ix] = next;\
95 }\
96\
97 next = elem->PTRS.next_sorted;\
98 prev = elem->PTRS.prev_sorted;\
99 if(next)\
100 next->PTRS.prev_sorted = prev;\
101 if(prev)\
102 prev->PTRS.next_sorted = next;\
103 else\
104 tbl->sorted_list = next;\
105}\
106\
107LINKAGE TYPE * find_##NAME##_hash(struct NAME##_table * tbl, KEYTYPE pos)\
108{\
109 int ix = hashfn(pos);\
110 TYPE * ptr = tbl->hashtable[ix];\
111 while(ptr && KEYCMP(ptr->KEY, pos))\
112 ptr = ptr->PTRS.next_hash;\
113 if(ptr && !KEYEQ(ptr->KEY, pos))\
114 ptr = NULL;\
115 return ptr;\
116}\
117\
118LINKAGE TYPE * find_##NAME##_hash_fuzzy(struct NAME##_table * tbl, KEYTYPE pos)\
119{\
120 int ix;\
121 int offset;\
122 TYPE * ptr;\
123 TYPE * next;\
124\
125 ptr = tbl->sorted_list;\
126 if(!ptr || KEYCMP(pos, ptr->KEY))\
127 return NULL;\
128 ix = HASHFN(pos);\
129 offset = HASHSIZE;\
130 do {\
131 offset >>= 1;\
132 next = tbl->hashtable[(ix+offset) & ((HASHSIZE)-1)];\
133 if(next && (KEYCMP(next->KEY, pos) || KEYEQ(next->KEY, pos))\
134 && KEYCMP(ptr->KEY, next->KEY))\
135 ptr = next;\
136 } while(offset);\
137\
138 for(;;) {\
139 next = ptr->PTRS.next_hash;\
140 if(next) {\
141 if(KEYCMP(next->KEY, pos)) {\
142 ptr = next;\
143 continue;\
144 }\
145 }\
146 next = ptr->PTRS.next_sorted;\
147 if(next && KEYCMP(next->KEY, pos)) {\
148 ptr = next;\
149 continue;\
150 }\
151 return ptr;\
152 }\
153 return NULL;\
154}
155
156#define DEF_HASH_STRUCTS(NAME,HASHSIZE,TYPE) \
157\
158struct NAME##_table {\
159 TYPE * hashtable[HASHSIZE];\
160 int nr_entries;\
161};\
162\
163struct NAME##_ptrs {\
164 TYPE * next_hash;\
165 TYPE * prev_hash;\
166};
167
168#define DEF_HASH(LINKAGE,NAME,HASHSIZE,TYPE,PTRS,KEYTYPE,KEY,KEYCMP,KEYEQ,HASHFN)\
169\
170LINKAGE void insert_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)\
171{\
172 int ix = HASHFN(elem->KEY);\
173 TYPE ** base = &tbl->hashtable[ix];\
174 TYPE * ptr = *base;\
175 TYPE * prev = NULL;\
176\
177 tbl->nr_entries++;\
178 while(ptr && KEYCMP(ptr->KEY, elem->KEY)) {\
179 base = &ptr->PTRS.next_hash;\
180 prev = ptr;\
181 ptr = *base;\
182 }\
183 elem->PTRS.next_hash = ptr;\
184 elem->PTRS.prev_hash = prev;\
185 if(ptr) {\
186 ptr->PTRS.prev_hash = elem;\
187 }\
188 *base = elem;\
189}\
190\
191LINKAGE void remove_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)\
192{\
193 TYPE * next = elem->PTRS.next_hash;\
194 TYPE * prev = elem->PTRS.prev_hash;\
195\
196 tbl->nr_entries--;\
197 if(next)\
198 next->PTRS.prev_hash = prev;\
199 if(prev)\
200 prev->PTRS.next_hash = next;\
201 else {\
202 int ix = HASHFN(elem->KEY);\
203 tbl->hashtable[ix] = next;\
204 }\
205}\
206\
207LINKAGE TYPE * find_##NAME##_hash(struct NAME##_table * tbl, KEYTYPE pos)\
208{\
209 int ix = hashfn(pos);\
210 TYPE * ptr = tbl->hashtable[ix];\
211 while(ptr && KEYCMP(ptr->KEY, pos))\
212 ptr = ptr->PTRS.next_hash;\
213 if(ptr && !KEYEQ(ptr->KEY, pos))\
214 ptr = NULL;\
215 return ptr;\
216}
217
218#endif
219