libcdsb/src/dict/modify.c

119 lines
3.3 KiB
C

/* 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;
}