/* This software is licensed by the MIT License, see LICENSE file */ /* Copyright © 2022 Gregory Lirent */ #include "../../include/set.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), 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, var_t value, void* _, vset_access_callback callback, bool cut) { rbnode_t* c; int cmp; var_t v; c = x->root; while (!rbnode_is_empty(c)) { v = vnode_peek(&c->value, x->type); cmp = variable_compare(value, v); if (cmp == 0) { cmp = (callback) ? callback(v, _) : 0; if (cut) { c = rbnode_delete(&x->root, c); vnode_free(&c->value, x->type); free(c); } return cmp; } else c = (cmp < 0) ? c->left : c->right; } return -1; } int libcdsb_vset_foreach(set_t* x, void* data, vset_access_callback callback, rbforeach_t type, bool flush) { bool reverse; stack_t iter; rbnode_t* n; int r = 0; reverse = type&RBFOREACH_REVERSE; 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; default: case RBFOREACH_BREADTH_FIRST: if (reverse || flush) { iter = rbiter_breadth_first(&x->root, type&RBFOREACH_REVERSE); break; } else return libcdsb_builtin_foreach(x, data, callback); } while ((n = stack_pop(&iter))) { if (!r) { r = callback(vnode_peek(&n->value, x->type), data); } else if (!flush) { stack_flush(&iter); return r; } if (flush) { vnode_free(&n->value, x->type); free(n); } } if (flush) x->root = rbnode_empty; return r; }