222 |
222 |
223 static void *cx_hash_map_get( |
223 static void *cx_hash_map_get( |
224 CxMap const *map, |
224 CxMap const *map, |
225 CxHashKey key |
225 CxHashKey key |
226 ) { |
226 ) { |
227 // we can safely cast, because we know when remove=false, the map stays untouched |
227 // we can safely cast, because we know the map stays untouched |
228 return cx_hash_map_get_remove((CxMap *) map, key, false, false); |
228 return cx_hash_map_get_remove((CxMap *) map, key, false, false); |
229 } |
229 } |
230 |
230 |
231 static void *cx_hash_map_remove( |
231 static void *cx_hash_map_remove( |
232 CxMap *map, |
232 CxMap *map, |
426 if (buckets == 0) { |
426 if (buckets == 0) { |
427 // implementation defined default |
427 // implementation defined default |
428 buckets = 16; |
428 buckets = 16; |
429 } |
429 } |
430 |
430 |
431 struct cx_hash_map_s *map = cxCalloc(allocator, 1, sizeof(struct cx_hash_map_s)); |
431 struct cx_hash_map_s *map = cxCalloc(allocator, 1, |
|
432 sizeof(struct cx_hash_map_s)); |
432 if (map == NULL) return NULL; |
433 if (map == NULL) return NULL; |
433 |
434 |
434 // initialize hash map members |
435 // initialize hash map members |
435 map->bucket_count = buckets; |
436 map->bucket_count = buckets; |
436 map->buckets = cxCalloc(allocator, buckets, sizeof(struct cx_hash_map_element_s *)); |
437 map->buckets = cxCalloc(allocator, buckets, |
|
438 sizeof(struct cx_hash_map_element_s *)); |
437 if (map->buckets == NULL) { |
439 if (map->buckets == NULL) { |
438 cxFree(allocator, map); |
440 cxFree(allocator, map); |
439 return NULL; |
441 return NULL; |
440 } |
442 } |
441 |
443 |
457 int cxMapRehash(CxMap *map) { |
459 int cxMapRehash(CxMap *map) { |
458 struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; |
460 struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; |
459 if (map->size > ((hash_map->bucket_count * 3) >> 2)) { |
461 if (map->size > ((hash_map->bucket_count * 3) >> 2)) { |
460 |
462 |
461 size_t new_bucket_count = (map->size * 5) >> 1; |
463 size_t new_bucket_count = (map->size * 5) >> 1; |
462 struct cx_hash_map_element_s **new_buckets = cxCalloc(map->allocator, |
464 struct cx_hash_map_element_s **new_buckets = cxCalloc( |
463 new_bucket_count, sizeof(struct cx_hash_map_element_s *)); |
465 map->allocator, |
|
466 new_bucket_count, sizeof(struct cx_hash_map_element_s *) |
|
467 ); |
464 |
468 |
465 if (new_buckets == NULL) { |
469 if (new_buckets == NULL) { |
466 return 1; |
470 return 1; |
467 } |
471 } |
468 |
472 |
474 size_t new_slot = elm->key.hash % new_bucket_count; |
478 size_t new_slot = elm->key.hash % new_bucket_count; |
475 |
479 |
476 // find position where to insert |
480 // find position where to insert |
477 struct cx_hash_map_element_s *bucket_next = new_buckets[new_slot]; |
481 struct cx_hash_map_element_s *bucket_next = new_buckets[new_slot]; |
478 struct cx_hash_map_element_s *bucket_prev = NULL; |
482 struct cx_hash_map_element_s *bucket_prev = NULL; |
479 while (bucket_next != NULL && bucket_next->key.hash < elm->key.hash) { |
483 while (bucket_next != NULL && |
|
484 bucket_next->key.hash < elm->key.hash) { |
480 bucket_prev = bucket_next; |
485 bucket_prev = bucket_next; |
481 bucket_next = bucket_next->next; |
486 bucket_next = bucket_next->next; |
482 } |
487 } |
483 |
488 |
484 // insert |
489 // insert |