/* This software is licensed by the MIT License, see LICENSE file */ /* Copyright © 2022 Gregory Lirent */ #include "include.h" _Bool libcdsb_map_update(map_t* x, const void* k, vtype kt, const void* v, vtype vt) { int cmp; mnode_t* n; mnode_t* p; vnode_t kn; n = x->root; kn = vnode_tcreate(x->type, k, kt); kt = x->type; k = vnode_peek(&kn, kt); if (!mnode_is_empty(n)) { do { p = n; cmp = vtype_compare(k, kt, vnode_peek(&n->key, kt), kt); if (cmp == 0) { vnode_free(&n->key, kt); vnode_free(&n->value, n->type); n->key = kn; n->value = vnode_create(v, vt); n->type = vt; return true; } n = (cmp < 0) ? n->left : n->right; } while (!mnode_is_empty(n)); n = mnode_create(kn, p, 1); if (cmp < 0) p->left = n; else p->right = n; if (!mnode_is_root(p)) mnode_fixup(&x->root, n); } else n = x->root = mnode_create(kn, mnode_empty, 0); n->value = vnode_create(v, vt); n->type = vt; return false; } int libcdsb_map_find(map_t* x, const void* k, vtype t, void* _, map_access_callback callback, _Bool cut) { mnode_t* c; void *key; int cmp; c = x->root; while (!mnode_is_empty(c)) { key = vnode_peek(&c->key, x->type); cmp = vtype_compare(key, x->type, k, t); if (cmp == 0) { cmp = (callback) ? callback(key, x->type, vnode_peek(&c->value, c->type), c->type, _) : 0; if (cut) { c = mnode_delete(&x->root, c); vnode_free(&c->key, x->type); vnode_free(&c->value, c->type); free(c); } return cmp; } } return -1; } int libcdsb_map_foreach(map_t* x, void* dt, map_access_callback callback, _Bool flush) { stack_t z = { .prev = 0, .value = x->root }; int r = 0; mnode_t* c; if (mnode_is_empty(x->root)) return 0; while ((c = stack_pop(&z))) { if ((r = callback(vnode_peek(&c->key, x->type), x->type, vnode_peek(&c->value, c->type), c->type, dt))) break; if (!mnode_is_empty(c->right)) stack_push(&z, c->right); if (!mnode_is_empty(c->left)) stack_push(&z, c->left); if (flush) { vnode_free(&c->key, x->type); vnode_free(&c->value, c->type); free(c); } } if (flush) { while (c) { if (!mnode_is_empty(c->right)) stack_push(&z, c->right); if (!mnode_is_empty(c->left)) stack_push(&z, c->left); vnode_free(&c->key, x->type); vnode_free(&c->value, c->type); free(c); c = stack_pop(&z); } memset(x, 0, sizeof(*x)); } else stack_flush(&z); return r; }