Merge branch 'rbtree' into discrete-tests
This commit is contained in:
commit
0c2b93e111
@ -17,6 +17,6 @@ extern ssize_t libcdsb_array_get(vtype_value* x, vtype_array* s, ssize_t index,
|
||||
extern ssize_t libcdsb_array_find(const vtype_array* x, const void* value, vtype value_type) LIBCDSB_nt__ LIBCDSB_nn1__;
|
||||
extern ssize_t libcdsb_array_push( vtype_array* x, const void* value, vtype value_type) LIBCDSB_nt__ LIBCDSB_nn1__;
|
||||
|
||||
extern int libcdsb_array_foreach(const vtype_array* x, int (*callback)(void* value, ssize_t index, vtype type)) LIBCDSB_nt__ LIBCDSB_nn12__;
|
||||
extern int libcdsb_array_foreach(const vtype_array* x, void* data, int (*callback)(void* value, ssize_t index, vtype type, void* data)) LIBCDSB_nt__ LIBCDSB_nn13__;
|
||||
|
||||
#endif /* LIBCDSB_EXTRA_ARRAY_H */
|
||||
|
@ -19,6 +19,6 @@ extern size_t libcdsb_list_count(const vtype_list* s, const void* value, vtype
|
||||
|
||||
extern ssize_t libcdsb_list_get(vtype_value* x, vtype_list* s, ssize_t index, _Bool cut) LIBCDSB_nt__ LIBCDSB_nn2__;
|
||||
|
||||
extern int libcdsb_list_foreach(const vtype_list* x, int (*callback)(void* value, ssize_t index, vtype type)) LIBCDSB_nt__ LIBCDSB_nn12__;
|
||||
extern int libcdsb_list_foreach(const vtype_list* x, void* data, int (*callback)(void* value, ssize_t index, vtype type, void* data)) LIBCDSB_nt__ LIBCDSB_nn13__;
|
||||
|
||||
#endif /* LIBCDSB_EXTRA_LIST_H */
|
||||
|
@ -7,6 +7,16 @@
|
||||
#ifndef LIBCDSB_EXTRA_MEMORY_H
|
||||
#define LIBCDSB_EXTRA_MEMORY_H
|
||||
|
||||
typedef struct libcdsb_stack_node {
|
||||
struct libcdsb_stack_node* prev;
|
||||
void* value;
|
||||
} stack_t;
|
||||
|
||||
extern void libcdsb_stack_init (stack_t* stack);
|
||||
extern void libcdsb_stack_push (stack_t* stack, void* value);
|
||||
extern void* libcdsb_stack_pop (stack_t* stack);
|
||||
extern void libcdsb_stack_flush(stack_t* stack);
|
||||
|
||||
extern void* libcdsb_aalloc (size_t a, size_t n) LIBCDSB_nt__ LIBCDSB_wur__;
|
||||
extern void* libcdsb_malloc (size_t n) LIBCDSB_nt__ LIBCDSB_wur__;
|
||||
extern void* libcdsb_calloc (size_t n, size_t c) LIBCDSB_nt__ LIBCDSB_wur__;
|
||||
@ -17,4 +27,9 @@ extern void* libcdsb_realloc(void *p, size_t n) LIBCDSB_nt__ LIBCDSB_wur__;
|
||||
#define calloc libcdsb_calloc
|
||||
#define realloc libcdsb_realloc
|
||||
|
||||
#define stack_init libcdsb_stack_init
|
||||
#define stack_push libcdsb_stack_push
|
||||
#define stack_pop libcdsb_stack_pop
|
||||
#define stack_flush libcdsb_stack_flush
|
||||
|
||||
#endif /* LIBCDSB_EXTRA_MEMORY_H */
|
||||
|
@ -11,6 +11,6 @@
|
||||
extern _Bool libcdsb_vset_find (vtype_value* x, vtype_set* s, const void* value, vtype type, _Bool cut);
|
||||
extern _Bool libcdsb_vset_insert(vtype_set* x, const void* value, vtype type);
|
||||
|
||||
extern int libcdsb_vset_foreach(const vtype_set* x, int (*callback)(const void* value, vtype type)) LIBCDSB_nt__ LIBCDSB_nn12__;
|
||||
extern int libcdsb_vset_foreach(const vtype_set* x, void* data, int (*callback)(const void* value, vtype type, void* data)) LIBCDSB_nt__ LIBCDSB_nn13__;
|
||||
|
||||
#endif /* LIBCDSB_EXTRA_SET_H */
|
||||
|
@ -6,14 +6,6 @@
|
||||
#ifndef LIBCDSB_SRC_INTERNAL_RBTREE_H
|
||||
#define LIBCDSB_SRC_INTERNAL_RBTREE_H
|
||||
|
||||
typedef enum libcdsb_rbtree_iter_flags {
|
||||
RBI_INORDER = 0,
|
||||
RBI_PREORDER = 1,
|
||||
RBI_POSTORDER = 2,
|
||||
|
||||
RBI_REVERSE = 4,
|
||||
} rbiter_f;
|
||||
|
||||
typedef struct libcdsb_rbtree_node {
|
||||
struct libcdsb_rbtree_node* left;
|
||||
struct libcdsb_rbtree_node* right;
|
||||
@ -23,30 +15,17 @@ typedef struct libcdsb_rbtree_node {
|
||||
short colored;
|
||||
} rbnode_t;
|
||||
|
||||
typedef struct libcdsb_rbtree_iter {
|
||||
struct libcdsb_rbtree_node* cursor;
|
||||
int flags;
|
||||
} rbiter_t;
|
||||
|
||||
extern const rbnode_t LIBCDSB_RBTREE_NODE_EMPTY[1];
|
||||
extern rbnode_t LIBCDSB_RBTREE_NODE_EMPTY[1];
|
||||
|
||||
extern void* libcdsb_rbtree_node_create(void* value, rbnode_t* parent, int colored, int size);
|
||||
extern void libcdsb_rbtree_node_fixup (rbnode_t** root, rbnode_t* node);
|
||||
extern rbnode_t* libcdsb_rbtree_node_delete(rbnode_t** root, rbnode_t* node);
|
||||
|
||||
extern _Bool libcdsb_rbtree_iter_init (rbiter_t* iter, rbnode_t *const *root, rbiter_f flags);
|
||||
extern rbnode_t* libcdsb_rbtree_iter_next (rbiter_t* iter);
|
||||
extern void libcdsb_rbtree_iter_reset(rbiter_t* iter);
|
||||
|
||||
#define rbnode_empty ((rbnode_t*)LIBCDSB_RBTREE_NODE_EMPTY)
|
||||
#define rbnode_create(v, p, c) ((rbnode_t*)libcdsb_rbtree_node_create(v, p, c, sizeof(rbnode_t)))
|
||||
#define rbnode_fixup libcdsb_rbtree_node_fixup
|
||||
#define rbnode_delete libcdsb_rbtree_node_delete
|
||||
|
||||
#define rbiter_init libcdsb_rbtree_iter_init
|
||||
#define rbiter_next libcdsb_rbtree_iter_next
|
||||
#define rbiter_reset libcdsb_rbtree_iter_reset
|
||||
|
||||
#define rbnode_is_empty(n) ((n) == rbnode_empty)
|
||||
#define rbnode_is_root(n) rbnode_is_empty((n)->parent)
|
||||
|
||||
|
@ -76,7 +76,7 @@ ssize_t libcdsb_array_get(val_t* x, arr_t* s, ssize_t i, _Bool cut) {
|
||||
|
||||
/*#####################################################################################################################*/
|
||||
|
||||
int libcdsb_array_foreach(const vtype_array* x, int (*callback)(void* value, ssize_t index, vtype type)) {
|
||||
int libcdsb_array_foreach(const vtype_array* x, void* data, int (*callback)(void* value, ssize_t index, vtype type, void* data)) {
|
||||
|
||||
void* p;
|
||||
void* e;
|
||||
@ -88,7 +88,7 @@ int libcdsb_array_foreach(const vtype_array* x, int (*callback)(void* value, ssi
|
||||
n = 0;
|
||||
|
||||
while (p < e) {
|
||||
if ((r = callback(p, n, x->type)))
|
||||
if ((r = callback(p, n, x->type, data)))
|
||||
return r;
|
||||
|
||||
p += vtype_size(x->type);
|
||||
|
53
src/extra.c
53
src/extra.c
@ -81,6 +81,59 @@ char* libcdsb_strndup(const char* s, size_t n) {
|
||||
/*#####################################################################################################################*/
|
||||
|
||||
|
||||
void libcdsb_stack_init(stack_t* x) {
|
||||
memset(x, 0, sizeof(*x));
|
||||
}
|
||||
|
||||
|
||||
void libcdsb_stack_push(stack_t* x, void* value) {
|
||||
stack_t* n;
|
||||
|
||||
if (x->value) {
|
||||
if (!(n = malloc(sizeof(*n))))
|
||||
abort();
|
||||
|
||||
n->prev = x->prev;
|
||||
n->value = x->value;
|
||||
x->prev = n;
|
||||
}
|
||||
|
||||
x->value = value;
|
||||
}
|
||||
|
||||
void* libcdsb_stack_pop(stack_t* x) {
|
||||
|
||||
stack_t* n;
|
||||
void* v;
|
||||
|
||||
v = x->value;
|
||||
|
||||
if (x->prev) {
|
||||
n = x->prev;
|
||||
x->prev = n->prev;
|
||||
x->value = n->value;
|
||||
free(n);
|
||||
} else x->value = 0;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
void libcdsb_stack_flush(stack_t* stack) {
|
||||
stack_t* c;
|
||||
|
||||
while (stack->prev) {
|
||||
c = stack->prev;
|
||||
stack->prev = c->prev;
|
||||
free(c);
|
||||
}
|
||||
|
||||
stack->value = 0;
|
||||
}
|
||||
|
||||
/*#####################################################################################################################*/
|
||||
|
||||
|
||||
size_t libcdsb_strlen(const char* s) {
|
||||
static const size_t m = (sizeof(size_t) == 8) ? 0x8080808080808080UL : 0x80808080UL;
|
||||
static const size_t d = (sizeof(size_t) == 8) ? 0x0101010101010101UL : 0x01010101UL;
|
||||
|
@ -163,7 +163,7 @@ _Bool libcdsb_list_update(list_t* x, ssize_t i, const void* v, vtype t, int ins)
|
||||
/*#####################################################################################################################*/
|
||||
|
||||
|
||||
int libcdsb_list_foreach(const vtype_list* x, int (*callback)(void* value, ssize_t index, vtype type)) {
|
||||
int libcdsb_list_foreach(const vtype_list* x, void* data, int (*callback)(void* value, ssize_t index, vtype type, void* data)) {
|
||||
|
||||
lnode_t* c;
|
||||
size_t n;
|
||||
@ -173,7 +173,7 @@ int libcdsb_list_foreach(const vtype_list* x, int (*callback)(void* value, ssize
|
||||
n = 0;
|
||||
|
||||
while (!is_null(c)) {
|
||||
if ((r = callback(vnode_peek(&c->node, c->type), n, c->type)) != 0)
|
||||
if ((r = callback(vnode_peek(&c->node, c->type), n, c->type, data)) != 0)
|
||||
return r;
|
||||
c = c->next;
|
||||
++n;
|
||||
|
194
src/rbtree.c
194
src/rbtree.c
@ -3,9 +3,6 @@
|
||||
|
||||
#include "__internal/rbtree.h"
|
||||
|
||||
#define RBI_BREAK ((rbiter_f)3)
|
||||
#define RBI_FIRST ((rbiter_f)8)
|
||||
|
||||
typedef enum libcdsb_rbtree_node_direction {
|
||||
RBD_LEFT = 1,
|
||||
RBD_RIGHT = 2
|
||||
@ -16,7 +13,7 @@ typedef enum libcdsb_rbtree_node_direction {
|
||||
|
||||
/*#####################################################################################################################*/
|
||||
|
||||
const rbnode_t LIBCDSB_RBTREE_NODE_EMPTY[1] = {{
|
||||
rbnode_t LIBCDSB_RBTREE_NODE_EMPTY[1] = {{
|
||||
.colored = 0,
|
||||
.value = 0,
|
||||
.parent = rbnode_empty,
|
||||
@ -45,105 +42,12 @@ static inline void rotate(rbnode_t **x, rbnode_t *c, rbdir_t d) {
|
||||
}
|
||||
|
||||
static inline void replace(rbnode_t** x, rbnode_t* c, rbnode_t* n) {
|
||||
rbnode_t* p;
|
||||
|
||||
p = c->parent;
|
||||
|
||||
if (!rbnode_is_empty(p)) {
|
||||
if (p->left == c) {
|
||||
p->left = n;
|
||||
} else p->right = n;
|
||||
if (!rbnode_is_root(c)) {
|
||||
if (c->parent->left == c) {
|
||||
c->parent->left = n;
|
||||
} else c->parent->right = n;
|
||||
} else *x = n;
|
||||
|
||||
n->parent = p;
|
||||
}
|
||||
|
||||
|
||||
/*#####################################################################################################################*/
|
||||
|
||||
|
||||
static rbnode_t* inorder_next(rbnode_t* c, rbiter_f f) {
|
||||
rbdir_t d = (f&RBI_REVERSE) ? RBD_RIGHT : RBD_LEFT;
|
||||
rbnode_t* p;
|
||||
|
||||
for (;;) {
|
||||
if (rbnode_is_empty(rbdir_inv(c, d))) {
|
||||
p = c->parent;
|
||||
|
||||
if (rbnode_is_root(p) || rbdir_dir(p, d) == c) {
|
||||
return p;
|
||||
}
|
||||
|
||||
c = p;
|
||||
p = c->parent;
|
||||
|
||||
if (rbnode_is_root(p) || rbdir_dir(p, d) == c) {
|
||||
return p;
|
||||
}
|
||||
|
||||
do {
|
||||
c = p;
|
||||
p = c->parent;
|
||||
} while(rbdir_inv(p, d) == c);
|
||||
|
||||
c = p;
|
||||
|
||||
} else { c = rbdir_inv(c, d); break; }
|
||||
|
||||
if (rbnode_is_root(c)) return c;
|
||||
}
|
||||
|
||||
while (!rbnode_is_empty(rbdir_dir(c, d)))
|
||||
c = rbdir_dir(c, d);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static rbnode_t* postorder_next(rbnode_t* c, rbiter_f f) {
|
||||
rbdir_t d = (f&RBI_REVERSE) ? RBD_RIGHT : RBD_LEFT;
|
||||
rbnode_t* p;
|
||||
|
||||
if (rbnode_is_empty(p = c->parent))
|
||||
return c;
|
||||
|
||||
if (rbdir_dir(p, d) == c && !rbnode_is_empty(rbdir_inv(p, d))) {
|
||||
c = rbdir_inv(p, d);
|
||||
|
||||
while (!rbnode_is_empty(c)) {
|
||||
p = c;
|
||||
c = (!rbnode_is_empty(rbdir_inv(p, d)))
|
||||
? rbdir_inv(p, d)
|
||||
: rbdir_dir(p, d);
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static rbnode_t* preorder_next(rbnode_t* c, rbiter_f f) {
|
||||
rbdir_t d = (f&RBI_REVERSE) ? RBD_RIGHT : RBD_LEFT;
|
||||
rbnode_t* p;
|
||||
|
||||
if (!rbnode_is_empty(rbdir_dir(c, d)))
|
||||
return rbdir_dir(c, d);
|
||||
|
||||
for (;;) {
|
||||
if (!rbnode_is_empty(rbdir_inv(c, d))) {
|
||||
return rbdir_inv(c, d);
|
||||
}
|
||||
|
||||
p = c->parent;
|
||||
|
||||
while (rbdir_inv(p, d) == c) {
|
||||
c = p;
|
||||
p = c->parent;
|
||||
}
|
||||
|
||||
if (rbnode_is_empty(p))
|
||||
return c;
|
||||
|
||||
c = p;
|
||||
}
|
||||
n->parent = c->parent;
|
||||
}
|
||||
|
||||
|
||||
@ -290,89 +194,3 @@ void* libcdsb_rbtree_node_create(void* v, rbnode_t* p, int c, int n) {
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
/*#####################################################################################################################*/
|
||||
|
||||
|
||||
_Bool libcdsb_rbtree_iter_init(rbiter_t* iter, rbnode_t *const *root, rbiter_f f) {
|
||||
rbdir_t d = (f&RBI_REVERSE) ? RBD_RIGHT : RBD_LEFT;
|
||||
rbnode_t* c = *root;
|
||||
|
||||
if (!rbnode_is_empty(c)) {
|
||||
if (!(f&RBI_BREAK)) {
|
||||
while (rbdir_dir(c, d) != rbnode_empty) {
|
||||
c = rbdir_dir(c, d);
|
||||
}
|
||||
} else if ((f&RBI_BREAK) == RBI_POSTORDER) {
|
||||
rbnode_t* p;
|
||||
|
||||
do {
|
||||
p = c;
|
||||
c = (!rbnode_is_empty(rbdir_dir(c, d))) ? rbdir_dir(c, d) : rbdir_inv(c, d);
|
||||
} while (!rbnode_is_empty(c));
|
||||
|
||||
c = p;
|
||||
}
|
||||
} else {
|
||||
iter->cursor = rbnode_empty;
|
||||
iter->flags = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
iter->cursor = c;
|
||||
iter->flags = f|RBI_FIRST;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void libcdsb_rbtree_iter_reset(rbiter_t* iter) {
|
||||
if (iter->flags&RBI_FIRST) return;
|
||||
|
||||
while (!rbnode_is_empty(iter->cursor->parent)) {
|
||||
iter->cursor = iter->cursor->parent;
|
||||
}
|
||||
|
||||
if ((iter->flags&RBI_BREAK) == RBI_BREAK) {
|
||||
libcdsb_rbtree_iter_init(iter, &iter->cursor, iter->flags&~RBI_BREAK);
|
||||
} else libcdsb_rbtree_iter_init(iter, &iter->cursor, iter->flags);
|
||||
}
|
||||
|
||||
|
||||
rbnode_t* libcdsb_rbtree_iter_next(rbiter_t* iter) {
|
||||
|
||||
rbnode_t* c;
|
||||
|
||||
c = iter->cursor;
|
||||
|
||||
if (rbnode_is_empty(c))
|
||||
return rbnode_empty;
|
||||
|
||||
if (!(iter->flags&RBI_FIRST)) {
|
||||
if (rbnode_is_root(c)) {
|
||||
if ((iter->flags&RBI_BREAK) == RBI_INORDER) {
|
||||
iter->flags |= RBI_BREAK;
|
||||
} else {
|
||||
libcdsb_rbtree_iter_reset(iter);
|
||||
if (iter->flags&RBI_POSTORDER) {
|
||||
iter->flags |= RBI_BREAK;
|
||||
return c;
|
||||
} else return rbnode_empty;
|
||||
}
|
||||
}
|
||||
} else if ((iter->flags&RBI_BREAK) == RBI_BREAK) {
|
||||
iter->flags = (iter->flags&~(RBI_BREAK^RBI_POSTORDER));
|
||||
return rbnode_empty;
|
||||
} else iter->flags &= ~RBI_FIRST;
|
||||
|
||||
switch (iter->flags&RBI_BREAK) {
|
||||
case RBI_POSTORDER: iter->cursor = postorder_next(c, iter->flags); break;
|
||||
case RBI_PREORDER: iter->cursor = preorder_next(c, iter->flags); break;
|
||||
case RBI_INORDER:
|
||||
default: iter->cursor = inorder_next(c, iter->flags); break;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
@ -4,36 +4,6 @@
|
||||
#include "../../include/set.h"
|
||||
#include "../__internal/rbtree.h"
|
||||
|
||||
/*#####################################################################################################################*/
|
||||
|
||||
|
||||
static int tree_compare(rbiter_t* s0, rbiter_t* s1, vtype t) {
|
||||
rbnode_t* p0;
|
||||
rbnode_t* p1;
|
||||
int cmp;
|
||||
|
||||
for(;;) {
|
||||
p0 = rbiter_next(s0);
|
||||
p1 = rbiter_next(s1);
|
||||
|
||||
if (rbnode_is_empty(p0) || rbnode_is_empty(p1)) {
|
||||
goto end_;
|
||||
} else cmp = vnode_compare(&p0->value, t, &p1->value, t);
|
||||
|
||||
if (cmp != 0) break;
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
p0 = rbiter_next(s0);
|
||||
p1 = rbiter_next(s1);
|
||||
|
||||
if (rbnode_is_empty(p0) || rbnode_is_empty(p1)) {
|
||||
end_:
|
||||
if (p0 == p1) return cmp;
|
||||
return (rbnode_is_empty(p0)) ? -1 : 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*#####################################################################################################################*/
|
||||
|
||||
@ -43,10 +13,13 @@ void vset_init(vtype_set* x, vtype t) {
|
||||
x->type = t;
|
||||
}
|
||||
|
||||
|
||||
void vset_free(vtype_set* x) {
|
||||
rbnode_t* t;
|
||||
rbnode_t* c;
|
||||
|
||||
c = x->root;
|
||||
|
||||
while (!rbnode_is_empty(x->root)) {
|
||||
if (!rbnode_is_empty(c->left)) {
|
||||
c = c->left;
|
||||
@ -71,28 +44,61 @@ void vset_free(vtype_set* x) {
|
||||
x->type = 0;
|
||||
}
|
||||
|
||||
|
||||
size_t vset_size(const vtype_set* x) {
|
||||
size_t n;
|
||||
rbiter_t i;
|
||||
stack_t s = { .prev = 0, .value = x->root };
|
||||
size_t n = 0;
|
||||
rbnode_t* c;
|
||||
|
||||
n = 0;
|
||||
|
||||
if (rbiter_init(&i, &x->root, 0)) {
|
||||
while (!rbnode_is_empty(rbiter_next(&i)))
|
||||
++n;
|
||||
while ((c = stack_pop(&s))) {
|
||||
++n;
|
||||
if (!rbnode_is_empty(c->left))
|
||||
stack_push(&s, c->left);
|
||||
if (!rbnode_is_empty(c->right))
|
||||
stack_push(&s, c->right);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
int vset_compare(const vtype_set* s0, const vtype_set* s1) {
|
||||
rbiter_t iter[2];
|
||||
stack_t s = { .prev = 0, .value = 0 };
|
||||
vtype t = s0->type;
|
||||
int c = 0;
|
||||
|
||||
if (s0 == s1) return 0;
|
||||
if (s0->type == s1->type) {
|
||||
rbiter_init(iter+0, &s0->root, RBI_INORDER);
|
||||
rbiter_init(iter+1, &s1->root, RBI_INORDER);
|
||||
if (s0 == s1 || s0->root == s1->root) return 0;
|
||||
if (s0->type != s1->type) return s0->type - s1->type;
|
||||
|
||||
return tree_compare(iter+0, iter+1, s0->type);
|
||||
} else return s0->type < s1->type ? -1 : 1;
|
||||
stack_push(&s, s0->root);
|
||||
stack_push(&s, s1->root);
|
||||
|
||||
for (rbnode_t *c0, *c1;;) {
|
||||
c0 = stack_pop(&s);
|
||||
c1 = stack_pop(&s);
|
||||
|
||||
if (is_null(c0)) return 0;
|
||||
|
||||
if (rbnode_is_empty(c0) || rbnode_is_empty(c1)) {
|
||||
if (c0 != c1) {
|
||||
stack_flush(&s);
|
||||
return rbnode_is_empty(c0) ? -1 : 1;
|
||||
}
|
||||
} else if ((c = vnode_compare(c0->value, t, c1->value, t))) {
|
||||
if (c0->left == c1->right) {
|
||||
c = vnode_compare(c1->value, t, c0->right->value, t);
|
||||
if (!c) c = vnode_compare(c1->left->value, t, c0->value, t);
|
||||
} else if (c0->right == c1->left) {
|
||||
c = vnode_compare(c0->value, t, c1->right->value, t);
|
||||
if (!c) c = vnode_compare(c0->left->value, t, c1->value, t);
|
||||
}
|
||||
|
||||
if (c) { stack_flush(&s); return c; }
|
||||
} else {
|
||||
stack_push(&s, c0->left);
|
||||
stack_push(&s, c1->left);
|
||||
stack_push(&s, c0->right);
|
||||
stack_push(&s, c1->right);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -76,17 +76,23 @@ _Bool libcdsb_vset_insert(set_t* x, const void* v, vtype t) {
|
||||
/*#####################################################################################################################*/
|
||||
|
||||
|
||||
int libcdsb_vset_foreach(const vtype_set* x, int (*callback)(const void* value, vtype type)) {
|
||||
rbiter_t i;
|
||||
int r;
|
||||
int libcdsb_vset_foreach(const set_t* x, void* data, int (*callback)(const void* value, vtype type, void* data)) {
|
||||
stack_t s = { .prev = 0, .value = x->root };
|
||||
int r = 0;
|
||||
rbnode_t* c;
|
||||
|
||||
if (rbiter_init(&i, &x->root, 0)) {
|
||||
while (!rbnode_is_empty(c = rbiter_next(&i))) {
|
||||
if ((r = callback(vnode_peek(&c->value, x->type), x->type)))
|
||||
return r;
|
||||
if (rbnode_is_empty(x->root)) return 0;
|
||||
|
||||
while ((c = stack_pop(&s))) {
|
||||
if ((r = callback(vnode_peek(&c->value, x->type), x->type, data))) {
|
||||
stack_flush(&s);
|
||||
break;
|
||||
}
|
||||
if (!rbnode_is_empty(c->left))
|
||||
stack_push(&s, c->left);
|
||||
if (!rbnode_is_empty(c->right))
|
||||
stack_push(&s, c->right);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return r;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user