/* 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_find(val_t* x, set_t* s, const void* v, vtype t, _Bool cut) { rbnode_t* c; int cmp; c = s->root; while (!rbnode_is_empty(c)) { cmp = vtype_compare(vnode_peek(&c->value, s->type), s->type, v, t); if (cmp == 0) { if (cut) { c = rbnode_delete(&s->root, c); if (!is_null(x)) { value_set(x, c->value, s->type, VF_WRITEABLE|VF_REMOVABLE); } else vnode_free(&c->value, s->type); free(c); } else if (!is_null(x)) value_set(x, c->value, s->type, VF_UNDEFINED); return true; } c = (cmp < 0) ? c->right : c->left; } return rbnode_empty; } _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_foreach(set_t* x, void* data, vset_foreach_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; }