diff --git a/src/dict/base.c b/src/dict/base.c index 29e4854..35ec012 100644 --- a/src/dict/base.c +++ b/src/dict/base.c @@ -23,10 +23,6 @@ static int dnode_compare(const dnode_t *s0, const dnode_t *s1, void* not_used) { return (!c) ? vnode_compare(&s0->value, s1->val_type, &s1->value, s1->val_type) : c; } -static hash_t dnode_hash(const dnode_t* s, void* not_used) { - return vnode_hash(s->key, s->key_type) + vnode_hash(s->value, s->val_type) + s->key_type; -} - /*#####################################################################################################################*/ static int dict_compare_equal_capacity(const dict_t* s0, const dict_t* s1) { diff --git a/src/dict/extra.c b/src/dict/extra.c index 66e2dd2..8688703 100644 --- a/src/dict/extra.c +++ b/src/dict/extra.c @@ -6,15 +6,20 @@ /*#####################################################################################################################*/ static void dict_rehash(dict_t* s, size_t capacity) { - stack_t z; - int cmp; - dnode_t *c, *p, *n, **r; + stack_t z; + int cmp; + size_t index; + dnode_t *c, *p, *n; - dnode_t **nodes = malloc(capacity * sizeof(*nodes)); + dnode_t **nodes = calloc(capacity, sizeof(*nodes)); - while (s->capacity--) { - if (!dnode_is_empty(s->nodes[s->capacity])) - stack_push(&z, s->nodes[s->capacity]); + z.prev = 0; + z.value = 0; + index = s->capacity; + + while (index--) { + if (!dnode_is_empty(s->nodes[index])) + stack_push(&z, s->nodes[index]); } while ((c = stack_pop(&z))) { @@ -29,9 +34,10 @@ static void dict_rehash(dict_t* s, size_t capacity) { c->left = dnode_empty; } - n = *(r = &nodes[vnode_hash(c->key, c->key_type) / capacity]); + index = vnode_hash(&c->key, c->key_type) % capacity; + n = nodes[index]; - if (!dnode_is_empty(*r)) { + if (!is_null(nodes[index])) { do { p = n; cmp = vnode_compare(&c->key, c->key_type, &n->key, n->key_type); @@ -45,19 +51,27 @@ static void dict_rehash(dict_t* s, size_t capacity) { c->colored = 1; if (!dnode_is_root(p)) - dnode_fixup(r, n); + dnode_fixup(nodes + index, n); } else { - *r = c; - c->colored = 0; - c->parent = dnode_empty; + nodes[index] = c; + c->colored = 0; + c->parent = dnode_empty; } } free(s->nodes); - s->capacity = capacity; s->nodes = nodes; + + if (capacity > s->capacity) { + s->capacity = capacity; + while (capacity--) { + if (is_null(*nodes)) + *nodes = dnode_empty; + ++nodes; + } + } else s->capacity = capacity; } /*#####################################################################################################################*/ @@ -83,17 +97,18 @@ bool libcdsb_dict_shrink_to_fit(dict_t* s) { bool libcdsb_dict_update(dict_t* x, const void* k, vtype kt, const void* v, vtype vt) { - dnode_t **r, *n, *p; + dnode_t *n, *p; vnode_t kn, vn; - int cmp; + int cmp; + size_t index; - if (!x->capacity || (double)x->size / x->capacity > REBUILD_POINT_MAX) { + if (!x->capacity || (double)x->size / x->capacity > REBUILD_POINT_MAX) dict_rehash(x, x->capacity + CAPACITY_BLOCK); - } - n = *(r = &x->nodes[vnode_hash(k, kt) / x->capacity]); - kn = vnode_create(k, kt); - vn = vnode_create(v, vt); + index = vtype_hash(k, kt) % x->capacity; + n = x->nodes[index]; + kn = vnode_create(k, kt); + vn = vnode_create(v, vt); if (!dnode_is_empty(n)) { do { @@ -120,26 +135,30 @@ bool libcdsb_dict_update(dict_t* x, const void* k, vtype kt, const void* v, vtyp else p->right = n; if (!dnode_is_root(p)) - dnode_fixup(r, n); + dnode_fixup(x->nodes + index, n); - } else n = *r = dnode_create(kn, dnode_empty, 0); + } else x->nodes[index] = n = dnode_create(kn, dnode_empty, 0); n->value = vn; n->key_type = kt; n->val_type = vt; + ++x->size; + return false; } int libcdsb_dict_get(dict_t* x, const void* k, vtype t, void* _, dict_access_callback callback, bool cut) { - dnode_t *c, **r; - void* key; - int cmp; + dnode_t *c; + void* key; + int cmp; + size_t index; if (x->capacity) { - c = *(r = &x->nodes[vnode_hash(k, t) / x->capacity]); + index = vtype_hash(k, t) % x->capacity; + c = x->nodes[index]; while (!dnode_is_empty(c)) { key = vnode_peek(&c->key, c->key_type); @@ -149,9 +168,10 @@ int libcdsb_dict_get(dict_t* x, const void* k, vtype t, void* _, dict_access_cal cmp = (callback) ? callback(key, t, vnode_peek(&c->value, c->val_type), c->val_type, _) : 0; if (cut) { - c = dnode_delete(r, c); + c = dnode_delete(x->nodes + index, c); dnode_free(c, nullptr); free(c); + --x->size; } return cmp; @@ -178,7 +198,10 @@ int libcdsb_dict_foreach(dict_t* x, void* dt, dict_access_callback callback, boo } while ((c = stack_pop(&z))) { - if ((r = callback(vnode_peek(&c->key, c->key_type), c->key_type, vnode_peek(&c->value, c->val_type), c->val_type, dt))) + void* k = vnode_peek(&c->key, c->key_type); + void* v = vnode_peek(&c->value, c->val_type); + + if ((r = callback(k, c->key_type, v, c->val_type, dt))) break; if (!dnode_is_empty(c->right)) stack_push(&z, c->right); diff --git a/src/dict/include.h b/src/dict/include.h index 9a10f6f..9926a72 100644 --- a/src/dict/include.h +++ b/src/dict/include.h @@ -8,9 +8,12 @@ #ifndef LIBCDSB_SRC_DICT_INCLUDE_H #define LIBCDSB_SRC_DICT_INCLUDE_H +#ifndef DICT_CAPACITY_BLOCK #define CAPACITY_BLOCK 100 +#else +#define CAPACITY_BLOCK DICT_CAPACITY_BLOCK +#endif #define REBUILD_POINT_MAX 0.65 -#define REBUILD_POINT_MIN 1 typedef struct libcdsb_dict_node { struct libcdsb_dict_node* left;