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"
|
|
|
|
|
2022-06-09 16:29:10 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-06-09 16:29:10 +03:00
|
|
|
int libcdsb_vset_find(vtype_set* x, const void* v, vtype t, void* _, vset_access_callback callback, bool cut) {
|
2022-06-08 20:59:46 +03:00
|
|
|
rbnode_t* c;
|
|
|
|
void *val;
|
|
|
|
int cmp;
|
|
|
|
|
|
|
|
c = x->root;
|
|
|
|
|
|
|
|
while (!rbnode_is_empty(c)) {
|
|
|
|
val = vnode_peek(&c->value, x->type);
|
2022-06-10 21:22:52 +03:00
|
|
|
cmp = vtype_compare(v, t, val, x->type);
|
2022-06-08 20:59:46 +03:00
|
|
|
|
|
|
|
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;
|
2022-06-10 21:22:52 +03:00
|
|
|
} else c = (cmp < 0) ? c->left : c->right;
|
2022-06-08 20:59:46 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-06-09 16:29:10 +03:00
|
|
|
int libcdsb_vset_foreach(set_t* x, void* data, vset_access_callback callback, bool flush) {
|
2022-08-18 03:15:57 +03:00
|
|
|
stack_t z;
|
|
|
|
int r;
|
2022-06-06 23:46:55 +03:00
|
|
|
rbnode_t* c;
|
2022-06-06 11:23:33 +03:00
|
|
|
|
2022-08-18 03:15:57 +03:00
|
|
|
stack_init(&z);
|
|
|
|
stack_push(&z, x->root);
|
|
|
|
|
|
|
|
r = 0;
|
|
|
|
|
|
|
|
if (rbnode_is_empty(x->root))
|
|
|
|
return 0;
|
2022-06-07 21:42:11 +03:00
|
|
|
|
2022-06-08 00:11:42 +03:00
|
|
|
while ((c = stack_pop(&z))) {
|
2022-06-08 09:58:16 +03:00
|
|
|
if ((r = callback(vnode_peek(&c->value, x->type), x->type, data)))
|
2022-06-07 21:42:11 +03:00
|
|
|
break;
|
2022-06-08 09:58:16 +03:00
|
|
|
|
2022-06-08 00:11:42 +03:00
|
|
|
|
|
|
|
if (!rbnode_is_empty(c->right)) stack_push(&z, c->right);
|
|
|
|
if (!rbnode_is_empty(c->left)) stack_push(&z, c->left);
|
2022-06-08 09:58:16 +03:00
|
|
|
|
|
|
|
if (flush) {
|
|
|
|
vnode_free(&c->value, x->type);
|
|
|
|
free(c);
|
|
|
|
}
|
2022-06-06 11:23:33 +03:00
|
|
|
}
|
|
|
|
|
2022-06-08 09:58:16 +03:00
|
|
|
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);
|
|
|
|
|
2022-06-07 21:42:11 +03:00
|
|
|
return r;
|
2022-06-06 11:23:33 +03:00
|
|
|
}
|