2022-08-19 19:32:52 +03:00
|
|
|
/* This software is licensed by the MIT License, see LICENSE file */
|
|
|
|
/* Copyright © 2022 Gregory Lirent */
|
|
|
|
|
|
|
|
#include "../../include/list.h"
|
|
|
|
#include "include.h"
|
|
|
|
|
2022-08-22 14:18:38 +03:00
|
|
|
static void libcdsb_builtin_rehash(dict_t* s, size_t capacity) {
|
2022-08-19 19:32:52 +03:00
|
|
|
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;
|
|
|
|
|
2022-08-22 14:18:38 +03:00
|
|
|
libcdsb_builtin_rehash(s, capacity);
|
2022-08-19 19:32:52 +03:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-08-26 17:54:27 +03:00
|
|
|
bool libcdsb_dict_update(dict_t* x, const void* k, vtype kt, const void* v, vtype vt, void* dt, dict_access_callback callback) {
|
2022-08-19 19:32:52 +03:00
|
|
|
dnode_t *c, **p;
|
|
|
|
|
|
|
|
if (!x->capacity || (double)x->size / x->capacity > REBUILD_POINT_MAX)
|
2022-08-22 14:18:38 +03:00
|
|
|
libcdsb_builtin_rehash(x, x->capacity + CAPACITY_BLOCK);
|
2022-08-19 19:32:52 +03:00
|
|
|
|
|
|
|
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) {
|
2022-08-26 17:54:27 +03:00
|
|
|
if (!callback) callback(vnode_peek(&c->key, c->key_type), c->key_type,
|
|
|
|
vnode_peek(&c->value, c->value_type), c->value_type, dt);
|
2022-08-19 19:32:52 +03:00
|
|
|
|
|
|
|
vnode_free(&c->value, c->value_type);
|
|
|
|
|
2022-08-26 17:54:27 +03:00
|
|
|
c->value = vnode_create(v, c->value_type = vt);
|
2022-08-19 19:32:52 +03:00
|
|
|
|
|
|
|
return true;
|
|
|
|
} else c = c->prev;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = malloc(sizeof(*c));
|
|
|
|
|
2022-08-26 17:54:27 +03:00
|
|
|
c->prev = *p;
|
|
|
|
c->key = vnode_create(k, c->key_type = kt);
|
|
|
|
c->value = vnode_create(v, c->value_type = vt);
|
2022-08-19 19:32:52 +03:00
|
|
|
|
|
|
|
*p = c;
|
|
|
|
++x->size;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-08-26 17:54:27 +03:00
|
|
|
bool libcdsb_dict_inject(dict_t* x, const void* k, vtype kt, const void* v, vtype vt, void* dt, dict_access_callback callback) {
|
2022-08-19 19:32:52 +03:00
|
|
|
dnode_t *c, **p;
|
|
|
|
|
|
|
|
if (!x->capacity || (double)x->size / x->capacity > REBUILD_POINT_MAX)
|
2022-08-22 14:18:38 +03:00
|
|
|
libcdsb_builtin_rehash(x, x->capacity + CAPACITY_BLOCK);
|
2022-08-19 19:32:52 +03:00
|
|
|
|
|
|
|
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) {
|
2022-08-26 17:54:27 +03:00
|
|
|
if (!callback) callback(vnode_peek(&c->key, c->key_type), c->key_type,
|
|
|
|
vnode_peek(&c->value, c->value_type), c->value_type, dt);
|
2022-08-19 19:32:52 +03:00
|
|
|
|
2022-08-26 17:54:27 +03:00
|
|
|
vnode_free(&c->key, c->key_type);
|
2022-08-19 19:32:52 +03:00
|
|
|
vnode_free(&c->value, c->value_type);
|
|
|
|
|
2022-08-26 17:54:27 +03:00
|
|
|
vnode_attach(&c->key, k, c->key_type = kt);
|
|
|
|
vnode_attach(&c->value, v, c->value_type = vt);
|
2022-08-19 19:32:52 +03:00
|
|
|
|
|
|
|
return true;
|
|
|
|
} else c = c->prev;
|
|
|
|
}
|
|
|
|
|
2022-08-26 17:54:27 +03:00
|
|
|
(c = malloc(sizeof(*c)))->prev = *p;
|
|
|
|
vnode_attach(&c->key, k, c->key_type = kt);
|
|
|
|
vnode_attach(&c->value, v, c->value_type = vt);
|
2022-08-19 19:32:52 +03:00
|
|
|
|
|
|
|
*p = c;
|
|
|
|
++x->size;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|