87 lines
2.2 KiB
C
87 lines
2.2 KiB
C
|
|
/* 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;
|
||
|
|
|
||
|
|
n = x->root;
|
||
|
|
|
||
|
|
if (!rbnode_is_empty(n)) {
|
||
|
|
do {
|
||
|
|
p = n;
|
||
|
|
cmp = vtype_compare(vnode_peek(&n->value, x->type), x->type, v, t);
|
||
|
|
|
||
|
|
if (cmp == 0) return false;
|
||
|
|
|
||
|
|
n = (cmp > 0) ? n->left : n->right;
|
||
|
|
} while (!rbnode_is_empty(n));
|
||
|
|
|
||
|
|
n = rbnode_create(0, p, 1);
|
||
|
|
|
||
|
|
if (cmp > 0) p->left = n;
|
||
|
|
else p->right = n;
|
||
|
|
|
||
|
|
if (!rbnode_is_root(n->parent))
|
||
|
|
rbnode_fixup(&x->root, n);
|
||
|
|
|
||
|
|
} else n = x->root = rbnode_create(0, p, 1);
|
||
|
|
|
||
|
|
n->value = vnode_tcreate(x->type, v, t);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*#####################################################################################################################*/
|
||
|
|
|
||
|
|
|
||
|
|
int libcdsb_vset_foreach(const vtype_set* x, int (*callback)(const void* value, vtype type)) {
|
||
|
|
rbiter_t i;
|
||
|
|
int r;
|
||
|
|
|
||
|
|
if (rbiter_init(&i, &x->root, 0)) {
|
||
|
|
while (!rbnode_is_empty(rbiter_next(&i))) {
|
||
|
|
if ((r = callback(vnode_peek(&i.cursor->value, x->type), x->type)))
|
||
|
|
return r;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|