Add set base & extra
This commit is contained in:
parent
da420ef59d
commit
0cf27783ea
16
include/extra/set.h
Normal file
16
include/extra/set.h
Normal file
@ -0,0 +1,16 @@
|
||||
/* 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 libcdsb_vset_foreach
|
||||
|
||||
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__;
|
||||
|
||||
#endif /* LIBCDSB_EXTRA_SET_H */
|
57
include/set.h
Normal file
57
include/set.h
Normal file
@ -0,0 +1,57 @@
|
||||
/* This software is licensed by the MIT License, see LICENSE file */
|
||||
/* Copyright © 2022 Gregory Lirent */
|
||||
|
||||
#include "__generics.h"
|
||||
#include "vtype.h"
|
||||
|
||||
#ifndef LIBCDSB_SET_H
|
||||
#define LIBCDSB_SET_H
|
||||
|
||||
extern void vset_init(vtype_set* x, vtype type);
|
||||
|
||||
#define vset_remove(x, value) _LIBCDSB_Generic (libcdsb_vset, touch, key)(x, value, 1)
|
||||
#define vset_push(x, value) _LIBCDSB_Generic (libcdsb_vset, push, key)(x, value)
|
||||
|
||||
#define in_vset(x, value) _LIBCDSB_Generic (libcdsb_vset, touch, key)(x, value, 0)
|
||||
|
||||
extern _Bool libcdsb_vset_push_pointer(vtype_set* x, const void* value);
|
||||
extern _Bool libcdsb_vset_push_cstring(vtype_set* x, const char* value);
|
||||
extern _Bool libcdsb_vset_push_string (vtype_set* x, const vtype_string* value);
|
||||
extern _Bool libcdsb_vset_push_array (vtype_set* x, const vtype_array* value);
|
||||
extern _Bool libcdsb_vset_push_list (vtype_set* x, const vtype_list* value);
|
||||
extern _Bool libcdsb_vset_push_map (vtype_set* x, const vtype_map* value);
|
||||
extern _Bool libcdsb_vset_push_vset (vtype_set* x, const vtype_set* value);
|
||||
extern _Bool libcdsb_vset_push_boolean(vtype_set* x, vtype_bool value);
|
||||
extern _Bool libcdsb_vset_push_uint8 (vtype_set* x, vtype_uint8 value);
|
||||
extern _Bool libcdsb_vset_push_uint16 (vtype_set* x, vtype_uint16 value);
|
||||
extern _Bool libcdsb_vset_push_uint32 (vtype_set* x, vtype_uint32 value);
|
||||
extern _Bool libcdsb_vset_push_uint64 (vtype_set* x, vtype_uint64 value);
|
||||
extern _Bool libcdsb_vset_push_int8 (vtype_set* x, vtype_int8 value);
|
||||
extern _Bool libcdsb_vset_push_int16 (vtype_set* x, vtype_int16 value);
|
||||
extern _Bool libcdsb_vset_push_int32 (vtype_set* x, vtype_int32 value);
|
||||
extern _Bool libcdsb_vset_push_int64 (vtype_set* x, vtype_int64 value);
|
||||
extern _Bool libcdsb_vset_push_float (vtype_set* x, vtype_float value);
|
||||
extern _Bool libcdsb_vset_push_double (vtype_set* x, vtype_double value);
|
||||
extern _Bool libcdsb_vset_push_ldouble(vtype_set* x, vtype_ldouble value);
|
||||
|
||||
extern _Bool libcdsb_vset_touch_pointer(vtype_set* x, const void* value, _Bool cut);
|
||||
extern _Bool libcdsb_vset_touch_cstring(vtype_set* x, const char* value, _Bool cut);
|
||||
extern _Bool libcdsb_vset_touch_string (vtype_set* x, const vtype_string* value, _Bool cut);
|
||||
extern _Bool libcdsb_vset_touch_array (vtype_set* x, const vtype_array* value, _Bool cut);
|
||||
extern _Bool libcdsb_vset_touch_list (vtype_set* x, const vtype_list* value, _Bool cut);
|
||||
extern _Bool libcdsb_vset_touch_map (vtype_set* x, const vtype_map* value, _Bool cut);
|
||||
extern _Bool libcdsb_vset_touch_vset (vtype_set* x, const vtype_set* value, _Bool cut);
|
||||
extern _Bool libcdsb_vset_touch_boolean(vtype_set* x, vtype_bool value, _Bool cut);
|
||||
extern _Bool libcdsb_vset_touch_uint8 (vtype_set* x, vtype_uint8 value, _Bool cut);
|
||||
extern _Bool libcdsb_vset_touch_uint16 (vtype_set* x, vtype_uint16 value, _Bool cut);
|
||||
extern _Bool libcdsb_vset_touch_uint32 (vtype_set* x, vtype_uint32 value, _Bool cut);
|
||||
extern _Bool libcdsb_vset_touch_uint64 (vtype_set* x, vtype_uint64 value, _Bool cut);
|
||||
extern _Bool libcdsb_vset_touch_int8 (vtype_set* x, vtype_int8 value, _Bool cut);
|
||||
extern _Bool libcdsb_vset_touch_int16 (vtype_set* x, vtype_int16 value, _Bool cut);
|
||||
extern _Bool libcdsb_vset_touch_int32 (vtype_set* x, vtype_int32 value, _Bool cut);
|
||||
extern _Bool libcdsb_vset_touch_int64 (vtype_set* x, vtype_int64 value, _Bool cut);
|
||||
extern _Bool libcdsb_vset_touch_float (vtype_set* x, vtype_float value, _Bool cut);
|
||||
extern _Bool libcdsb_vset_touch_double (vtype_set* x, vtype_double value, _Bool cut);
|
||||
extern _Bool libcdsb_vset_touch_ldouble(vtype_set* x, vtype_ldouble value, _Bool cut);
|
||||
|
||||
#endif /* LIBCDSB_SET_H */
|
@ -43,6 +43,10 @@ extern void libcdsb_rbtree_iter_reset(rbiter_t* iter);
|
||||
#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)
|
||||
|
||||
|
98
src/set/base.c
Normal file
98
src/set/base.c
Normal file
@ -0,0 +1,98 @@
|
||||
/* 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 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*#####################################################################################################################*/
|
||||
|
||||
|
||||
void vset_init(vtype_set* x, vtype t) {
|
||||
x->root = rbnode_empty;
|
||||
x->type = t;
|
||||
}
|
||||
|
||||
void vset_free(vtype_set* x) {
|
||||
rbnode_t* t;
|
||||
rbnode_t* c;
|
||||
|
||||
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 vtype_set* x) {
|
||||
size_t n;
|
||||
rbiter_t i;
|
||||
|
||||
n = 0;
|
||||
|
||||
if (rbiter_init(&i, &x->root, 0)) {
|
||||
while (!rbnode_is_empty(rbiter_next(&i)))
|
||||
++n;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int vset_compare(const vtype_set* s0, const vtype_set* s1) {
|
||||
rbiter_t iter[2];
|
||||
|
||||
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);
|
||||
|
||||
return tree_compare(iter+0, iter+1, s0->type);
|
||||
} else return s0->type < s1->type ? -1 : 1;
|
||||
}
|
59
src/set/copy.c
Normal file
59
src/set/copy.c
Normal file
@ -0,0 +1,59 @@
|
||||
/* This software is licensed by the MIT License, see LICENSE file */
|
||||
/* Copyright © 2022 Gregory Lirent */
|
||||
|
||||
#include "../../include/set.h"
|
||||
#include "../__internal/rbtree.h"
|
||||
|
||||
/*#####################################################################################################################*/
|
||||
|
||||
static void copy_child(rbnode_t* x, vtype t, const rbnode_t* l, const rbnode_t* r) {
|
||||
|
||||
if (!rbnode_is_empty(l)) {
|
||||
x->left = rbnode_create(vnode_duplicate(&l->value, t), x, l->colored);
|
||||
copy_child(x->left, t, l->left, l->right);
|
||||
} else x->left = rbnode_empty;
|
||||
|
||||
if (!rbnode_is_empty(r)) {
|
||||
x->left = rbnode_create(vnode_duplicate(&r->value, t), x, r->colored);
|
||||
copy_child(x->right, t, r->right, r->right);
|
||||
} else x->right = rbnode_empty;
|
||||
}
|
||||
|
||||
/*#####################################################################################################################*/
|
||||
|
||||
vtype_set vset_copy(const vtype_set* s) {
|
||||
|
||||
set_t x = { .type = s->type };
|
||||
|
||||
if (!rbnode_is_empty(s->root)) {
|
||||
x.root = rbnode_create(vnode_duplicate(&s->root->value, s->type), rbnode_empty, 0);
|
||||
|
||||
copy_child(x.root, s->type, s->root->left, s->root->right);
|
||||
} else x.root = rbnode_empty;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
vtype_set* vset_duplicate(const vtype_set* s) {
|
||||
set_t* x = malloc(sizeof(*x));
|
||||
|
||||
x->type = s->type;
|
||||
|
||||
if (!rbnode_is_empty(s->root)) {
|
||||
x->root = rbnode_create(vnode_duplicate(&s->root->value, s->type), rbnode_empty, 0);
|
||||
|
||||
copy_child(x->root, s->type, s->root->left, s->root->right);
|
||||
} else x->root = rbnode_empty;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
void vset_copy_init(vtype_set* x, const vtype_set* s) {
|
||||
x->type = s->type;
|
||||
|
||||
if (!rbnode_is_empty(s->root)) {
|
||||
x->root = rbnode_create(vnode_duplicate(&s->root->value, s->type), rbnode_empty, 0);
|
||||
|
||||
copy_child(x->root, s->type, s->root->left, s->root->right);
|
||||
} else x->root = rbnode_empty;
|
||||
}
|
86
src/set/extra.c
Normal file
86
src/set/extra.c
Normal file
@ -0,0 +1,86 @@
|
||||
/* This software is licensed by the MIT License, see LICENSE file */
|
||||
/* Copyright © 2022 Gregory Lirent */
|
||||
|
||||
#include "../../include/extra/set.h"
|
||||
#include "../__internal/rbtree.h"
|
||||
|
||||
/*#####################################################################################################################*/
|
||||
|
||||
|
||||
_Bool libcdsb_vset_find(val_t* x, set_t* s, const void* v, vtype t, _Bool cut) {
|
||||
rbnode_t* c;
|
||||
int cmp;
|
||||
|
||||
c = s->root;
|
||||
|
||||
while (!rbnode_is_empty(c)) {
|
||||
|
||||
cmp = vtype_compare(vnode_peek(&c->value, s->type), s->type, v, t);
|
||||
|
||||
if (cmp == 0) {
|
||||
if (cut) {
|
||||
c = rbnode_delete(&s->root, c);
|
||||
if (!is_null(x)) {
|
||||
value_set(x, c->value, s->type, VF_WRITEABLE|VF_REMOVABLE);
|
||||
} else vnode_free(&c->value, s->type);
|
||||
free(c);
|
||||
} else if (!is_null(x)) value_set(x, c->value, s->type, VF_UNDEFINED);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
c = (cmp < 0) ? c->right : c->left;
|
||||
}
|
||||
return rbnode_empty;
|
||||
}
|
||||
|
||||
|
||||
_Bool libcdsb_vset_insert(set_t* x, const void* v, vtype t) {
|
||||
int cmp;
|
||||
rbnode_t* n;
|
||||
rbnode_t* p;
|
||||
|
||||
n = x->root;
|
||||
|
||||
if (!rbnode_is_empty(n)) {
|
||||
do {
|
||||
p = n;
|
||||
cmp = vtype_compare(vnode_peek(&n->value, x->type), x->type, v, t);
|
||||
|
||||
if (cmp == 0) return false;
|
||||
|
||||
n = (cmp > 0) ? n->left : n->right;
|
||||
} while (!rbnode_is_empty(n));
|
||||
|
||||
n = rbnode_create(0, p, 1);
|
||||
|
||||
if (cmp > 0) p->left = n;
|
||||
else p->right = n;
|
||||
|
||||
if (!rbnode_is_root(n->parent))
|
||||
rbnode_fixup(&x->root, n);
|
||||
|
||||
} else n = x->root = rbnode_create(0, p, 1);
|
||||
|
||||
n->value = vnode_tcreate(x->type, v, t);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*#####################################################################################################################*/
|
||||
|
||||
|
||||
int libcdsb_vset_foreach(const vtype_set* x, int (*callback)(const void* value, vtype type)) {
|
||||
rbiter_t i;
|
||||
int r;
|
||||
|
||||
if (rbiter_init(&i, &x->root, 0)) {
|
||||
while (!rbnode_is_empty(rbiter_next(&i))) {
|
||||
if ((r = callback(vnode_peek(&i.cursor->value, x->type), x->type)))
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
45
src/set/generics.c
Normal file
45
src/set/generics.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* This software is licensed by the MIT License, see LICENSE file */
|
||||
/* Copyright © 2022 Gregory Lirent */
|
||||
|
||||
#include "../../include/extra/set.h"
|
||||
#include "../__internal/include.h"
|
||||
|
||||
_Bool libcdsb_vset_touch_pointer(set_t* x, const void* k, _Bool f) { return libcdsb_vset_find(0, x, &k, vtypeof(&k), f); }
|
||||
_Bool libcdsb_vset_touch_cstring(set_t* x, const char* k, _Bool f) { return libcdsb_vset_find(0, x, &k, vtypeof(&k), f); }
|
||||
_Bool libcdsb_vset_touch_string (set_t* x, const str_t* k, _Bool f) { return libcdsb_vset_find(0, x, k, vtypeof( k), f); }
|
||||
_Bool libcdsb_vset_touch_array (set_t* x, const arr_t* k, _Bool f) { return libcdsb_vset_find(0, x, k, vtypeof( k), f); }
|
||||
_Bool libcdsb_vset_touch_list (set_t* x, const list_t* k, _Bool f) { return libcdsb_vset_find(0, x, k, vtypeof( k), f); }
|
||||
_Bool libcdsb_vset_touch_map (set_t* x, const map_t* k, _Bool f) { return libcdsb_vset_find(0, x, k, vtypeof( k), f); }
|
||||
_Bool libcdsb_vset_touch_vset (set_t* x, const set_t* k, _Bool f) { return libcdsb_vset_find(0, x, k, vtypeof( k), f); }
|
||||
_Bool libcdsb_vset_touch_boolean(set_t* x, _Bool k, _Bool f) { return libcdsb_vset_find(0, x, &k, vtypeof(&k), f); }
|
||||
_Bool libcdsb_vset_touch_int8 (set_t* x, s8_t k, _Bool f) { return libcdsb_vset_find(0, x, &k, vtypeof(&k), f); }
|
||||
_Bool libcdsb_vset_touch_int16 (set_t* x, s16_t k, _Bool f) { return libcdsb_vset_find(0, x, &k, vtypeof(&k), f); }
|
||||
_Bool libcdsb_vset_touch_int32 (set_t* x, s32_t k, _Bool f) { return libcdsb_vset_find(0, x, &k, vtypeof(&k), f); }
|
||||
_Bool libcdsb_vset_touch_int64 (set_t* x, s64_t k, _Bool f) { return libcdsb_vset_find(0, x, &k, vtypeof(&k), f); }
|
||||
_Bool libcdsb_vset_touch_uint8 (set_t* x, u8_t k, _Bool f) { return libcdsb_vset_find(0, x, &k, vtypeof(&k), f); }
|
||||
_Bool libcdsb_vset_touch_uint16 (set_t* x, u16_t k, _Bool f) { return libcdsb_vset_find(0, x, &k, vtypeof(&k), f); }
|
||||
_Bool libcdsb_vset_touch_uint32 (set_t* x, u32_t k, _Bool f) { return libcdsb_vset_find(0, x, &k, vtypeof(&k), f); }
|
||||
_Bool libcdsb_vset_touch_uint64 (set_t* x, u64_t k, _Bool f) { return libcdsb_vset_find(0, x, &k, vtypeof(&k), f); }
|
||||
_Bool libcdsb_vset_touch_float (set_t* x, fl_t k, _Bool f) { return libcdsb_vset_find(0, x, &k, vtypeof(&k), f); }
|
||||
_Bool libcdsb_vset_touch_double (set_t* x, dbl_t k, _Bool f) { return libcdsb_vset_find(0, x, &k, vtypeof(&k), f); }
|
||||
_Bool libcdsb_vset_touch_ldouble(set_t* x, ldbl_t k, _Bool f) { return libcdsb_vset_find(0, x, &k, vtypeof(&k), f); }
|
||||
|
||||
_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_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)); }
|
Loading…
Reference in New Issue
Block a user