@@ -108,7 +108,6 @@ Py_uhash_t
108
108
_Py_hashtable_hash_ptr (struct _Py_hashtable_t * ht , const void * pkey )
109
109
{
110
110
void * key ;
111
-
112
111
_Py_HASHTABLE_READ_KEY (ht , pkey , key );
113
112
return (Py_uhash_t )_Py_HashPointer (key );
114
113
}
@@ -137,61 +136,6 @@ round_size(size_t s)
137
136
}
138
137
139
138
140
- _Py_hashtable_t *
141
- _Py_hashtable_new_full (size_t key_size , size_t data_size ,
142
- size_t init_size ,
143
- _Py_hashtable_hash_func hash_func ,
144
- _Py_hashtable_compare_func compare_func ,
145
- _Py_hashtable_allocator_t * allocator )
146
- {
147
- _Py_hashtable_t * ht ;
148
- size_t buckets_size ;
149
- _Py_hashtable_allocator_t alloc ;
150
-
151
- if (allocator == NULL ) {
152
- alloc .malloc = PyMem_Malloc ;
153
- alloc .free = PyMem_Free ;
154
- }
155
- else {
156
- alloc = * allocator ;
157
- }
158
-
159
- ht = (_Py_hashtable_t * )alloc .malloc (sizeof (_Py_hashtable_t ));
160
- if (ht == NULL )
161
- return ht ;
162
-
163
- ht -> num_buckets = round_size (init_size );
164
- ht -> entries = 0 ;
165
- ht -> key_size = key_size ;
166
- ht -> data_size = data_size ;
167
-
168
- buckets_size = ht -> num_buckets * sizeof (ht -> buckets [0 ]);
169
- ht -> buckets = alloc .malloc (buckets_size );
170
- if (ht -> buckets == NULL ) {
171
- alloc .free (ht );
172
- return NULL ;
173
- }
174
- memset (ht -> buckets , 0 , buckets_size );
175
-
176
- ht -> hash_func = hash_func ;
177
- ht -> compare_func = compare_func ;
178
- ht -> alloc = alloc ;
179
- return ht ;
180
- }
181
-
182
-
183
- _Py_hashtable_t *
184
- _Py_hashtable_new (size_t key_size , size_t data_size ,
185
- _Py_hashtable_hash_func hash_func ,
186
- _Py_hashtable_compare_func compare_func )
187
- {
188
- return _Py_hashtable_new_full (key_size , data_size ,
189
- HASHTABLE_MIN_SIZE ,
190
- hash_func , compare_func ,
191
- NULL );
192
- }
193
-
194
-
195
139
size_t
196
140
_Py_hashtable_size (_Py_hashtable_t * ht )
197
141
{
@@ -251,23 +195,20 @@ _Py_hashtable_print_stats(_Py_hashtable_t *ht)
251
195
252
196
253
197
_Py_hashtable_entry_t *
254
- _Py_hashtable_get_entry (_Py_hashtable_t * ht ,
255
- size_t key_size , const void * pkey )
198
+ _Py_hashtable_get_entry_generic (_Py_hashtable_t * ht , const void * pkey )
256
199
{
257
- Py_uhash_t key_hash ;
258
- size_t index ;
259
- _Py_hashtable_entry_t * entry ;
260
-
261
- assert (key_size == ht -> key_size );
262
-
263
- key_hash = ht -> hash_func (ht , pkey );
264
- index = key_hash & (ht -> num_buckets - 1 );
265
-
266
- for (entry = TABLE_HEAD (ht , index ); entry != NULL ; entry = ENTRY_NEXT (entry )) {
267
- if (entry -> key_hash == key_hash && ht -> compare_func (ht , pkey , entry ))
200
+ Py_uhash_t key_hash = ht -> hash_func (ht , pkey );
201
+ size_t index = key_hash & (ht -> num_buckets - 1 );
202
+ _Py_hashtable_entry_t * entry = entry = TABLE_HEAD (ht , index );
203
+ while (1 ) {
204
+ if (entry == NULL ) {
205
+ return NULL ;
206
+ }
207
+ if (entry -> key_hash == key_hash && ht -> compare_func (ht , pkey , entry )) {
268
208
break ;
209
+ }
210
+ entry = ENTRY_NEXT (entry );
269
211
}
270
-
271
212
return entry ;
272
213
}
273
214
@@ -324,7 +265,7 @@ _Py_hashtable_set(_Py_hashtable_t *ht, size_t key_size, const void *pkey,
324
265
/* Don't write the assertion on a single line because it is interesting
325
266
to know the duplicated entry if the assertion failed. The entry can
326
267
be read using a debugger. */
327
- entry = _Py_hashtable_get_entry (ht , key_size , pkey );
268
+ entry = ht -> get_entry_func (ht , pkey );
328
269
assert (entry == NULL );
329
270
#endif
330
271
@@ -352,18 +293,62 @@ _Py_hashtable_set(_Py_hashtable_t *ht, size_t key_size, const void *pkey,
352
293
353
294
354
295
int
355
- _Py_hashtable_get (_Py_hashtable_t * ht , size_t key_size ,const void * pkey ,
356
- size_t data_size , void * data )
296
+ _Py_hashtable_get_generic (_Py_hashtable_t * ht , const void * pkey , void * data )
357
297
{
358
- _Py_hashtable_entry_t * entry ;
359
-
360
298
assert (data != NULL );
299
+ _Py_hashtable_entry_t * entry = ht -> get_entry_func (ht , pkey );
300
+ if (entry != NULL ) {
301
+ ENTRY_READ_PDATA (ht , entry , ht -> data_size , data );
302
+ return 1 ;
303
+ }
304
+ else {
305
+ return 0 ;
306
+ }
307
+ }
361
308
362
- entry = _Py_hashtable_get_entry (ht , key_size , pkey );
363
- if (entry == NULL )
309
+
310
+ // Specialized for:
311
+ // key_size == sizeof(void*)
312
+ // hash_func == _Py_hashtable_hash_ptr
313
+ // compare_func == _Py_hashtable_compare_direct
314
+ _Py_hashtable_entry_t *
315
+ _Py_hashtable_get_entry_ptr (_Py_hashtable_t * ht , const void * pkey )
316
+ {
317
+ Py_uhash_t key_hash = _Py_hashtable_hash_ptr (ht , pkey );
318
+ size_t index = key_hash & (ht -> num_buckets - 1 );
319
+ _Py_hashtable_entry_t * entry = entry = TABLE_HEAD (ht , index );
320
+ while (1 ) {
321
+ if (entry == NULL ) {
322
+ return NULL ;
323
+ }
324
+ if (entry -> key_hash == key_hash ) {
325
+ const void * pkey2 = _Py_HASHTABLE_ENTRY_PKEY (entry );
326
+ if (memcmp (pkey , pkey2 , sizeof (void * )) == 0 ) {
327
+ break ;
328
+ }
329
+ }
330
+ entry = ENTRY_NEXT (entry );
331
+ }
332
+ return entry ;
333
+ }
334
+
335
+
336
+ // Specialized for:
337
+ // key_size == sizeof(void*)
338
+ // hash_func == _Py_hashtable_hash_ptr
339
+ // compare_func == _Py_hashtable_compare_direct
340
+ int
341
+ _Py_hashtable_get_ptr (_Py_hashtable_t * ht , const void * pkey , void * data )
342
+ {
343
+ assert (data != NULL );
344
+ _Py_hashtable_entry_t * entry = _Py_hashtable_get_entry_ptr (ht , pkey );
345
+ if (entry != NULL ) {
346
+ ENTRY_READ_PDATA (ht , entry , ht -> data_size , data );
347
+ return 1 ;
348
+ }
349
+ else {
364
350
return 0 ;
365
- ENTRY_READ_PDATA (ht , entry , data_size , data );
366
- return 1 ;
351
+ }
367
352
}
368
353
369
354
@@ -454,6 +439,70 @@ hashtable_rehash(_Py_hashtable_t *ht)
454
439
}
455
440
456
441
442
+ _Py_hashtable_t *
443
+ _Py_hashtable_new_full (size_t key_size , size_t data_size ,
444
+ size_t init_size ,
445
+ _Py_hashtable_hash_func hash_func ,
446
+ _Py_hashtable_compare_func compare_func ,
447
+ _Py_hashtable_allocator_t * allocator )
448
+ {
449
+ _Py_hashtable_t * ht ;
450
+ size_t buckets_size ;
451
+ _Py_hashtable_allocator_t alloc ;
452
+
453
+ if (allocator == NULL ) {
454
+ alloc .malloc = PyMem_Malloc ;
455
+ alloc .free = PyMem_Free ;
456
+ }
457
+ else {
458
+ alloc = * allocator ;
459
+ }
460
+
461
+ ht = (_Py_hashtable_t * )alloc .malloc (sizeof (_Py_hashtable_t ));
462
+ if (ht == NULL )
463
+ return ht ;
464
+
465
+ ht -> num_buckets = round_size (init_size );
466
+ ht -> entries = 0 ;
467
+ ht -> key_size = key_size ;
468
+ ht -> data_size = data_size ;
469
+
470
+ buckets_size = ht -> num_buckets * sizeof (ht -> buckets [0 ]);
471
+ ht -> buckets = alloc .malloc (buckets_size );
472
+ if (ht -> buckets == NULL ) {
473
+ alloc .free (ht );
474
+ return NULL ;
475
+ }
476
+ memset (ht -> buckets , 0 , buckets_size );
477
+
478
+ ht -> get_func = _Py_hashtable_get_generic ;
479
+ ht -> get_entry_func = _Py_hashtable_get_entry_generic ;
480
+ ht -> hash_func = hash_func ;
481
+ ht -> compare_func = compare_func ;
482
+ ht -> alloc = alloc ;
483
+ if (ht -> key_size == sizeof (void * )
484
+ && ht -> hash_func == _Py_hashtable_hash_ptr
485
+ && ht -> compare_func == _Py_hashtable_compare_direct )
486
+ {
487
+ ht -> get_func = _Py_hashtable_get_ptr ;
488
+ ht -> get_entry_func = _Py_hashtable_get_entry_ptr ;
489
+ }
490
+ return ht ;
491
+ }
492
+
493
+
494
+ _Py_hashtable_t *
495
+ _Py_hashtable_new (size_t key_size , size_t data_size ,
496
+ _Py_hashtable_hash_func hash_func ,
497
+ _Py_hashtable_compare_func compare_func )
498
+ {
499
+ return _Py_hashtable_new_full (key_size , data_size ,
500
+ HASHTABLE_MIN_SIZE ,
501
+ hash_func , compare_func ,
502
+ NULL );
503
+ }
504
+
505
+
457
506
void
458
507
_Py_hashtable_clear (_Py_hashtable_t * ht )
459
508
{
0 commit comments