/* This software is licensed by the MIT License, see LICENSE file */ /* Copyright © 2022 Gregory Lirent */ #include "../../include/extra/set.h" #include "../__internal/rbtree.h" bool libcdsb_vset_insert(set_t* x, const void* v, vtype t) { int cmp; rbnode_t* n; rbnode_t* p; vnode_t vn; n = x->root; vn = vnode_tcreate(x->type, v, t); t = x->type; v = vnode_peek(&vn, t); if (!rbnode_is_empty(n)) { do { p = n; cmp = vtype_compare(v, t, vnode_peek(&n->value, t), t); if (cmp == 0) { vnode_free(&vn, t); return false; } n = (cmp < 0) ? n->left : n->right; } while (!rbnode_is_empty(n)); n = rbnode_create(vn, p, 1); if (cmp < 0) p->left = n; else p->right = n; if (!rbnode_is_root(p)) rbnode_fixup(&x->root, n); } else n = x->root = rbnode_create(vn, rbnode_empty, 0); return true; } int libcdsb_vset_find(vtype_set* x, const void* v, vtype t, void* _, vset_access_callback callback, bool cut) { rbnode_t* c; void *val; int cmp; c = x->root; while (!rbnode_is_empty(c)) { val = vnode_peek(&c->value, x->type); cmp = vtype_compare(val, x->type, v, t); if (cmp == 0) { cmp = (callback) ? callback(val, x->type, _) : 0; if (cut) { c = rbnode_delete(&x->root, c); vnode_free(&c->value, x->type); free(c); } return cmp; } } return -1; } int libcdsb_vset_foreach(set_t* x, void* data, vset_access_callback callback, bool flush) { stack_t z = { .prev = 0, .value = x->root }; int r = 0; rbnode_t* c; if (rbnode_is_empty(x->root)) return 0; while ((c = stack_pop(&z))) { if ((r = callback(vnode_peek(&c->value, x->type), x->type, data))) break; if (!rbnode_is_empty(c->right)) stack_push(&z, c->right); if (!rbnode_is_empty(c->left)) stack_push(&z, c->left); if (flush) { vnode_free(&c->value, x->type); free(c); } } if (flush) { while (c) { if (!rbnode_is_empty(c->right)) stack_push(&z, c->right); if (!rbnode_is_empty(c->left)) stack_push(&z, c->left); vnode_free(&c->value, x->type); free(c); c = stack_pop(&z); } memset(x, 0, sizeof(*x)); } else stack_flush(&z); return r; }