diff --git a/examples/set.c b/examples/set.c index 9b9b4d1..d05a978 100644 --- a/examples/set.c +++ b/examples/set.c @@ -3,7 +3,7 @@ #include #include -#include "../include/extra/set.h" +#include "../include/set.h" typedef vtype_set vset_t; @@ -22,6 +22,7 @@ int print_value(const void* value, vtype type, void* data) { int main(int argc, char** argv) { vset_t set; + int a, b; vset_init(&set, VTYPE_INT32); @@ -29,8 +30,11 @@ int main(int argc, char** argv) { vset_push(&set, i); } - vset_get(&set, 13, "Get value:", print_value); - vset_pop(&set, 18, "Pop value:", print_value); + a = 13; + b = 18; + + vset_get(&set, a, "Get value:", print_value); + vset_pop(&set, b, "Pop value:", print_value); vset_foreach(&set, "Foreach loop:", print_value); diff --git a/include/extra/set.h b/include/extra/set.h deleted file mode 100644 index 42be364..0000000 --- a/include/extra/set.h +++ /dev/null @@ -1,15 +0,0 @@ -/* This software is licensed by the MIT License, see LICENSE file */ -/* Copyright © 2022 Gregory Lirent */ - -#include "../set.h" - -#ifndef LIBCDSB_EXTRA_SET_H -#define LIBCDSB_EXTRA_SET_H - -#define vset_foreach(x, data, callback) libcdsb_vset_foreach(x, data, callback, 0) - -extern bool libcdsb_vset_insert (vtype_set* x, const void* value, vtype type) Nonnull__(1); -extern int libcdsb_vset_find (vtype_set* x, const void* value, vtype type, void* data, vset_access_callback, bool cut) Nonnull__(1); -extern int libcdsb_vset_foreach(vtype_set* x, void* data, vset_access_callback, bool flush) Nonnull__(1,3); - -#endif /* LIBCDSB_EXTRA_SET_H */ diff --git a/include/set.h b/include/set.h index d679c98..f71d88b 100644 --- a/include/set.h +++ b/include/set.h @@ -7,61 +7,28 @@ #ifndef LIBCDSB_SET_H #define LIBCDSB_SET_H -/*#####################################################################################################################*/ - typedef int (*vset_access_callback)(const void* value, vtype type, void* data); +/*#####################################################################################################################*/ + extern void vset_init(vtype_set* x, vtype type) Nonnull__(1); -#define vset_pop(x, value, data, callback) _LIBCDSB_Generic (libcdsb_vset, find, value)(x, value, data, callback, 1) -#define vset_get(x, value, data, callback) _LIBCDSB_Generic (libcdsb_vset, find, value)(x, value, data, callback, 0) -#define vset_push(x, value) _LIBCDSB_Generic (libcdsb_vset, push, value)(x, value) -#define vset_remove(x, value) vset_pop(x, value, 0, 0) +/*#####################################################################################################################*/ -#define in_vset(x, value) (vset_get(&x, value, 0, 0) == 0) +#define vset_pop(x, value, data, callback) libcdsb_vset_find (x, _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value), data, callback, 1) +#define vset_get(x, value, data, callback) libcdsb_vset_find (x, _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value), data, callback, 0) +#define vset_push(x, value) libcdsb_vset_insert (x, _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value)) +#define vset_attach(x, value) libcdsb_vset_attach (x, _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value)) +#define vset_foreach(x, data, callback) libcdsb_vset_foreach(x, data, callback, 0) +#define vset_remove(x, value) vset_pop (x, value, 0, 0) + +#define in_vset(x, value) (vset_get(x, value, 0, 0) == 0) /*#####################################################################################################################*/ -extern bool libcdsb_vset_push_pointer(vtype_set* x, const void* value) Nonnull__(1); -extern bool libcdsb_vset_push_cstring(vtype_set* x, const char* value) Nonnull__(1,2); -extern bool libcdsb_vset_push_string (vtype_set* x, const vtype_string* value) Nonnull__(1,2); -extern bool libcdsb_vset_push_array (vtype_set* x, const vtype_array* value) Nonnull__(1,2); -extern bool libcdsb_vset_push_list (vtype_set* x, const vtype_list* value) Nonnull__(1,2); -extern bool libcdsb_vset_push_map (vtype_set* x, const vtype_map* value) Nonnull__(1,2); -extern bool libcdsb_vset_push_vset (vtype_set* x, const vtype_set* value) Nonnull__(1,2); -extern bool libcdsb_vset_push_dict (vtype_set* x, const vtype_dict* value) Nonnull__(1,2); -extern bool libcdsb_vset_push_boolean(vtype_set* x, vtype_bool value) Nonnull__(1); -extern bool libcdsb_vset_push_uint8 (vtype_set* x, vtype_uint8 value) Nonnull__(1); -extern bool libcdsb_vset_push_uint16 (vtype_set* x, vtype_uint16 value) Nonnull__(1); -extern bool libcdsb_vset_push_uint32 (vtype_set* x, vtype_uint32 value) Nonnull__(1); -extern bool libcdsb_vset_push_uint64 (vtype_set* x, vtype_uint64 value) Nonnull__(1); -extern bool libcdsb_vset_push_int8 (vtype_set* x, vtype_int8 value) Nonnull__(1); -extern bool libcdsb_vset_push_int16 (vtype_set* x, vtype_int16 value) Nonnull__(1); -extern bool libcdsb_vset_push_int32 (vtype_set* x, vtype_int32 value) Nonnull__(1); -extern bool libcdsb_vset_push_int64 (vtype_set* x, vtype_int64 value) Nonnull__(1); -extern bool libcdsb_vset_push_float (vtype_set* x, vtype_float value) Nonnull__(1); -extern bool libcdsb_vset_push_double (vtype_set* x, vtype_double value) Nonnull__(1); -extern bool libcdsb_vset_push_ldouble(vtype_set* x, vtype_ldouble value) Nonnull__(1); - -extern int libcdsb_vset_find_pointer(vtype_set* x, const void* value, void* data, vset_access_callback, bool cut) Nonnull__(1); -extern int libcdsb_vset_find_cstring(vtype_set* x, const char* value, void* data, vset_access_callback, bool cut) Nonnull__(1,2); -extern int libcdsb_vset_find_string (vtype_set* x, const vtype_string* value, void* data, vset_access_callback, bool cut) Nonnull__(1,2); -extern int libcdsb_vset_find_array (vtype_set* x, const vtype_array* value, void* data, vset_access_callback, bool cut) Nonnull__(1,2); -extern int libcdsb_vset_find_list (vtype_set* x, const vtype_list* value, void* data, vset_access_callback, bool cut) Nonnull__(1,2); -extern int libcdsb_vset_find_map (vtype_set* x, const vtype_map* value, void* data, vset_access_callback, bool cut) Nonnull__(1,2); -extern int libcdsb_vset_find_vset (vtype_set* x, const vtype_set* value, void* data, vset_access_callback, bool cut) Nonnull__(1,2); -extern int libcdsb_vset_find_dict (vtype_set* x, const vtype_dict* value, void* data, vset_access_callback, bool cut) Nonnull__(1,2); -extern int libcdsb_vset_find_boolean(vtype_set* x, vtype_bool value, void* data, vset_access_callback, bool cut) Nonnull__(1); -extern int libcdsb_vset_find_uint8 (vtype_set* x, vtype_uint8 value, void* data, vset_access_callback, bool cut) Nonnull__(1); -extern int libcdsb_vset_find_uint16 (vtype_set* x, vtype_uint16 value, void* data, vset_access_callback, bool cut) Nonnull__(1); -extern int libcdsb_vset_find_uint32 (vtype_set* x, vtype_uint32 value, void* data, vset_access_callback, bool cut) Nonnull__(1); -extern int libcdsb_vset_find_uint64 (vtype_set* x, vtype_uint64 value, void* data, vset_access_callback, bool cut) Nonnull__(1); -extern int libcdsb_vset_find_int8 (vtype_set* x, vtype_int8 value, void* data, vset_access_callback, bool cut) Nonnull__(1); -extern int libcdsb_vset_find_int16 (vtype_set* x, vtype_int16 value, void* data, vset_access_callback, bool cut) Nonnull__(1); -extern int libcdsb_vset_find_int32 (vtype_set* x, vtype_int32 value, void* data, vset_access_callback, bool cut) Nonnull__(1); -extern int libcdsb_vset_find_int64 (vtype_set* x, vtype_int64 value, void* data, vset_access_callback, bool cut) Nonnull__(1); -extern int libcdsb_vset_find_float (vtype_set* x, vtype_float value, void* data, vset_access_callback, bool cut) Nonnull__(1); -extern int libcdsb_vset_find_double (vtype_set* x, vtype_double value, void* data, vset_access_callback, bool cut) Nonnull__(1); -extern int libcdsb_vset_find_ldouble(vtype_set* x, vtype_ldouble value, void* data, vset_access_callback, bool cut) Nonnull__(1); +extern bool libcdsb_vset_insert (vtype_set* x, const void* value, vtype type) Nonnull__(1); +extern bool libcdsb_vset_attach (vtype_set* x, const void* value, vtype type) Nonnull__(1); +extern int libcdsb_vset_find (vtype_set* x, const void* value, vtype type, void* data, vset_access_callback, bool cut) Nonnull__(1); +extern int libcdsb_vset_foreach(vtype_set* x, void* data, vset_access_callback, bool flush) Nonnull__(1,3); #endif /* LIBCDSB_SET_H */ diff --git a/src/__internal/rbtree.h b/src/__internal/rbtree.h index 01a5c10..93ecb97 100644 --- a/src/__internal/rbtree.h +++ b/src/__internal/rbtree.h @@ -17,7 +17,7 @@ typedef struct libcdsb_rbtree_node { extern rbnode_t LIBCDSB_RBTREE_NODE_EMPTY[1]; -extern void* libcdsb_rbtree_node_create(void* value, rbnode_t* parent, int colored, int size) Nonnull__(1,2); +extern void* libcdsb_rbtree_node_create(void* value, rbnode_t* parent, int colored, int size) Nonnull__( 2); extern void libcdsb_rbtree_node_fixup (rbnode_t** root, rbnode_t* node) Nonnull__(1,2); extern rbnode_t* libcdsb_rbtree_node_delete(rbnode_t** root, rbnode_t* node) Nonnull__(1,2); diff --git a/src/set/extra.c b/src/set/access.c similarity index 67% rename from src/set/extra.c rename to src/set/access.c index b18926b..2f022c1 100644 --- a/src/set/extra.c +++ b/src/set/access.c @@ -1,47 +1,9 @@ /* This software is licensed by the MIT License, see LICENSE file */ /* Copyright © 2022 Gregory Lirent */ -#include "../../include/extra/set.h" +#include "../../include/set.h" #include "../__internal/rbtree.h" -bool libcdsb_vset_insert(set_t* x, const void* v, vtype t) { - int cmp; - rbnode_t* n; - rbnode_t* p; - vnode_t vn; - - n = x->root; - vn = vnode_tcreate(x->type, v, t); - t = x->type; - v = vnode_peek(&vn, t); - - if (!rbnode_is_empty(n)) { - do { - p = n; - cmp = vtype_compare(v, t, vnode_peek(&n->value, t), t); - - if (cmp == 0) { - vnode_free(&vn, t); - return false; - } - - n = (cmp < 0) ? n->left : n->right; - } while (!rbnode_is_empty(n)); - - n = rbnode_create(vn, p, 1); - - if (cmp < 0) p->left = n; - else p->right = n; - - if (!rbnode_is_root(p)) - rbnode_fixup(&x->root, n); - - } else n = x->root = rbnode_create(vn, rbnode_empty, 0); - - return true; -} - - int libcdsb_vset_find(vtype_set* x, const void* v, vtype t, void* _, vset_access_callback callback, bool cut) { rbnode_t* c; void *val; diff --git a/src/set/base.c b/src/set/base.c deleted file mode 100644 index 7a85537..0000000 --- a/src/set/base.c +++ /dev/null @@ -1,161 +0,0 @@ -/* This software is licensed by the MIT License, see LICENSE file */ -/* Copyright © 2022 Gregory Lirent */ - -#include "../../include/set.h" -#include "../__internal/rbtree.h" - -/*#####################################################################################################################*/ - -static inline int rbnode_compare(const rbnode_t* s0, const rbnode_t* s1, vtype t) { - return vnode_compare(s0->value, t, s1->value, t); -} - -static inline hash_t rbnode_hash(const rbnode_t* s, vtype t) { - return vnode_hash(&s->value, t); -} - -/*#####################################################################################################################*/ - -hash_t vset_hash(const set_t* s) { - - stack_t z; - rbnode_t *c0, *c1; - hash_t hash, v; - - if (rbnode_is_empty(s->root)) - return 0; - - stack_init(&z); - stack_push(&z, s->root->left); - - hash = 1; - - if (!rbnode_is_empty(c0 = stack_pop(&z))) { - do { - ++hash; - if (!rbnode_is_empty(c0->right)) stack_push(&z, c0->right); - if (!rbnode_is_empty(c0->left)) stack_push(&z, c1 = c0->left); - } while (!is_null(c0 = stack_pop(&z))); - } - - v = rbnode_hash(c1, s->type); - stack_push(&z, s->root->right); - - if (!rbnode_is_empty(c0 = stack_pop(&z))) { - do { - ++hash; - if (!rbnode_is_empty(c0->right)) stack_push(&z, c1 = c0->right); - if (!rbnode_is_empty(c0->left)) stack_push(&z, c0->left); - } while (!is_null(c0 = stack_pop(&z))); - } - - v += rbnode_hash(c1, s->type); - - return (hash ^ v) + VTYPE_SET; -} - -/*#####################################################################################################################*/ - -void vset_init(set_t* x, vtype t) { - x->root = rbnode_empty; - x->type = t; -} - - -void vset_free(set_t* x) { - rbnode_t *t, *c; - - c = x->root; - - while (!rbnode_is_empty(x->root)) { - if (!rbnode_is_empty(c->left)) { - c = c->left; - } else if (!rbnode_is_empty(c->right)) { - c = c->right; - } else if (!rbnode_is_root(c)) { - vnode_free(&c->value, x->type); - - t = c; - c = c->parent; - - if (t == c->left) c->left = rbnode_empty; - else c->right = rbnode_empty; - - free(t); - } else { - vnode_free(&c->value, x->type); - x->root = rbnode_empty; - } - } - - x->type = 0; -} - -/*#####################################################################################################################*/ - -size_t vset_size(const set_t* x) { - stack_t z; - size_t n; - rbnode_t* c; - - stack_init(&z); - stack_push(&z, x->root); - - n = 0; - - if (!rbnode_is_empty(x->root)) { - while ((c = stack_pop(&z))) { - ++n; - if (!rbnode_is_empty(c->right)) stack_push(&z, c->right); - if (!rbnode_is_empty(c->left)) stack_push(&z, c->left); - } - } - - return n; -} - -/*#####################################################################################################################*/ - -int vset_compare(const set_t* s0, const set_t* s1) { - stack_t z; - rbnode_t *c0, *c1; - int cmp; - - if (s0 == s1 || s0->root == s1->root) - return 0; - if (s0->type != s1->type) - return s0->type - s1->type; - - stack_init(&z); - stack_push_many(&z, 2, (void*)s1, (void*)s0); - - cmp = 0; - - do { - c0 = stack_pop(&z); - c1 = stack_pop(&z); - - if (rbnode_is_empty(c0) || rbnode_is_empty(c1)) { - if (c0 != c1) { - stack_flush(&z); - return rbnode_is_empty(c0) ? -1 : 1; - } - } else if ((cmp = rbnode_compare(c0, c1, s0->type))) { - if (c0->left == c1->right) { // == rbnode_empty - cmp = rbnode_compare(c0->right, c1, s0->type); - if (!cmp) cmp = rbnode_compare(c0, c1->left, s0->type); - } else if (c0->right == c1->left) { // == rbnode_empty - cmp = rbnode_compare(c0, c1->right, s0->type); - if (!cmp) cmp = rbnode_compare(c0->left, c1, s0->type); - } - - if (cmp) { - stack_flush(&z); - return cmp; - } - } else stack_push_many(&z, 4, c1->right, c0->right, c1->left, c0->left); - - } while (!is_null(z.value)); - - return 0; -} diff --git a/src/set/comparison.c b/src/set/comparison.c new file mode 100644 index 0000000..4a3dabc --- /dev/null +++ b/src/set/comparison.c @@ -0,0 +1,55 @@ +/* This software is licensed by the MIT License, see LICENSE file */ +/* Copyright © 2022 Gregory Lirent */ + +#include "../../include/set.h" +#include "../__internal/rbtree.h" + +static inline int rbnode_compare(const rbnode_t* s0, const rbnode_t* s1, vtype t) { + return vnode_compare(s0->value, t, s1->value, t); +} + +/*#####################################################################################################################*/ + +int vset_compare(const set_t* s0, const set_t* s1) { + stack_t z; + rbnode_t *c0, *c1; + int cmp; + + if (s0 == s1 || s0->root == s1->root) + return 0; + if (s0->type != s1->type) + return s0->type - s1->type; + + stack_init(&z); + stack_push_many(&z, 2, (void*)s1, (void*)s0); + + cmp = 0; + + do { + c0 = stack_pop(&z); + c1 = stack_pop(&z); + + if (rbnode_is_empty(c0) || rbnode_is_empty(c1)) { + if (c0 != c1) { + stack_flush(&z); + return rbnode_is_empty(c0) ? -1 : 1; + } + } else if ((cmp = rbnode_compare(c0, c1, s0->type))) { + if (c0->left == c1->right) { // == rbnode_empty + cmp = rbnode_compare(c0->right, c1, s0->type); + if (!cmp) cmp = rbnode_compare(c0, c1->left, s0->type); + } else if (c0->right == c1->left) { // == rbnode_empty + cmp = rbnode_compare(c0, c1->right, s0->type); + if (!cmp) cmp = rbnode_compare(c0->left, c1, s0->type); + } + + if (cmp) { + stack_flush(&z); + return cmp; + } + } else stack_push_many(&z, 4, c1->right, c0->right, c1->left, c0->left); + + } while (!is_null(z.value)); + + return 0; +} diff --git a/src/set/compute.c b/src/set/compute.c new file mode 100644 index 0000000..3f3bb78 --- /dev/null +++ b/src/set/compute.c @@ -0,0 +1,71 @@ +/* This software is licensed by the MIT License, see LICENSE file */ +/* Copyright © 2022 Gregory Lirent */ + +#include "../../include/set.h" +#include "../__internal/rbtree.h" + +static inline hash_t rbnode_hash(const rbnode_t* s, vtype t) { + return vnode_hash(&s->value, t); +} + +/*#####################################################################################################################*/ + +size_t vset_size(const set_t* x) { + stack_t z; + size_t n; + rbnode_t* c; + + stack_init(&z); + stack_push(&z, x->root); + + n = 0; + + if (!rbnode_is_empty(x->root)) { + while ((c = stack_pop(&z))) { + ++n; + if (!rbnode_is_empty(c->right)) stack_push(&z, c->right); + if (!rbnode_is_empty(c->left)) stack_push(&z, c->left); + } + } + + return n; +} + + +hash_t vset_hash(const set_t* s) { + + stack_t z; + rbnode_t *c0, *c1; + hash_t hash, v; + + if (rbnode_is_empty(s->root)) + return 0; + + stack_init(&z); + stack_push(&z, s->root->left); + + hash = 1; + + if (!rbnode_is_empty(c0 = stack_pop(&z))) { + do { + ++hash; + if (!rbnode_is_empty(c0->right)) stack_push(&z, c0->right); + if (!rbnode_is_empty(c0->left)) stack_push(&z, c1 = c0->left); + } while (!is_null(c0 = stack_pop(&z))); + } + + v = rbnode_hash(c1, s->type); + stack_push(&z, s->root->right); + + if (!rbnode_is_empty(c0 = stack_pop(&z))) { + do { + ++hash; + if (!rbnode_is_empty(c0->right)) stack_push(&z, c1 = c0->right); + if (!rbnode_is_empty(c0->left)) stack_push(&z, c0->left); + } while (!is_null(c0 = stack_pop(&z))); + } + + v += rbnode_hash(c1, s->type); + + return (hash ^ v) + VTYPE_SET; +} diff --git a/src/set/generics.c b/src/set/generics.c deleted file mode 100644 index bd88199..0000000 --- a/src/set/generics.c +++ /dev/null @@ -1,47 +0,0 @@ -/* This software is licensed by the MIT License, see LICENSE file */ -/* Copyright © 2022 Gregory Lirent */ - -#include "../../include/extra/set.h" -#include "../__internal/include.h" - -int libcdsb_vset_find_pointer(set_t* x, const void* v, void* _, vset_access_callback cb, bool cut) { return libcdsb_vset_find(x, &v, vtypeof(&v), _, cb, cut); } -int libcdsb_vset_find_cstring(set_t* x, const char* v, void* _, vset_access_callback cb, bool cut) { return libcdsb_vset_find(x, &v, vtypeof(&v), _, cb, cut); } -int libcdsb_vset_find_string (set_t* x, const str_t* v, void* _, vset_access_callback cb, bool cut) { return libcdsb_vset_find(x, v, vtypeof( v), _, cb, cut); } -int libcdsb_vset_find_array (set_t* x, const arr_t* v, void* _, vset_access_callback cb, bool cut) { return libcdsb_vset_find(x, v, vtypeof( v), _, cb, cut); } -int libcdsb_vset_find_list (set_t* x, const list_t* v, void* _, vset_access_callback cb, bool cut) { return libcdsb_vset_find(x, v, vtypeof( v), _, cb, cut); } -int libcdsb_vset_find_map (set_t* x, const map_t* v, void* _, vset_access_callback cb, bool cut) { return libcdsb_vset_find(x, v, vtypeof( v), _, cb, cut); } -int libcdsb_vset_find_vset (set_t* x, const set_t* v, void* _, vset_access_callback cb, bool cut) { return libcdsb_vset_find(x, v, vtypeof( v), _, cb, cut); } -int libcdsb_vset_find_dict (set_t* x, const dict_t* v, void* _, vset_access_callback cb, bool cut) { return libcdsb_vset_find(x, v, vtypeof( v), _, cb, cut); } -int libcdsb_vset_find_boolean(set_t* x, bool v, void* _, vset_access_callback cb, bool cut) { return libcdsb_vset_find(x, &v, vtypeof(&v), _, cb, cut); } -int libcdsb_vset_find_int8 (set_t* x, s8_t v, void* _, vset_access_callback cb, bool cut) { return libcdsb_vset_find(x, &v, vtypeof(&v), _, cb, cut); } -int libcdsb_vset_find_int16 (set_t* x, s16_t v, void* _, vset_access_callback cb, bool cut) { return libcdsb_vset_find(x, &v, vtypeof(&v), _, cb, cut); } -int libcdsb_vset_find_int32 (set_t* x, s32_t v, void* _, vset_access_callback cb, bool cut) { return libcdsb_vset_find(x, &v, vtypeof(&v), _, cb, cut); } -int libcdsb_vset_find_int64 (set_t* x, s64_t v, void* _, vset_access_callback cb, bool cut) { return libcdsb_vset_find(x, &v, vtypeof(&v), _, cb, cut); } -int libcdsb_vset_find_uint8 (set_t* x, u8_t v, void* _, vset_access_callback cb, bool cut) { return libcdsb_vset_find(x, &v, vtypeof(&v), _, cb, cut); } -int libcdsb_vset_find_uint16 (set_t* x, u16_t v, void* _, vset_access_callback cb, bool cut) { return libcdsb_vset_find(x, &v, vtypeof(&v), _, cb, cut); } -int libcdsb_vset_find_uint32 (set_t* x, u32_t v, void* _, vset_access_callback cb, bool cut) { return libcdsb_vset_find(x, &v, vtypeof(&v), _, cb, cut); } -int libcdsb_vset_find_uint64 (set_t* x, u64_t v, void* _, vset_access_callback cb, bool cut) { return libcdsb_vset_find(x, &v, vtypeof(&v), _, cb, cut); } -int libcdsb_vset_find_float (set_t* x, fl_t v, void* _, vset_access_callback cb, bool cut) { return libcdsb_vset_find(x, &v, vtypeof(&v), _, cb, cut); } -int libcdsb_vset_find_double (set_t* x, dbl_t v, void* _, vset_access_callback cb, bool cut) { return libcdsb_vset_find(x, &v, vtypeof(&v), _, cb, cut); } -int libcdsb_vset_find_ldouble(set_t* x, ldbl_t v, void* _, vset_access_callback cb, bool cut) { return libcdsb_vset_find(x, &v, vtypeof(&v), _, cb, cut); } - -bool libcdsb_vset_push_pointer(set_t* x, const void* v) { return libcdsb_vset_insert(x, &v, vtypeof(&v)); } -bool libcdsb_vset_push_cstring(set_t* x, const char* v) { return libcdsb_vset_insert(x, &v, vtypeof(&v)); } -bool libcdsb_vset_push_string (set_t* x, const str_t* v) { return libcdsb_vset_insert(x, v, vtypeof( v)); } -bool libcdsb_vset_push_array (set_t* x, const arr_t* v) { return libcdsb_vset_insert(x, v, vtypeof( v)); } -bool libcdsb_vset_push_list (set_t* x, const list_t* v) { return libcdsb_vset_insert(x, v, vtypeof( v)); } -bool libcdsb_vset_push_map (set_t* x, const map_t* v) { return libcdsb_vset_insert(x, v, vtypeof( v)); } -bool libcdsb_vset_push_vset (set_t* x, const set_t* v) { return libcdsb_vset_insert(x, v, vtypeof( v)); } -bool libcdsb_vset_push_dict (set_t* x, const dict_t* v) { return libcdsb_vset_insert(x, v, vtypeof( v)); } -bool libcdsb_vset_push_boolean(set_t* x, bool v) { return libcdsb_vset_insert(x, &v, vtypeof(&v)); } -bool libcdsb_vset_push_int8 (set_t* x, s8_t v) { return libcdsb_vset_insert(x, &v, vtypeof(&v)); } -bool libcdsb_vset_push_int16 (set_t* x, s16_t v) { return libcdsb_vset_insert(x, &v, vtypeof(&v)); } -bool libcdsb_vset_push_int32 (set_t* x, s32_t v) { return libcdsb_vset_insert(x, &v, vtypeof(&v)); } -bool libcdsb_vset_push_int64 (set_t* x, s64_t v) { return libcdsb_vset_insert(x, &v, vtypeof(&v)); } -bool libcdsb_vset_push_uint8 (set_t* x, u8_t v) { return libcdsb_vset_insert(x, &v, vtypeof(&v)); } -bool libcdsb_vset_push_uint16 (set_t* x, u16_t v) { return libcdsb_vset_insert(x, &v, vtypeof(&v)); } -bool libcdsb_vset_push_uint32 (set_t* x, u32_t v) { return libcdsb_vset_insert(x, &v, vtypeof(&v)); } -bool libcdsb_vset_push_uint64 (set_t* x, u64_t v) { return libcdsb_vset_insert(x, &v, vtypeof(&v)); } -bool libcdsb_vset_push_float (set_t* x, fl_t v) { return libcdsb_vset_insert(x, &v, vtypeof(&v)); } -bool libcdsb_vset_push_double (set_t* x, dbl_t v) { return libcdsb_vset_insert(x, &v, vtypeof(&v)); } -bool libcdsb_vset_push_ldouble(set_t* x, ldbl_t v) { return libcdsb_vset_insert(x, &v, vtypeof(&v)); } diff --git a/src/set/memory.c b/src/set/memory.c new file mode 100644 index 0000000..e0e3c2b --- /dev/null +++ b/src/set/memory.c @@ -0,0 +1,39 @@ +/* This software is licensed by the MIT License, see LICENSE file */ +/* Copyright © 2022 Gregory Lirent */ + +#include "../../include/set.h" +#include "../__internal/rbtree.h" + +void vset_init(set_t* x, vtype t) { + x->root = rbnode_empty; + x->type = t; +} + +void vset_free(set_t* x) { + rbnode_t *t, *c; + + c = x->root; + + while (!rbnode_is_empty(x->root)) { + if (!rbnode_is_empty(c->left)) { + c = c->left; + } else if (!rbnode_is_empty(c->right)) { + c = c->right; + } else if (!rbnode_is_root(c)) { + vnode_free(&c->value, x->type); + + t = c; + c = c->parent; + + if (t == c->left) c->left = rbnode_empty; + else c->right = rbnode_empty; + + free(t); + } else { + vnode_free(&c->value, x->type); + x->root = rbnode_empty; + } + } + + x->type = 0; +} diff --git a/src/set/modify.c b/src/set/modify.c new file mode 100644 index 0000000..dd5e4c2 --- /dev/null +++ b/src/set/modify.c @@ -0,0 +1,88 @@ +/* This software is licensed by the MIT License, see LICENSE file */ +/* Copyright © 2022 Gregory Lirent */ + +#include "../../include/set.h" +#include "../__internal/rbtree.h" +#include "../__internal/assert.h" + +bool libcdsb_vset_insert(set_t* x, const void* v, vtype t) { + int cmp; + rbnode_t* n; + rbnode_t* p; + vnode_t vn; + + n = x->root; + vn = vnode_tcreate(x->type, v, t); + t = x->type; + v = vnode_peek(&vn, t); + + if (!rbnode_is_empty(n)) { + do { + p = n; + cmp = vtype_compare(v, t, vnode_peek(&n->value, t), t); + + if (cmp == 0) { + vnode_free(&vn, t); + return false; + } + + n = (cmp < 0) ? n->left : n->right; + } while (!rbnode_is_empty(n)); + + n = rbnode_create(vn, p, 1); + + if (cmp < 0) p->left = n; + else p->right = n; + + if (!rbnode_is_root(p)) + rbnode_fixup(&x->root, n); + + } else n = x->root = rbnode_create(vn, rbnode_empty, 0); + + return true; +} + + +bool libcdsb_vset_attach(set_t* x, const void* v, vtype t) { + int cmp; + rbnode_t* n; + rbnode_t* p; + + n = x->root; + t = x->type; + + if (!rbnode_is_empty(n)) { + do { + p = n; + cmp = vtype_compare(v, t, vnode_peek(&n->value, t), t); + + if (cmp == 0) return false; + + n = (cmp < 0) ? n->left : n->right; + } while (!rbnode_is_empty(n)); + + n = rbnode_create(nullptr, p, 1); + + if (cmp < 0) p->left = n; + else p->right = n; + + if (!rbnode_is_root(p)) + rbnode_fixup(&x->root, n); + + } else n = x->root = rbnode_create(nullptr, rbnode_empty, 0); + + if (t < VTYPE_STRING) { + n->value = vnode_tcreate(x->type, v, t); + } else { + type_assert(x->type, t); + + if (sizeof(str_t) == sizeof(void*) && t == VTYPE_STRING) { + n->value = *(char**)v; + } else { + n->value = malloc(vtype_size(t)); + memcpy(n->value, v, vtype_size(t)); + } + } + + return true; +} diff --git a/tests/src/set/plug.h b/tests/src/set/plug.h index 756e649..5e430b8 100644 --- a/tests/src/set/plug.h +++ b/tests/src/set/plug.h @@ -1,7 +1,7 @@ /* This software is licensed by the MIT License, see LICENSE file */ /* Copyright © 2022 Gregory Lirent */ -#include "../../../include/extra/set.h" +#include "../../../include/set.h" #include "../../../src/__internal/rbtree.h" #include "../../include/random.h"