libcdsb/src/set/extra.c

93 lines
2.3 KiB
C
Raw Normal View History

2022-06-06 11:23:33 +03:00
/* 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) {
2022-06-06 23:46:55 +03:00
int cmp;
2022-06-06 11:23:33 +03:00
rbnode_t* n;
rbnode_t* p;
2022-06-06 23:46:55 +03:00
vnode_t vn;
2022-06-06 11:23:33 +03:00
2022-06-06 23:46:55 +03:00
n = x->root;
vn = vnode_tcreate(x->type, v, t);
t = x->type;
v = vnode_peek(&vn, t);
2022-06-06 11:23:33 +03:00
if (!rbnode_is_empty(n)) {
do {
2022-06-06 23:46:55 +03:00
p = n;
cmp = vtype_compare(v, t, vnode_peek(&n->value, t), t);
2022-06-06 11:23:33 +03:00
2022-06-06 23:46:55 +03:00
if (cmp == 0) {
vnode_free(&vn, t);
return false;
}
2022-06-06 11:23:33 +03:00
2022-06-06 23:46:55 +03:00
n = (cmp < 0) ? n->left : n->right;
2022-06-06 11:23:33 +03:00
} while (!rbnode_is_empty(n));
2022-06-06 23:46:55 +03:00
n = rbnode_create(vn, p, 1);
2022-06-06 11:23:33 +03:00
2022-06-06 23:46:55 +03:00
if (cmp < 0) p->left = n;
2022-06-06 11:23:33 +03:00
else p->right = n;
2022-06-06 23:46:55 +03:00
if (!rbnode_is_root(p))
2022-06-06 11:23:33 +03:00
rbnode_fixup(&x->root, n);
2022-06-06 23:46:55 +03:00
} else n = x->root = rbnode_create(vn, rbnode_empty, 0);
2022-06-06 11:23:33 +03:00
return true;
}
/*#####################################################################################################################*/
int libcdsb_vset_foreach(const vtype_set* x, int (*callback)(const void* value, vtype type)) {
rbiter_t i;
int r;
2022-06-06 23:46:55 +03:00
rbnode_t* c;
2022-06-06 11:23:33 +03:00
if (rbiter_init(&i, &x->root, 0)) {
2022-06-06 23:46:55 +03:00
while (!rbnode_is_empty(c = rbiter_next(&i))) {
if ((r = callback(vnode_peek(&c->value, x->type), x->type)))
2022-06-06 11:23:33 +03:00
return r;
}
}
return 0;
}