/* This software is licensed by the MIT License, see LICENSE file */ /* Copyright © 2022 Gregory Lirent */ #include "../../include/list.h" #include "include.h" static void libcdsb_builtin_rehash(dict_t* s, size_t capacity) { dnode_t **nodes, *c, *n, **p; size_t i; i = s->capacity; nodes = calloc(sizeof(*nodes), capacity); while (i--) { c = s->nodes[i]; while (!is_null(c)) { p = nodes + (vnode_hash(&c->key, c->key_type) % capacity); n = c->prev; c->prev = *p; *p = c; c = n; } } free(s->nodes); s->nodes = nodes; s->capacity = capacity; } /*#####################################################################################################################*/ bool libcdsb_dict_shrink_to_fit(dict_t* s) { size_t capacity; capacity = (s->size / CAPACITY_BLOCK) + 1; capacity *= CAPACITY_BLOCK; while (((double)s->size / capacity) > 0.65) capacity += CAPACITY_BLOCK; if (capacity >= s->capacity) return false; libcdsb_builtin_rehash(s, capacity); return true; } bool libcdsb_dict_update(dict_t* x, const void* k, vtype kt, const void* v, vtype vt, void* dt, dict_access_callback callback) { dnode_t *c, **p; if (!x->capacity || (double)x->size / x->capacity > REBUILD_POINT_MAX) libcdsb_builtin_rehash(x, x->capacity + CAPACITY_BLOCK); c = *(p = x->nodes + (vtype_hash(k, kt) % x->capacity)); while (!is_null(c)) { if (vtype_compare(k, kt, vnode_peek(&c->key, c->key_type), c->key_type) == 0) { if (!callback) callback(vnode_peek(&c->key, c->key_type), c->key_type, vnode_peek(&c->value, c->value_type), c->value_type, dt); vnode_free(&c->value, c->value_type); c->value = vnode_create(v, c->value_type = vt); return true; } else c = c->prev; } c = malloc(sizeof(*c)); c->prev = *p; c->key = vnode_create(k, c->key_type = kt); c->value = vnode_create(v, c->value_type = vt); *p = c; ++x->size; return false; } bool libcdsb_dict_inject(dict_t* x, const void* k, vtype kt, const void* v, vtype vt, void* dt, dict_access_callback callback) { dnode_t *c, **p; if (!x->capacity || (double)x->size / x->capacity > REBUILD_POINT_MAX) libcdsb_builtin_rehash(x, x->capacity + CAPACITY_BLOCK); c = *(p = x->nodes + (vtype_hash(k, kt) % x->capacity)); while (!is_null(c)) { if (vtype_compare(k, kt, vnode_peek(&c->key, c->key_type), c->key_type) == 0) { if (!callback) callback(vnode_peek(&c->key, c->key_type), c->key_type, vnode_peek(&c->value, c->value_type), c->value_type, dt); vnode_free(&c->key, c->key_type); vnode_free(&c->value, c->value_type); vnode_attach(&c->key, k, c->key_type = kt); vnode_attach(&c->value, v, c->value_type = vt); return true; } else c = c->prev; } (c = malloc(sizeof(*c)))->prev = *p; vnode_attach(&c->key, k, c->key_type = kt); vnode_attach(&c->value, v, c->value_type = vt); *p = c; ++x->size; return false; }