Update rbtree-based foreach implementation
This commit is contained in:
parent
4a174df6da
commit
1d8e8efe90
@ -3,6 +3,48 @@
|
|||||||
|
|
||||||
#include "include.h"
|
#include "include.h"
|
||||||
|
|
||||||
|
static int libcdsb_builtin_foreach(map_t* x, void* data, map_access_callback callback) {
|
||||||
|
stack_t z, *top, *bot, *cur;
|
||||||
|
mnode_t* n;
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
|
memset(&z, 0, sizeof(z));
|
||||||
|
|
||||||
|
if (rbnode_is_empty(z.value = x->root))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (top = bot = &z;;) {
|
||||||
|
for (cur = bot;;) {
|
||||||
|
|
||||||
|
n = top->value;
|
||||||
|
|
||||||
|
if (!mnode_is_empty(n->left)) cur = stack_insert(cur, n->left);
|
||||||
|
if (!mnode_is_empty(n->right)) cur = stack_insert(cur, n->right);
|
||||||
|
|
||||||
|
if (!r) {
|
||||||
|
r = callback(vnode_peek(&n->key, x->type), x->type, vnode_peek(&n->value, n->type), n->type, data);
|
||||||
|
} else {
|
||||||
|
stack_flush(&z);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (top == bot) {
|
||||||
|
top = top->prev;
|
||||||
|
break;
|
||||||
|
} else top = top->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_null(top)) {
|
||||||
|
while (!is_null(bot->prev)) bot = bot->prev;
|
||||||
|
} else break;
|
||||||
|
}
|
||||||
|
|
||||||
|
stack_flush(&z);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*#####################################################################################################################*/
|
||||||
|
|
||||||
int libcdsb_map_find(map_t* x, const void* k, vtype t, void* _, map_access_callback callback, bool cut) {
|
int libcdsb_map_find(map_t* x, const void* k, vtype t, void* _, map_access_callback callback, bool cut) {
|
||||||
mnode_t* c;
|
mnode_t* c;
|
||||||
void *key;
|
void *key;
|
||||||
@ -32,47 +74,41 @@ int libcdsb_map_find(map_t* x, const void* k, vtype t, void* _, map_access_callb
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int libcdsb_map_foreach(map_t* x, void* dt, map_access_callback callback, bool flush) {
|
int libcdsb_map_foreach(map_t* x, void* data, map_access_callback callback, rbforeach_t type, bool flush) {
|
||||||
stack_t z;
|
bool reverse;
|
||||||
int r;
|
stack_t iter;
|
||||||
mnode_t* c;
|
mnode_t* n;
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
stack_init(&z);
|
reverse = type&RBFOREACH_REVERSE;
|
||||||
stack_push(&z, x->root);
|
|
||||||
|
|
||||||
r = 0;
|
switch (type&(RBFOREACH_INORDER|RBFOREACH_PREORDER|RBFOREACH_POSTORDER|RBFOREACH_BREADTH_FIRST)) {
|
||||||
|
case RBFOREACH_INORDER: iter = miter_inorder (&x->root, reverse); break;
|
||||||
|
case RBFOREACH_PREORDER: iter = miter_preorder (&x->root, reverse); break;
|
||||||
|
case RBFOREACH_POSTORDER: iter = miter_postorder(&x->root, reverse); break;
|
||||||
|
|
||||||
if (mnode_is_empty(x->root))
|
default:
|
||||||
return 0;
|
case RBFOREACH_BREADTH_FIRST: if (reverse || flush) {
|
||||||
|
iter = miter_breath_first(&x->root, type&RBFOREACH_REVERSE);
|
||||||
while ((c = stack_pop(&z))) {
|
|
||||||
if ((r = callback(vnode_peek(&c->key, x->type), x->type, vnode_peek(&c->value, c->type), c->type, dt)))
|
|
||||||
break;
|
break;
|
||||||
|
} else return libcdsb_builtin_foreach(x, data, callback);
|
||||||
if (!mnode_is_empty(c->right)) stack_push(&z, c->right);
|
|
||||||
if (!mnode_is_empty(c->left)) stack_push(&z, c->left);
|
|
||||||
|
|
||||||
if (flush) {
|
|
||||||
vnode_free(&c->key, x->type);
|
|
||||||
vnode_free(&c->value, c->type);
|
|
||||||
free(c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while ((n = stack_pop(&iter))) {
|
||||||
|
if (!r) {
|
||||||
|
r = callback(vnode_peek(&n->key, x->type), x->type, vnode_peek(&n->value, n->type), n->type, data);
|
||||||
|
} else if (!flush) {
|
||||||
|
stack_flush(&iter);
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flush) {
|
if (flush) {
|
||||||
while (c) {
|
vnode_free(&n->value, x->type);
|
||||||
if (!mnode_is_empty(c->right)) stack_push(&z, c->right);
|
free(n);
|
||||||
if (!mnode_is_empty(c->left)) stack_push(&z, c->left);
|
}
|
||||||
|
|
||||||
vnode_free(&c->key, x->type);
|
|
||||||
vnode_free(&c->value, c->type);
|
|
||||||
free(c);
|
|
||||||
|
|
||||||
c = stack_pop(&z);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(x, 0, sizeof(*x));
|
if (flush) x->root = mnode_empty;
|
||||||
} else stack_flush(&z);
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -35,4 +35,9 @@ static_assert(offsetof(struct libcdsb_set, type) == offsetof(struct l
|
|||||||
#define mnode_is_empty(n) ((n) == mnode_empty)
|
#define mnode_is_empty(n) ((n) == mnode_empty)
|
||||||
#define mnode_is_root(n) mnode_is_empty((n)->parent)
|
#define mnode_is_root(n) mnode_is_empty((n)->parent)
|
||||||
|
|
||||||
|
#define miter_inorder(x, reverse) rbiter_inorder((void*)x, reverse)
|
||||||
|
#define miter_preorder(x, reverse) rbiter_preorder((void*)x, reverse)
|
||||||
|
#define miter_postorder(x, reverse) rbiter_postorder((void*)x, reverse)
|
||||||
|
#define miter_breath_first(x, reverse) rbiter_breath_first((void*)x, reverse)
|
||||||
|
|
||||||
#endif /* LIBCDSB_SRC_MAP_INCLUDE_H */
|
#endif /* LIBCDSB_SRC_MAP_INCLUDE_H */
|
||||||
|
@ -4,6 +4,48 @@
|
|||||||
#include "../../include/set.h"
|
#include "../../include/set.h"
|
||||||
#include "../__internal/rbtree.h"
|
#include "../__internal/rbtree.h"
|
||||||
|
|
||||||
|
static int libcdsb_builtin_foreach(set_t* x, void* data, vset_access_callback callback) {
|
||||||
|
stack_t z, *top, *bot, *cur;
|
||||||
|
rbnode_t* n;
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
|
memset(&z, 0, sizeof(z));
|
||||||
|
|
||||||
|
if (rbnode_is_empty(z.value = x->root))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (top = bot = &z;;) {
|
||||||
|
for (cur = bot;;) {
|
||||||
|
|
||||||
|
n = top->value;
|
||||||
|
|
||||||
|
if (!rbnode_is_empty(n->left)) cur = stack_insert(cur, n->left);
|
||||||
|
if (!rbnode_is_empty(n->right)) cur = stack_insert(cur, n->right);
|
||||||
|
|
||||||
|
if (!r) {
|
||||||
|
r = callback(vnode_peek(&n->value, x->type), x->type, data);
|
||||||
|
} else {
|
||||||
|
stack_flush(&z);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (top == bot) {
|
||||||
|
top = top->prev;
|
||||||
|
break;
|
||||||
|
} else top = top->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_null(top)) {
|
||||||
|
while (!is_null(bot->prev)) bot = bot->prev;
|
||||||
|
} else break;
|
||||||
|
}
|
||||||
|
|
||||||
|
stack_flush(&z);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*#####################################################################################################################*/
|
||||||
|
|
||||||
int libcdsb_vset_find(vtype_set* x, const void* v, vtype t, void* _, vset_access_callback callback, bool cut) {
|
int libcdsb_vset_find(vtype_set* x, const void* v, vtype t, void* _, vset_access_callback callback, bool cut) {
|
||||||
rbnode_t* c;
|
rbnode_t* c;
|
||||||
void *val;
|
void *val;
|
||||||
@ -32,46 +74,41 @@ int libcdsb_vset_find(vtype_set* x, const void* v, vtype t, void* _, vset_access
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int libcdsb_vset_foreach(set_t* x, void* data, vset_access_callback callback, bool flush) {
|
int libcdsb_vset_foreach(set_t* x, void* data, vset_access_callback callback, rbforeach_t type, bool flush) {
|
||||||
stack_t z;
|
bool reverse;
|
||||||
int r;
|
stack_t iter;
|
||||||
rbnode_t* c;
|
rbnode_t* n;
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
stack_init(&z);
|
reverse = type&RBFOREACH_REVERSE;
|
||||||
stack_push(&z, x->root);
|
|
||||||
|
|
||||||
r = 0;
|
switch (type&(RBFOREACH_INORDER|RBFOREACH_PREORDER|RBFOREACH_POSTORDER|RBFOREACH_BREADTH_FIRST)) {
|
||||||
|
case RBFOREACH_INORDER: iter = rbiter_inorder (&x->root, reverse); break;
|
||||||
|
case RBFOREACH_PREORDER: iter = rbiter_preorder (&x->root, reverse); break;
|
||||||
|
case RBFOREACH_POSTORDER: iter = rbiter_postorder(&x->root, reverse); break;
|
||||||
|
|
||||||
if (rbnode_is_empty(x->root))
|
default:
|
||||||
return 0;
|
case RBFOREACH_BREADTH_FIRST: if (reverse || flush) {
|
||||||
|
iter = rbiter_breath_first(&x->root, type&RBFOREACH_REVERSE);
|
||||||
while ((c = stack_pop(&z))) {
|
|
||||||
if ((r = callback(vnode_peek(&c->value, x->type), x->type, data)))
|
|
||||||
break;
|
break;
|
||||||
|
} else return libcdsb_builtin_foreach(x, data, callback);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while ((n = stack_pop(&iter))) {
|
||||||
|
if (!r) {
|
||||||
|
r = callback(vnode_peek(&n->value, x->type), x->type, data);
|
||||||
|
} else if (!flush) {
|
||||||
|
stack_flush(&iter);
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flush) {
|
if (flush) {
|
||||||
while (c) {
|
vnode_free(&n->value, x->type);
|
||||||
if (!rbnode_is_empty(c->right)) stack_push(&z, c->right);
|
free(n);
|
||||||
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));
|
if (flush) x->root = rbnode_empty;
|
||||||
} else stack_flush(&z);
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user