70#include "../include/cmp.h"
71#include "../include/lock.h"
72#include "../include/map.h"
73#include "../include/platform.h"
78#define DEFAULT_MAX_LOAD_FACTOR 0.75f
79#define TOMBSTONE_RATIO_THRESHOLD 0.5f
81#define MAX(a, b) ((a) > (b) ? (a) : (b))
84#define _RH_DIB(m, i) ((m)->deleted[i])
85#define _RH_SET_DIB(m, i, d) ((m)->deleted[i] = (size_t)(d))
87#define _RH_EMPTY(m, i) ((m)->keys_values[(i) * 2] == NULL)
90static inline size_t _rh_slot(
size_t hash,
size_t offset,
size_t cap_mask) {
return (hash + offset) & cap_mask; }
93typedef struct hash_map {
98 float max_load_factor;
100 KeyCmpFunction key_compare;
101 KeyFreeFunction key_free;
102 ValueFreeFunction value_free;
107static inline uint64_t fast_small_hash(
const void* key,
size_t size) {
117 const uint8_t* src = (
const uint8_t*)key;
118 for (
size_t i = 0; i < size && i <
sizeof(value); i++) {
119 value.u8[i] = src[i];
125static inline unsigned long xxhash(
const void* key,
size_t size) {
126 if (size <=
sizeof(uint64_t)) {
127 return fast_small_hash(key, size);
129 return XXH3_64bits(key, size);
133static inline size_t next_power_of_two(
size_t n) {
134 if (n == 0)
return 1;
141#if SIZE_MAX > UINT32_MAX
148static inline size_t calculate_new_capacity(
size_t current) {
149 if (current > SIZE_MAX / 2) {
152 size_t new_cap = current * 2;
153 return (new_cap < current) ? SIZE_MAX : new_cap;
157static inline size_t xxhash_wrapper(
const void* key,
size_t len) {
return (
size_t)xxhash(key, (
size_t)len); }
160HashMap* map_create(
const MapConfig* config) {
161 if (!config || !config->key_compare) {
165 size_t capacity =
MAX(
166 MIN_CAPACITY, config->initial_capacity > 0 ? next_power_of_two(config->initial_capacity) : INITIAL_MAP_SIZE);
168 if (capacity > SIZE_MAX / 2) {
172 float max_load_factor = config->max_load_factor > 0.1f && config->max_load_factor <= 0.95f
173 ? config->max_load_factor
174 : DEFAULT_MAX_LOAD_FACTOR;
176 HashMap* m = (HashMap*)malloc(
sizeof(HashMap));
182 m->keys_values = (
void**)calloc(capacity * 2,
sizeof(
void*));
183 m->deleted = (
size_t*)calloc(capacity,
sizeof(
size_t));
185 if (!m->keys_values || !m->deleted) {
186 free(m->keys_values);
193 m->capacity = capacity;
194 m->max_load_factor = max_load_factor;
195 m->hash = config->hash_func ? config->hash_func : xxhash_wrapper;
196 m->key_compare = config->key_compare;
197 m->key_free = config->key_free;
198 m->value_free = config->value_free;
205static inline void** get_key_ptr(HashMap* m,
size_t index) {
return &m->keys_values[index * 2]; }
208static inline void** get_value_ptr(HashMap* m,
size_t index) {
return &m->keys_values[index * 2 + 1]; }
211static bool map_resize(HashMap* m,
size_t new_capacity,
size_t key_len) {
212 if (new_capacity <= m->capacity || new_capacity > SIZE_MAX / 2) {
216 void** new_keys_values = (
void**)calloc(new_capacity * 2,
sizeof(
void*));
217 size_t* new_deleted = (
size_t*)calloc(new_capacity,
sizeof(
size_t));
219 if (!new_keys_values || !new_deleted) {
220 free(new_keys_values);
226 void** old_keys_values = m->keys_values;
227 size_t* old_deleted = m->deleted;
228 size_t old_capacity = m->capacity;
231 m->keys_values = new_keys_values;
232 m->deleted = new_deleted;
233 m->capacity = new_capacity;
234 size_t old_size = m->size;
239 const size_t mask = new_capacity - 1;
240 for (
size_t i = 0; i < old_capacity; i++) {
241 if (old_keys_values[i * 2] && old_keys_values[i * 2] != NULL) {
242 void* ins_key = old_keys_values[i * 2];
243 void* ins_value = old_keys_values[i * 2 + 1];
245 size_t hash = m->hash(ins_key, key_len);
246 size_t idx = hash & mask;
249 for (
size_t j = 0; j < new_capacity; j++) {
250 if (_RH_EMPTY(m, idx)) {
251 *get_key_ptr(m, idx) = ins_key;
252 *get_value_ptr(m, idx) = ins_value;
253 _RH_SET_DIB(m, idx, ins_dist);
259 size_t cur_dist = _RH_DIB(m, idx);
260 if (cur_dist < ins_dist) {
261 void* tmp_k = *get_key_ptr(m, idx);
262 void* tmp_v = *get_value_ptr(m, idx);
263 *get_key_ptr(m, idx) = ins_key;
264 *get_value_ptr(m, idx) = ins_value;
265 _RH_SET_DIB(m, idx, ins_dist);
271 idx = (idx + 1) & mask;
279 free(old_keys_values);
283 m->keys_values = old_keys_values;
284 m->deleted = old_deleted;
285 m->capacity = old_capacity;
287 free(new_keys_values);
295size_t map_length(HashMap* m) {
return m->size; }
298bool map_set(HashMap* m,
void* key,
size_t key_len,
void* value) {
299 if (!m || !key)
return false;
302 size_t total_used = m->size;
303 if ((
float)total_used / (
float)m->capacity >= m->max_load_factor) {
304 size_t new_cap = calculate_new_capacity(m->capacity);
305 if (new_cap <= m->capacity || !map_resize(m, new_cap, key_len))
return false;
308 const size_t mask = m->capacity - 1;
309 size_t hash = m->hash(key, key_len);
310 size_t idx = hash & mask;
314 void* ins_value = value;
317 for (
size_t i = 0; i < m->capacity; i++) {
318 if (_RH_EMPTY(m, idx)) {
320 *get_key_ptr(m, idx) = ins_key;
321 *get_value_ptr(m, idx) = ins_value;
322 _RH_SET_DIB(m, idx, ins_dist);
328 void** cur_kp = get_key_ptr(m, idx);
329 if (m->key_compare(*cur_kp, ins_key)) {
331 if (m->value_free) m->value_free(*get_value_ptr(m, idx));
332 *get_value_ptr(m, idx) = ins_value;
337 size_t cur_dist = _RH_DIB(m, idx);
338 if (cur_dist < ins_dist) {
340 void* tmp_k = *cur_kp;
341 void* tmp_v = *get_value_ptr(m, idx);
343 *get_key_ptr(m, idx) = ins_key;
344 *get_value_ptr(m, idx) = ins_value;
345 _RH_SET_DIB(m, idx, ins_dist);
352 idx = (idx + 1) & mask;
360void* map_get(HashMap* m,
void* key,
size_t key_len) {
361 if (!m || !key)
return NULL;
363 const size_t hash = m->hash(key, key_len);
364 const size_t mask = m->capacity - 1;
365 size_t idx = hash & mask;
367 for (
size_t dist = 0; dist < m->capacity; dist++) {
368 if (_RH_EMPTY(m, idx))
return NULL;
371 if (_RH_DIB(m, idx) < dist)
return NULL;
373 void** kp = get_key_ptr(m, idx);
374 if (m->key_compare(*kp, key))
return *get_value_ptr(m, idx);
376 idx = (idx + 1) & mask;
382bool map_remove(HashMap* m,
void* key,
size_t key_len) {
383 if (!m || !key)
return false;
385 const size_t mask = m->capacity - 1;
386 size_t hash = m->hash(key, key_len);
387 size_t idx = hash & mask;
390 size_t pos = SIZE_MAX;
391 for (
size_t dist = 0; dist < m->capacity; dist++) {
392 if (_RH_EMPTY(m, idx))
return false;
393 if (_RH_DIB(m, idx) < dist)
return false;
395 if (m->key_compare(*get_key_ptr(m, idx), key)) {
399 idx = (idx + 1) & mask;
401 if (pos == SIZE_MAX)
return false;
404 if (m->key_free) m->key_free(*get_key_ptr(m, pos));
405 if (m->value_free) m->value_free(*get_value_ptr(m, pos));
410 size_t next = (hole + 1) & mask;
411 if (_RH_EMPTY(m, next) || _RH_DIB(m, next) == 0)
break;
414 *get_key_ptr(m, hole) = *get_key_ptr(m, next);
415 *get_value_ptr(m, hole) = *get_value_ptr(m, next);
416 _RH_SET_DIB(m, hole, _RH_DIB(m, next) - 1);
422 *get_key_ptr(m, hole) = NULL;
423 *get_value_ptr(m, hole) = NULL;
424 _RH_SET_DIB(m, hole, 0);
429void map_destroy(HashMap* m) {
433 if (!m->key_free && !m->value_free) {
437 void** keys_values = m->keys_values;
438 size_t capacity = m->capacity;
439 KeyFreeFunction key_free = m->key_free;
440 ValueFreeFunction value_free = m->value_free;
442 for (
size_t i = 0; i < capacity; i++) {
443 void* key = keys_values[i * 2];
445 if (key_free) key_free(key);
446 if (value_free) value_free(keys_values[i * 2 + 1]);
451 free(m->keys_values);
457map_iterator map_iter(HashMap* map) {
458 map_iterator it = {.map = map, .index = 0};
462bool map_next(map_iterator* it,
void** key,
void** value) {
463 HashMap* map = it->map;
464 size_t capacity = map->capacity;
465 void** keys_values = map->keys_values;
466 size_t index = it->index;
468 while (index < capacity) {
469 void* current_key = keys_values[index * 2];
471 if (key) *key = current_key;
472 if (value) *value = keys_values[index * 2 + 1];
473 it->index = index + 1;
478 it->index = capacity;
483bool map_set_safe(HashMap* m,
void* key,
size_t key_len,
void* value) {
485 bool result = map_set(m, key, key_len, value);
490void* map_get_safe(HashMap* m,
void* key,
size_t key_len) {
492 void* value = map_get(m, key, key_len);
497bool map_remove_safe(HashMap* m,
void* key,
size_t key_len) {
499 bool result = map_remove(m, key, key_len);
int lock_init(Lock *lock)
int lock_acquire(Lock *lock)
int lock_release(Lock *lock)
int lock_free(Lock *lock)