1
1
#include <hl.h>
2
2
3
3
#define H_SIZE_INIT 7
4
+ #define H_CELL_SIZE 3
4
5
5
6
// successive primes that double every time
6
7
static int H_PRIMES [] = {
7
8
7 ,17 ,37 ,79 ,163 ,331 ,673 ,1361 ,2729 ,5471 ,10949 ,21911 ,43853 ,87613 ,175229 ,350459 ,700919 ,1401857 ,2803727 ,5607457 ,11214943 ,22429903 ,44859823 ,89719661 ,179424673 ,373587883 ,776531401 ,1611623773
8
9
};
9
10
10
11
typedef struct _hl_bytes_map hl_bytes_map ;
12
+ typedef struct _hl_bytes_cell hl_bytes_cell ;
13
+
14
+ struct _hl_bytes_cell {
15
+ int nvalues ;
16
+ int hashes [H_CELL_SIZE ];
17
+ uchar * strings [H_CELL_SIZE ];
18
+ vdynamic * values [H_CELL_SIZE ];
19
+ hl_bytes_cell * next ;
20
+ };
11
21
12
22
struct _hl_bytes_map {
13
- int _ ;
23
+ hl_bytes_cell * * cells ;
24
+ int ncells ;
25
+ int nentries ;
14
26
};
15
27
16
28
HL_PRIM hl_bytes_map * hl_hballoc () {
17
29
hl_bytes_map * m = (hl_bytes_map * )hl_gc_alloc (sizeof (hl_bytes_map ));
30
+ m -> ncells = H_SIZE_INIT ;
31
+ m -> nentries = 0 ;
32
+ m -> cells = (hl_bytes_cell * * )hl_gc_alloc (sizeof (hl_bytes_cell * )* m -> ncells );
33
+ memset (m -> cells ,0 ,m -> ncells * sizeof (void * ));
18
34
return m ;
19
35
}
20
36
21
- HL_PRIM void hl_hbset ( hl_bytes_map * m , vbytes * key , vdynamic * val ) {
37
+ static vdynamic * * hl_hbfind ( hl_bytes_map * m , uchar * key ) {
38
+ int hash = hl_hash_gen (key ,false);
39
+ int ckey = ((unsigned )hash ) % ((unsigned )m -> ncells );
40
+ hl_bytes_cell * c = m -> cells [ckey ];
41
+ int i ;
42
+ while ( c ) {
43
+ for (i = 0 ;i < c -> nvalues ;i ++ )
44
+ if ( c -> hashes [i ] == hash && ucmp (key ,c -> strings [i ]) == 0 )
45
+ return c -> values + i ;
46
+ c = c -> next ;
47
+ }
48
+ return NULL ;
22
49
}
23
50
51
+ static void hl_hbremap ( hl_bytes_map * m , uchar * key , int hash , vdynamic * value , hl_bytes_cell * * reuse ) {
52
+ int ckey = ((unsigned )hash ) % ((unsigned )m -> ncells );
53
+ hl_bytes_cell * c = m -> cells [ckey ];
54
+ if ( c && c -> nvalues < H_CELL_SIZE ) {
55
+ c -> hashes [c -> nvalues ] = hash ;
56
+ c -> strings [c -> nvalues ] = key ;
57
+ c -> values [c -> nvalues ] = value ;
58
+ return ;
59
+ }
60
+ c = * reuse ;
61
+ if ( c )
62
+ * reuse = c -> next ;
63
+ else
64
+ c = (hl_bytes_cell * )hl_gc_alloc (sizeof (hl_bytes_cell ));
65
+ memset (c ,0 ,sizeof (hl_bytes_cell ));
66
+ c -> strings [0 ] = key ;
67
+ c -> hashes [0 ] = hash ;
68
+ c -> values [0 ] = value ;
69
+ c -> nvalues = 1 ;
70
+ c -> next = m -> cells [ckey ];
71
+ m -> cells [ckey ] = c ;
72
+ }
73
+
74
+ static bool hl_hbadd ( hl_bytes_map * m , uchar * key , vdynamic * value ) {
75
+ int hash = hl_hash_gen (key ,false);
76
+ int ckey = ((unsigned )hash ) % ((unsigned )m -> ncells );
77
+ hl_bytes_cell * c = m -> cells [ckey ];
78
+ hl_bytes_cell * pspace = NULL ;
79
+ int i ;
80
+ while ( c ) {
81
+ for (i = 0 ;i < c -> nvalues ;i ++ )
82
+ if ( c -> hashes [i ] == hash && ucmp (key ,c -> strings [i ]) == 0 ) {
83
+ c -> values [i ] = value ;
84
+ return false;
85
+ }
86
+ if ( !pspace && c -> nvalues < H_CELL_SIZE ) pspace = c ;
87
+ c = c -> next ;
88
+ }
89
+ if ( pspace ) {
90
+ pspace -> hashes [pspace -> nvalues ] = hash ;
91
+ pspace -> strings [pspace -> nvalues ] = key ;
92
+ pspace -> values [pspace -> nvalues ] = value ;
93
+ pspace -> nvalues ++ ;
94
+ m -> nentries ++ ;
95
+ return false;
96
+ }
97
+ c = (hl_bytes_cell * )hl_gc_alloc (sizeof (hl_bytes_cell ));
98
+ memset (c ,0 ,sizeof (hl_bytes_cell ));
99
+ c -> strings [0 ] = key ;
100
+ c -> hashes [0 ] = hash ;
101
+ c -> values [0 ] = value ;
102
+ c -> nvalues = 1 ;
103
+ c -> next = m -> cells [ckey ];
104
+ m -> cells [ckey ] = c ;
105
+ m -> nentries ++ ;
106
+ return true;
107
+ }
108
+
109
+ static void hl_hbgrow ( hl_bytes_map * m ) {
110
+ int i = 0 ;
111
+ int oldsize = m -> ncells ;
112
+ hl_bytes_cell * * old_cells = m -> cells ;
113
+ hl_bytes_cell * reuse = NULL ;
114
+ while ( H_PRIMES [i ] <= m -> ncells ) i ++ ;
115
+ m -> ncells = H_PRIMES [i ];
116
+ m -> cells = (hl_bytes_cell * * )hl_gc_alloc (sizeof (hl_bytes_cell * )* m -> ncells );
117
+ memset (m -> cells ,0 ,m -> ncells * sizeof (void * ));
118
+ for (i = 0 ;i < oldsize ;i ++ ) {
119
+ hl_bytes_cell * c = old_cells [i ];
120
+ while ( c ) {
121
+ hl_bytes_cell * next = c -> next ;
122
+ int j ;
123
+ for (j = 0 ;j < c -> nvalues ;j ++ ) {
124
+ if ( j == c -> nvalues - 1 ) {
125
+ c -> next = reuse ;
126
+ reuse = c ;
127
+ }
128
+ hl_hbremap (m ,c -> strings [j ],c -> hashes [j ],c -> values [j ],& reuse );
129
+ }
130
+ c = next ;
131
+ }
132
+ }
133
+ }
134
+
135
+ HL_PRIM void hl_hbset ( hl_bytes_map * m , vbytes * key , vdynamic * value ) {
136
+ if ( hl_hbadd (m ,(uchar * )key ,value ) && m -> nentries > m -> ncells * H_CELL_SIZE * 2 )
137
+ hl_hbgrow (m );
138
+ }
24
139
25
140
HL_PRIM bool hl_hbexists ( hl_bytes_map * m , vbytes * key ) {
26
- return false ;
141
+ return hl_hbfind ( m ,( uchar * ) key ) != NULL ;
27
142
}
28
143
29
- HL_PRIM vdynamic * hl_hbget ( hl_bytes_map * m , vbytes * key ) {
30
- return NULL ;
144
+ HL_PRIM vdynamic * hl_hbget ( hl_bytes_map * m , vbytes * key ) {
145
+ vdynamic * * v = hl_hbfind (m ,(uchar * )key );
146
+ if ( v == NULL ) return NULL ;
147
+ return * v ;
31
148
}
32
149
33
- HL_PRIM bool hl_hbremove ( hl_bytes_map * m , vbytes * key ) {
150
+ HL_PRIM bool hl_hbremove ( hl_bytes_map * m , vbytes * _key ) {
151
+ uchar * key = (uchar * )_key ;
152
+ int hash = hl_hash_gen (key ,false);
153
+ int ckey = ((unsigned )hash ) % ((unsigned )m -> ncells );
154
+ hl_bytes_cell * c = m -> cells [ckey ];
155
+ hl_bytes_cell * prev = NULL ;
156
+ int i ;
157
+ while ( c ) {
158
+ for (i = 0 ;i < c -> nvalues ;i ++ )
159
+ if ( c -> hashes [i ] == hash && ucmp (c -> strings [i ],key ) == 0 ) {
160
+ c -> nvalues -- ;
161
+ if ( c -> nvalues ) {
162
+ int j ;
163
+ for (j = i ;j < c -> nvalues ;j ++ ) {
164
+ c -> hashes [j ] = c -> hashes [j + 1 ];
165
+ c -> strings [j ] = c -> strings [j + 1 ];
166
+ c -> values [j ] = c -> values [j + 1 ];
167
+ }
168
+ c -> strings [j ] = NULL ;
169
+ c -> values [j ] = NULL ; // GC friendly
170
+ } else if ( prev )
171
+ prev -> next = c -> next ;
172
+ else
173
+ m -> cells [ckey ] = c -> next ;
174
+ return true;
175
+ }
176
+ prev = c ;
177
+ c = c -> next ;
178
+ }
34
179
return false;
35
180
}
36
181
37
- HL_PRIM varray * hl_hbkeys ( hl_bytes_map * m ) {
38
- return NULL ;
182
+ HL_PRIM varray * hl_hbkeys ( hl_bytes_map * m ) {
183
+ varray * a = (varray * )hl_gc_alloc_noptr (sizeof (varray )+ sizeof (uchar * )* m -> nentries );
184
+ uchar * * keys = (uchar * * )(a + 1 );
185
+ int p = 0 ;
186
+ int i ;
187
+ a -> t = & hlt_array ;
188
+ a -> at = & hlt_bytes ;
189
+ a -> size = m -> nentries ;
190
+ for (i = 0 ;i < m -> ncells ;i ++ ) {
191
+ int j ;
192
+ hl_bytes_cell * c = m -> cells [i ];
193
+ while ( c ) {
194
+ for (j = 0 ;j < c -> nvalues ;j ++ )
195
+ keys [p ++ ] = c -> strings [j ];
196
+ c = c -> next ;
197
+ }
198
+ }
199
+ return a ;
39
200
}
40
201
41
- HL_PRIM varray * hl_hbvalues ( hl_bytes_map * m ) {
42
- return NULL ;
202
+ HL_PRIM varray * hl_hbvalues ( hl_bytes_map * m ) {
203
+ varray * a = (varray * )hl_gc_alloc (sizeof (varray )+ sizeof (void * )* m -> nentries );
204
+ vdynamic * * values = (vdynamic * * )(a + 1 );
205
+ int p = 0 ;
206
+ int i ;
207
+ a -> t = & hlt_array ;
208
+ a -> at = & hlt_dyn ;
209
+ a -> size = m -> nentries ;
210
+ for (i = 0 ;i < m -> ncells ;i ++ ) {
211
+ int j ;
212
+ hl_bytes_cell * c = m -> cells [i ];
213
+ while ( c ) {
214
+ for (j = 0 ;j < c -> nvalues ;j ++ )
215
+ values [p ++ ] = c -> values [j ];
216
+ c = c -> next ;
217
+ }
218
+ }
219
+ return a ;
43
220
}
44
221
45
222
// ----- INT MAP ---------------------------------
46
223
47
224
typedef struct _hl_int_map hl_int_map ;
48
225
typedef struct _hl_int_cell hl_int_cell ;
49
226
50
- #define ICELL_SIZE 3
51
-
52
227
struct _hl_int_cell {
53
228
int nvalues ;
54
- int keys [ICELL_SIZE ];
55
- vdynamic * values [ICELL_SIZE ];
229
+ int keys [H_CELL_SIZE ];
230
+ vdynamic * values [H_CELL_SIZE ];
56
231
hl_int_cell * next ;
57
232
};
58
233
@@ -84,7 +259,29 @@ static vdynamic **hl_hifind( hl_int_map *m, int key ) {
84
259
return NULL ;
85
260
}
86
261
87
- static bool hl_hiadd ( hl_int_map * m , int key , vdynamic * value , hl_int_cell * reuse ) {
262
+ static void hl_hiremap ( hl_int_map * m , int key , vdynamic * value , hl_int_cell * * reuse ) {
263
+ int ckey = ((unsigned )key ) % ((unsigned )m -> ncells );
264
+ hl_int_cell * c = m -> cells [ckey ];
265
+ if ( c && c -> nvalues < H_CELL_SIZE ) {
266
+ c -> keys [c -> nvalues ] = key ;
267
+ c -> values [c -> nvalues ] = value ;
268
+ c -> nvalues ++ ;
269
+ return ;
270
+ }
271
+ c = * reuse ;
272
+ if ( c )
273
+ * reuse = c -> next ;
274
+ else
275
+ c = (hl_int_cell * )hl_gc_alloc (sizeof (hl_int_cell ));
276
+ memset (c ,0 ,sizeof (hl_int_cell ));
277
+ c -> keys [0 ] = key ;
278
+ c -> values [0 ] = value ;
279
+ c -> nvalues = 1 ;
280
+ c -> next = m -> cells [ckey ];
281
+ m -> cells [ckey ] = c ;
282
+ }
283
+
284
+ static bool hl_hiadd ( hl_int_map * m , int key , vdynamic * value ) {
88
285
int ckey = ((unsigned )key ) % ((unsigned )m -> ncells );
89
286
hl_int_cell * c = m -> cells [ckey ];
90
287
hl_int_cell * pspace = NULL ;
@@ -95,7 +292,7 @@ static bool hl_hiadd( hl_int_map *m, int key, vdynamic *value, hl_int_cell *reus
95
292
c -> values [i ] = value ;
96
293
return false;
97
294
}
98
- if ( !pspace && c -> nvalues < ICELL_SIZE ) pspace = c ;
295
+ if ( !pspace && c -> nvalues < H_CELL_SIZE ) pspace = c ;
99
296
c = c -> next ;
100
297
}
101
298
if ( pspace ) {
@@ -105,10 +302,7 @@ static bool hl_hiadd( hl_int_map *m, int key, vdynamic *value, hl_int_cell *reus
105
302
m -> nentries ++ ;
106
303
return false;
107
304
}
108
- if ( reuse )
109
- c = reuse ;
110
- else
111
- c = (hl_int_cell * )hl_gc_alloc (sizeof (hl_int_cell ));
305
+ c = (hl_int_cell * )hl_gc_alloc (sizeof (hl_int_cell ));
112
306
memset (c ,0 ,sizeof (hl_int_cell ));
113
307
c -> keys [0 ] = key ;
114
308
c -> values [0 ] = value ;
@@ -139,16 +333,15 @@ static void hl_higrow( hl_int_map *m ) {
139
333
c -> next = reuse ;
140
334
reuse = c ;
141
335
}
142
- if ( hl_hiadd (m ,c -> keys [j ],c -> values [j ],reuse ) )
143
- reuse = reuse -> next ;
336
+ hl_hiremap (m ,c -> keys [j ],c -> values [j ],& reuse );
144
337
}
145
338
c = next ;
146
339
}
147
340
}
148
341
}
149
342
150
343
HL_PRIM void hl_hiset ( hl_int_map * m , int key , vdynamic * value ) {
151
- if ( hl_hiadd (m ,key ,value , NULL ) && m -> nentries > m -> ncells * ICELL_SIZE * 2 )
344
+ if ( hl_hiadd (m ,key ,value ) && m -> nentries > m -> ncells * H_CELL_SIZE * 2 )
152
345
hl_higrow (m );
153
346
}
154
347
0 commit comments