libcdsb/src/dict/access.c

88 lines
2.3 KiB
C

/* This software is licensed by the MIT License, see LICENSE file */
/* Copyright © 2022 Gregory Lirent */
#include "include.h"
int libcdsb_dict_find(dict_t* x, const void* k, vtype t, void* dt, dict_access_callback callback, bool cut) {
dnode_t *c, **p;
int r;
void* key;
if (x->capacity) {
c = *(p = x->nodes + (vtype_hash(k, t) % x->capacity));
while (!is_null(c)) {
key = vnode_peek(&c->key, c->key_type);
if (vtype_compare(k, t, key, c->key_type) == 0) {
r = (callback) ? callback(key, c->key_type, vnode_peek(&c->value, c->value_type), c->value_type, dt) : 0;
if (cut) {
*p = c->prev;
vnode_free(&c->key, c->key_type);
vnode_free(&c->value, c->value_type);
free(c);
--x->size;
}
return r;
} else c = *(p = &c->prev);
}
}
return -1;
}
int libcdsb_dict_foreach(dict_t* x, void* dt, dict_access_callback callback, bool flush) {
dnode_t *c;
ssize_t i;
int r;
r = 0;
i = x->capacity;
while (i) {
c = x->nodes[--i];
while (!is_null(c)) {
r = callback(vnode_peek(&c->key, c->key_type), c->key_type,
vnode_peek(&c->value, c->value_type), c->value_type, dt);
c = c->prev;
if (r) {
if (!flush) goto end_;
else goto flush_loop_;
} else if (flush) {
vnode_free(&x->nodes[i]->key, x->nodes[i]->key_type);
vnode_free(&x->nodes[i]->value, x->nodes[i]->value_type);
free(x->nodes[i]);
x->nodes[i] = c;
}
}
}
if (flush) {
while (i) {
--i;
while (!is_null(x->nodes[i])) { flush_loop_:
vnode_free(&x->nodes[i]->key, x->nodes[i]->key_type);
vnode_free(&x->nodes[i]->value, x->nodes[i]->value_type);
c = x->nodes[i]->prev;
free(x->nodes[i]);
x->nodes[i] = c;
}
}
free(x->nodes);
memset(x, 0, sizeof(*x));
}
end_:
return r;
}