diff --git a/include/extra/array.h b/include/extra/array.h index 6ec3825..af89ba0 100644 --- a/include/extra/array.h +++ b/include/extra/array.h @@ -10,11 +10,13 @@ #define array_pop(x, s, index) libcdsb_array_get(x, s, index, 1) #define array_remove(s, index) libcdsb_array_get(0, s, index, 1) +#define array_foreach libcdsb_array_foreach + extern ssize_t libcdsb_array_get(vtype_value* x, vtype_array* s, ssize_t index, _Bool cut) LIBCDSB_nt__ LIBCDSB_nn2__; 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 array_foreach(vtype_array* x, int (*callback)(void* value, ssize_t index, vtype type)) LIBCDSB_nt__ LIBCDSB_nn12__; +extern int libcdsb_array_foreach(vtype_array* x, int (*callback)(void* value, ssize_t index, vtype type)) LIBCDSB_nt__ LIBCDSB_nn12__; #endif /* LIBCDSB_EXTRA_ARRAY_H */ diff --git a/include/extra/list.h b/include/extra/list.h index 68f1168..6ef3c89 100644 --- a/include/extra/list.h +++ b/include/extra/list.h @@ -1,7 +1,6 @@ /* This software is licensed by the MIT License, see LICENSE file */ /* Copyright © 2022 Gregory Lirent */ -#include #include "../list.h" #ifndef LIBCDSB_EXTRA_LIST_H @@ -11,6 +10,8 @@ #define list_pop_by_index(x, s, index) libcdsb_list_get(x, s, index, 1) #define list_remove_by_index(s, index) libcdsb_list_get(0, s, index, 1) +#define list_foreach libcdsb_list_foreach + extern ssize_t libcdsb_list_find (vtype_value* x, vtype_list* s, const void* value, vtype type, _Bool reverse, _Bool cut) LIBCDSB_nt__ LIBCDSB_nn2__; extern _Bool libcdsb_list_update(vtype_list* x, ssize_t index, const void* value, vtype type, int ins_direction) LIBCDSB_nt__ LIBCDSB_nn1__; @@ -18,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 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, int (*callback)(void* value, ssize_t index, vtype type)) LIBCDSB_nt__ LIBCDSB_nn12__; #endif /* LIBCDSB_EXTRA_LIST_H */ diff --git a/include/extra/set.h b/include/extra/set.h new file mode 100644 index 0000000..80fabf9 --- /dev/null +++ b/include/extra/set.h @@ -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 */ diff --git a/include/extra/string.h b/include/extra/string.h index c224b69..b96933c 100644 --- a/include/extra/string.h +++ b/include/extra/string.h @@ -27,9 +27,10 @@ extern size_t string_align_center(vtype_string* x, size_t padsize, int padchr) L extern size_t string_align_right (vtype_string* x, size_t padsize, int padchr) LIBCDSB_nt__ LIBCDSB_nn1__; extern size_t string_align_left (vtype_string* x, size_t padsize, int padchr) LIBCDSB_nt__ LIBCDSB_nn1__; - extern int string_compare_case_insensitive(const vtype_string* s0, const vtype_string* s1) LIBCDSB_cmpattr__; +extern void libcdsb_string_replace(vtype_string* x, char* dest, size_t dest_nmemb, const char* src, size_t nmemb); + /*#####################################################################################################################*/ inline vtype_array libcdsb_string_split_string (const vtype_string* x, const vtype_string* sep, size_t maxn) __attribute__((always_inline)); diff --git a/include/set.h b/include/set.h new file mode 100644 index 0000000..cb0202e --- /dev/null +++ b/include/set.h @@ -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 */ diff --git a/src/__internal/rbtree.h b/src/__internal/rbtree.h new file mode 100644 index 0000000..33d4fb5 --- /dev/null +++ b/src/__internal/rbtree.h @@ -0,0 +1,53 @@ +/* This software is licensed by the Apache License 2.0, see LICENSE file */ +/* Copyright © 2022 Gregory Lirent */ + +#include "vnode.h" + +#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; + struct libcdsb_rbtree_node* parent; + + vnode_t value; + 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 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) + +#endif /* LIBCDSB_SRC_INTERNAL_RBTREE_H */ diff --git a/src/__internal/vnode.h b/src/__internal/vnode.h index 6a03b14..4303a37 100644 --- a/src/__internal/vnode.h +++ b/src/__internal/vnode.h @@ -6,12 +6,6 @@ #ifndef LIBCDSB_SRC_INTERNAL_VNODE_H #define LIBCDSB_SRC_INTERNAL_VNODE_H -#define mark_ptr(x, m) ((void*)((uintptr_t)(x)|(uintptr_t)(m))) -#define unmark_ptr(x) ((void*)((uintptr_t)(x)&~(uintptr_t)(_Alignof(max_align_t)-1))) -#define get_mark(x) ((int)((uintptr_t)(x)&(uintptr_t)(_Alignof(max_align_t)-1))) -#define unmark_ptr16(x) ((void*)((uintptr_t)(x)&~(uintptr_t)(15))) -#define get_mark16(x) ((int)((uintptr_t)(x)&(uintptr_t)(15))) - #define is_permissible(T) (sizeof(void*) >= sizeof(T) && _Alignof(void*) >= _Alignof(T)) typedef union { diff --git a/src/array/extra.c b/src/array/extra.c index 25b1d2c..99070e1 100644 --- a/src/array/extra.c +++ b/src/array/extra.c @@ -76,7 +76,7 @@ ssize_t libcdsb_array_get(val_t* x, arr_t* s, ssize_t i, _Bool cut) { /*#####################################################################################################################*/ -int array_foreach(vtype_array* x, int (*callback)(void* value, ssize_t index, vtype type)) { +int libcdsb_array_foreach(vtype_array* x, int (*callback)(void* value, ssize_t index, vtype type)) { void* p; void* e; diff --git a/src/list/extra.c b/src/list/extra.c index 6429bcd..570b679 100644 --- a/src/list/extra.c +++ b/src/list/extra.c @@ -163,7 +163,7 @@ _Bool libcdsb_list_update(list_t* x, ssize_t i, const void* v, vtype t, int ins) /*#####################################################################################################################*/ -int list_foreach(const vtype_list* x, int (*callback)(void* value, ssize_t index, vtype type)) { +int libcdsb_list_foreach(const vtype_list* x, int (*callback)(void* value, ssize_t index, vtype type)) { lnode_t* c; size_t n; diff --git a/src/rbtree.c b/src/rbtree.c new file mode 100644 index 0000000..22dee93 --- /dev/null +++ b/src/rbtree.c @@ -0,0 +1,383 @@ +/* This software is licensed by the MIT License, see LICENSE file */ +/* Copyright © 2022 Gregory Lirent */ + +#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 +} rbdir_t; + +#define rbdir_dir(cur, d) (&((cur)->left))[(d)>>1] +#define rbdir_inv(cur, d) (&((cur)->left))[(d)&1] + +/*#####################################################################################################################*/ + +const rbnode_t LIBCDSB_RBTREE_NODE_EMPTY[1] = {{ + .colored = 0, + .value = 0, + .parent = rbnode_empty, + .left = rbnode_empty, + .right = rbnode_empty +}}; + +/*#####################################################################################################################*/ + +static inline void rotate(rbnode_t **x, rbnode_t *c, rbdir_t d) { + rbnode_t* n = rbdir_inv(c, d); + + rbdir_inv(c, d) = rbdir_dir(n, d); + n->parent = c->parent; + + if (!rbnode_is_empty(rbdir_dir(n, d))) { + rbdir_dir(n, d)->parent = c; + } + + if (!rbnode_is_root(c)) { + rbnode_t* p = c->parent; + + if (rbdir_dir(p, d) == c) { + rbdir_dir(p, d) = n; + } else rbdir_inv(c, d) = n; + } else *x = n; + + rbdir_inv(n, d) = c; + c->parent = n; +} + +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; + } 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; + } +} + + +/*#####################################################################################################################*/ + + +static void delete_fixup(rbnode_t** x, rbnode_t* n) { + rbdir_t d; + rbnode_t *s, *p; + + while (!rbnode_is_root(n) && !n->colored) { + p = n->parent; + d = (p->left == n) ? RBD_LEFT : RBD_RIGHT; + s = rbdir_inv(p, d); + + if (s->colored) { + s->colored = 0; + p->colored = 1; + rotate(x, p, d); + p = n->parent; + s = rbdir_inv(p, d); + } + + if (!rbdir_dir(s, d)->colored && !rbdir_inv(s, d)->colored) { + s->colored = 1; + n = p; + } else { + if (!rbdir_inv(s, d)->colored) { + rbdir_dir(s, d)->colored = 0; + s->colored = 1; + rotate(x, s, (d == RBD_LEFT) ? RBD_RIGHT : RBD_LEFT); + p = n->parent; + s = rbdir_inv(p, d); + } + + s->colored = p->colored; + p->colored = 0; + rbdir_inv(s, d)->colored = 0; + + rotate(x, p, d); + + n = *x; + } + } + + n->colored = 0; +} + +/*#####################################################################################################################*/ + + +rbnode_t* libcdsb_rbtree_node_delete(rbnode_t** x, rbnode_t* c) { + rbnode_t *n, *t; + int s; + void* v; + + s = c->colored; + + if (rbnode_is_empty(c->left)) { + n = c->right; + replace(x, c, c->right); + } else if (rbnode_is_empty(c->right)) { + n = c->left; + replace(x, c, c->left); + } else { + t = c->right; + + while (!rbnode_is_empty(t->left)) { + t = t->left; + } + + s = t->colored; + n = t->right; + + if (t->parent == c) { + n->parent = t; + } else { + replace(x, t, t->right); + c->right->parent = t; + t->right = c->right; + } + + replace(x, c, t); + c->left->parent = t; + t->colored = c->colored; + t->left = c->left; + } + + if (!s) delete_fixup(x, n); + + return c; +} + + + +void libcdsb_rbtree_node_fixup(rbnode_t** x, rbnode_t* n) { + rbdir_t d[2]; + rbnode_t *u, *p, *gp; + + while (n->parent->colored) { + p = n->parent; + gp = p->parent; + d[0] = (gp->right == p) ? RBD_LEFT : RBD_RIGHT; + u = rbdir_dir(gp, d[0]); + + if (rbdir_dir(p, d[0]) == n) { + d[1] = (d[0] == RBD_LEFT) ? RBD_RIGHT : RBD_LEFT; + } else d[1] = 0; + + if (u->colored) { + u->colored = 0; + p->colored = 0; + gp->colored = 1; + + n = gp; + } else { + if (d[1]) { + rotate(x, n = p, d[1]); + p = n->parent; + gp = p->parent; + } + p->colored = 0; + gp->colored = 1; + + rotate(x, gp, d[0]); + } + + if (rbnode_is_root(n)) break; + } + + (*x)->colored = 0; +} + + +void* libcdsb_rbtree_node_create(void* v, rbnode_t* p, int c, int n) { + rbnode_t* x; + + x = malloc(n); + + x->left = rbnode_empty; + x->right = rbnode_empty; + x->value = v; + x->colored = c; + x->parent = p; + + 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* hhttpc_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; +} diff --git a/src/set/base.c b/src/set/base.c new file mode 100644 index 0000000..0b93fbb --- /dev/null +++ b/src/set/base.c @@ -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; +} diff --git a/src/set/copy.c b/src/set/copy.c new file mode 100644 index 0000000..ac75e6a --- /dev/null +++ b/src/set/copy.c @@ -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; +} diff --git a/src/set/extra.c b/src/set/extra.c new file mode 100644 index 0000000..0c68389 --- /dev/null +++ b/src/set/extra.c @@ -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; +} diff --git a/src/set/generics.c b/src/set/generics.c new file mode 100644 index 0000000..946ea80 --- /dev/null +++ b/src/set/generics.c @@ -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)); } diff --git a/src/string/base.c b/src/string/base.c index 55f5ee5..d4b4d46 100644 --- a/src/string/base.c +++ b/src/string/base.c @@ -60,7 +60,7 @@ int string_compare(const str_t* s0, const str_t* s1) { /*#####################################################################################################################*/ -_Bool string_concat_cstring(str_t* x, const char* s) { +_Bool libcdsb_string_concat_cstring(str_t* x, const char* s) { size_t n; size_t xn; @@ -77,7 +77,7 @@ _Bool string_concat_cstring(str_t* x, const char* s) { } -_Bool string_concat_char(str_t* x, int chr) { +_Bool libcdsb_string_concat_char(str_t* x, int chr) { size_t xn; size_t n; char *e; diff --git a/src/string/extra-split.c b/src/string/extra-split.c index 655e067..7879fc3 100644 --- a/src/string/extra-split.c +++ b/src/string/extra-split.c @@ -3,7 +3,7 @@ #include "include.h" -arr_t string_split_cstring(const str_t* s, const char* a, size_t maxn) { +arr_t libcdsb_string_split_cstring(const str_t* s, const char* a, size_t maxn) { arr_t x = { .mem = 0, .size = 0, .type = VTYPE_STRING }; size_t n; @@ -46,7 +46,7 @@ arr_t string_split_cstring(const str_t* s, const char* a, size_t maxn) { } -arr_t string_split_char(const str_t* s, int ac, size_t maxn) { +arr_t libcdsb_string_split_char(const str_t* s, int ac, size_t maxn) { arr_t x = { .mem = 0, .size = 0, .type = VTYPE_STRING }; char a[5] = { 0 }; diff --git a/src/string/extra.c b/src/string/extra.c index 4cd5493..50600f2 100644 --- a/src/string/extra.c +++ b/src/string/extra.c @@ -4,7 +4,7 @@ #include #include "include.h" -int string_case_compare(const str_t* s0, const str_t* s1) { +int string_compare_case_insensitive(const str_t* s0, const str_t* s1) { const char *p0, *p1, *t0, *t1; ssize_t n0, n1; u32_t uc0, uc1; @@ -76,7 +76,7 @@ size_t string_to_lower(str_t* x) { es = tochar_unicode(ps, uc1); if (!is_null(es)) { - string_replace(x, p, e-p, ps, es-ps); + libcdsb_string_replace(x, p, e-p, ps, es-ps); ++n; } } @@ -112,7 +112,7 @@ size_t string_to_upper(str_t* x) { es = tochar_unicode(ps, uc1); if (!is_null(es)) { - string_replace(x, p, e-p, ps, es-ps); + libcdsb_string_replace(x, p, e-p, ps, es-ps); ++n; } } @@ -146,7 +146,7 @@ size_t string_capitalize(str_t* x) { es = tochar_unicode(ps, uc1); if (!is_null(es)) { - string_replace(x, p, e-p, ps, es-ps); + libcdsb_string_replace(x, p, e-p, ps, es-ps); ++n; } } @@ -164,7 +164,7 @@ size_t string_capitalize(str_t* x) { es = tochar_unicode(ps, uc1); if (!is_null(es)) { - string_replace(x, p, e-p, ps, es-ps); + libcdsb_string_replace(x, p, e-p, ps, es-ps); ++n; } } @@ -207,3 +207,22 @@ size_t string_reverse(str_t* x) { return n; } + +/*#####################################################################################################################*/ + +void libcdsb_string_replace(str_t* x, char* p, size_t n, const char* v, size_t vn) { + if (n != vn) { + size_t l = strlen(x->buffer); + + if (n < vn) { + char* t = x->buffer; + + x->buffer = realloc(x->buffer, l + (vn - n) + 1); + p = x->buffer + (p - t); + } + + memmove(p+vn, p+n, l - (p+n - x->buffer) + 1); + } + + memcpy(p, v, vn); +} diff --git a/src/string/get.c b/src/string/get.c index 98c7a63..209ce9a 100644 --- a/src/string/get.c +++ b/src/string/get.c @@ -63,7 +63,7 @@ _Bool string_slice(str_t* x, str_t* s, ssize_t i, size_t c, _Bool cut) { /*#####################################################################################################################*/ -ssize_t string_indexof_cstring(const str_t* s, const char* a) { +ssize_t libcdsb_string_indexof_cstring(const str_t* s, const char* a) { char *e, *p; size_t n; @@ -92,7 +92,7 @@ ssize_t string_indexof_cstring(const str_t* s, const char* a) { } -ssize_t string_indexof_char(const str_t* s, int ac) { +ssize_t libcdsb_string_indexof_char(const str_t* s, int ac) { size_t n; char* e; @@ -127,7 +127,7 @@ ssize_t string_indexof_char(const str_t* s, int ac) { /*#####################################################################################################################*/ -size_t string_count_cstring(const str_t* s, const char* a) { +size_t libcdsb_string_count_cstring(const str_t* s, const char* a) { char* p; size_t n, c; @@ -148,7 +148,7 @@ size_t string_count_cstring(const str_t* s, const char* a) { } -size_t string_count_char(const str_t* s, int ac) { +size_t libcdsb_string_count_char(const str_t* s, int ac) { size_t n, c; char a[5] = {0}; diff --git a/src/string/include.h b/src/string/include.h index 361ba2a..a0a4764 100644 --- a/src/string/include.h +++ b/src/string/include.h @@ -29,35 +29,4 @@ ainline(char* prev_char(char* s)) { return s; } -extern void libcdsb_string_replace(str_t* x, char* p, size_t n, const char* v, size_t vn); - -#ifdef string_replace -#undef string_replace -#endif -#ifdef string_trim_spaces -#undef string_trim_spaces -#endif - -#define string_replace libcdsb_string_replace -#define string_indexof_cstring libcdsb_string_indexof_cstring -#define string_indexof_char libcdsb_string_indexof_char -#define string_count_cstring libcdsb_string_count_cstring -#define string_count_char libcdsb_string_count_char -#define string_concat_cstring libcdsb_string_concat_cstring -#define string_concat_char libcdsb_string_concat_char -#define string_trim_spaces libcdsb_string_trim_spaces -#define string_trim_cstring libcdsb_string_trim_cstring -#define string_trim_char libcdsb_string_trim_char -#define string_replace_cstring_cstring libcdsb_string_replace_cstring_cstring -#define string_replace_cstring_char libcdsb_string_replace_cstring_char -#define string_replace_char_cstring libcdsb_string_replace_char_cstring -#define string_replace_char_char libcdsb_string_replace_char_char -#define string_split_string libcdsb_string_split_string -#define string_split_cstring libcdsb_string_split_cstring -#define string_split_char libcdsb_string_split_char - -#define string_replace_cstring_cstring_r libcdsb_string_replace_r_cstring_cstring -#define string_replace_cstring_char_r libcdsb_string_replace_r_cstring_char -#define string_replace_char_cstring_r libcdsb_string_replace_r_char_cstring - #endif /* LIBCDSB_SRC_STRING_INCLUDE_H */ diff --git a/src/string/internal.c b/src/string/internal.c deleted file mode 100644 index bc50e01..0000000 --- a/src/string/internal.c +++ /dev/null @@ -1,21 +0,0 @@ -/* This software is licensed by the MIT License, see LICENSE file */ -/* Copyright © 2022 Gregory Lirent */ - -#include "include.h" - -void string_replace(str_t* x, char* p, size_t n, const char* v, size_t vn) { - if (n != vn) { - size_t l = strlen(x->buffer); - - if (n < vn) { - char* t = x->buffer; - - x->buffer = realloc(x->buffer, l + (vn - n) + 1); - p = x->buffer + (p - t); - } - - memmove(p+vn, p+n, l - (p+n - x->buffer) + 1); - } - - memcpy(p, v, vn); -} diff --git a/src/string/replace.c b/src/string/replace.c index 2ee84cd..ea08c43 100644 --- a/src/string/replace.c +++ b/src/string/replace.c @@ -3,7 +3,7 @@ #include "include.h" -size_t string_replace_cstring_cstring(str_t* x, const char* a, const char* d, size_t maxn) { +size_t libcdsb_string_replace_cstring_cstring(str_t* x, const char* a, const char* d, size_t maxn) { char *p, *t, *r; size_t c, n, an, dn; @@ -38,7 +38,7 @@ size_t string_replace_cstring_cstring(str_t* x, const char* a, const char* d, si } while (maxn-- && !is_null(p = strstr(p, a))) { - string_replace(x, p, an, d, dn); + libcdsb_string_replace(x, p, an, d, dn); p += an; ++c; } @@ -49,7 +49,7 @@ size_t string_replace_cstring_cstring(str_t* x, const char* a, const char* d, si } -size_t string_replace_cstring_char(str_t* x, const char* a, int dc, size_t maxn) { +size_t libcdsb_string_replace_cstring_char(str_t* x, const char* a, int dc, size_t maxn) { char *p, *t; char d[4]; size_t c, n, an, dn; @@ -77,7 +77,7 @@ size_t string_replace_cstring_char(str_t* x, const char* a, int dc, size_t maxn) } while (maxn-- && !is_null(p = strstr(p, a))) { - string_replace(x, p, an, d, dn); + libcdsb_string_replace(x, p, an, d, dn); p += an; ++c; } @@ -87,7 +87,7 @@ size_t string_replace_cstring_char(str_t* x, const char* a, int dc, size_t maxn) } -size_t string_replace_char_cstring(str_t* x, int ac, const char* d, size_t maxn) { +size_t libcdsb_string_replace_char_cstring(str_t* x, int ac, const char* d, size_t maxn) { char *p, *t; char a[4]; size_t c, n, an, dn; @@ -110,7 +110,7 @@ size_t string_replace_char_cstring(str_t* x, int ac, const char* d, size_t maxn) } while (maxn-- && !is_null(p = strstr(p, a))) { - string_replace(x, p, an, d, dn); + libcdsb_string_replace(x, p, an, d, dn); p += an; ++c; } @@ -120,7 +120,7 @@ size_t string_replace_char_cstring(str_t* x, int ac, const char* d, size_t maxn) } -size_t string_replace_char_char(str_t* x, int ac, int dc, size_t maxn) { +size_t libcdsb_string_replace_char_char(str_t* x, int ac, int dc, size_t maxn) { char* p; char a[4]; char d[4]; @@ -139,7 +139,7 @@ size_t string_replace_char_char(str_t* x, int ac, int dc, size_t maxn) { c = 0; while (maxn-- && !is_null(p = strstr(p, a))) { - string_replace(x, p, an, d, dn); + libcdsb_string_replace(x, p, an, d, dn); p += an; ++c; } @@ -149,7 +149,7 @@ size_t string_replace_char_char(str_t* x, int ac, int dc, size_t maxn) { -size_t string_replace_cstring_cstring_r(str_t* x, const char*restrict a, const char*restrict d, size_t maxn) { +size_t libcdsb_string_replace_r_cstring_cstring(str_t* x, const char*restrict a, const char*restrict d, size_t maxn) { char *restrict p; size_t c, an, dn; @@ -163,7 +163,7 @@ size_t string_replace_cstring_cstring_r(str_t* x, const char*restrict a, const c c = 0; while (maxn-- && !is_null(p = strstr(p, a))) { - string_replace(x, p, an, d, dn); + libcdsb_string_replace(x, p, an, d, dn); p += an; ++c; } @@ -172,7 +172,7 @@ size_t string_replace_cstring_cstring_r(str_t* x, const char*restrict a, const c } -size_t string_replace_cstring_char_r(str_t* x, const char*restrict a, int dc, size_t maxn) { +size_t libcdsb_string_replace_r_cstring_char(str_t* x, const char*restrict a, int dc, size_t maxn) { char *restrict p; char d[4]; size_t c, an, dn; @@ -188,7 +188,7 @@ size_t string_replace_cstring_char_r(str_t* x, const char*restrict a, int dc, si c = 0; while (maxn-- && !is_null(p = strstr(p, a))) { - string_replace(x, p, an, d, dn); + libcdsb_string_replace(x, p, an, d, dn); p += an; ++c; } @@ -197,7 +197,7 @@ size_t string_replace_cstring_char_r(str_t* x, const char*restrict a, int dc, si } -size_t string_replace_char_cstring_r(str_t* x, int ac, const char*restrict d, size_t maxn) { +size_t libcdsb_string_replace_r_char_cstring(str_t* x, int ac, const char*restrict d, size_t maxn) { char *restrict p; char a[4]; size_t c, an, dn; @@ -214,7 +214,7 @@ size_t string_replace_char_cstring_r(str_t* x, int ac, const char*restrict d, si c = 0; while (maxn-- && !is_null(p = strstr(p, a))) { - string_replace(x, p, an, d, dn); + libcdsb_string_replace(x, p, an, d, dn); p += an; ++c; } diff --git a/src/string/trim.c b/src/string/trim.c index 11ac6e1..d40fe9c 100644 --- a/src/string/trim.c +++ b/src/string/trim.c @@ -7,7 +7,7 @@ /*#####################################################################################################################*/ -void string_trim_spaces(str_t* x, int direction) { +void libcdsb_string_trim_spaces(str_t* x, int direction) { static size_t m[32/(sizeof(size_t))] = {0}; u8_t* l; @@ -51,7 +51,7 @@ void string_trim_spaces(str_t* x, int direction) { /*#####################################################################################################################*/ -void string_trim_cstring(str_t* x, const char* s, int direction) { +void libcdsb_string_trim_cstring(str_t* x, const char* s, int direction) { u8_t* l; u8_t* r; @@ -122,7 +122,7 @@ void string_trim_cstring(str_t* x, const char* s, int direction) { } -void string_trim_char(str_t* x, int sc, int direction) { +void libcdsb_string_trim_char(str_t* x, int sc, int direction) { u8_t* l; u8_t* r; diff --git a/src/vnode.c b/src/vnode.c index e8c2efd..6ec31dd 100644 --- a/src/vnode.c +++ b/src/vnode.c @@ -3,6 +3,7 @@ #include "__internal/assert.h" #include "__internal/vnode.h" +#include "../include/string.h" /*#####################################################################################################################*/ @@ -10,6 +11,17 @@ static vnode_t create_value(vtype xt, const void* v, vtype t) { var_t _; + if (t == VTYPE_FLOAT) { + _.u64 = (s64_t)roundf(*(fl_t*)v); + t = VTYPE_INT64; + } else if (t == VTYPE_DOUBLE) { + _.u64 = (s64_t)round (*(dbl_t*)v); + t = VTYPE_INT64; + } else { + _.u64 = (s64_t)roundl(*(ldbl_t*)v); + t = VTYPE_INT64; + } + if (sizeof(void*) == 8) { if (t == VTYPE_UINT8 || t == VTYPE_INT8 || t == VTYPE_BOOLEAN ) { _.u64 = *(u8_t*)v; @@ -63,11 +75,27 @@ static vnode_t create_value(vtype xt, const void* v, vtype t) { static vnode_t create_float(vtype xt, const void* v, vtype t) { var_t _; - if (t == VTYPE_FLOAT) { + if (t == VTYPE_UINT8 || t == VTYPE_BOOLEAN ) { + _.ld = *(u8_t*)v; + } else if (t == VTYPE_UINT16) { + _.ld = *(u16_t*)v; + } else if (t == VTYPE_UINT32 || (sizeof(void*) == 4 && t == VTYPE_POINTER)) { + _.ld = *(u32_t*)v; + } else if (t == VTYPE_UINT64 || (sizeof(void*) == 8 && t == VTYPE_POINTER)) { + _.ld = *(u64_t*)v; + } else if (t == VTYPE_INT8) { + _.ld = *(s8_t*)v; + } else if (t == VTYPE_INT16) { + _.ld = *(s16_t*)v; + } else if (t == VTYPE_INT32) { + _.ld = *(s32_t*)v; + } else if (t == VTYPE_INT64) { + _.ld = *(s64_t*)v; + } else if (t == VTYPE_FLOAT) { _.ld = *(fl_t*)v; } else if (t == VTYPE_DOUBLE) { _.ld = *(dbl_t*)v; - } else { // (t == VTYPE_LDOUBLE) + } else { _.ld = *(ldbl_t*)v; } @@ -81,7 +109,7 @@ static vnode_t create_float(vtype xt, const void* v, vtype t) { if (!is_permissible(dbl_t)) { _.ptr = memndup(&_.d, sizeof(_.d)); } - } else { // (xt == VTYPE_LDOUBLE) + } else { if (!is_permissible(ldbl_t)) { _.ptr = memndup(&_.ld, sizeof(_.ld)); } @@ -135,7 +163,9 @@ vnode_t libcdsb_vnode_create(const void* v, vtype t) { case VTYPE_POINTER: _.ptr = *(void**)v; break; - case VTYPE_STRING: _.ptr = string_duplicate(v); + case VTYPE_STRING: if (sizeof(str_t) == sizeof(void*)) { + _.ptr = strdup(*(char**)v); + } else _.ptr = string_duplicate(v); break; case VTYPE_MAP: _.ptr = map_duplicate(v); @@ -178,7 +208,7 @@ void* libcdsb_vnode_peek(const vnode_t* x, vtype t) { case VTYPE_UINT32: vt_: return (void*)x; - case VTYPE_STRING: + case VTYPE_STRING: if (sizeof(str_t) == sizeof(void*)) goto vt_; case VTYPE_MAP: case VTYPE_ARRAY: case VTYPE_LIST: @@ -210,7 +240,10 @@ void libcdsb_vnode_free(vnode_t* x, vtype t) { vt_: break; - case VTYPE_STRING: string_free(*x); goto pt_; + case VTYPE_STRING: if (sizeof(str_t) > sizeof(void*)) { + string_free(*x); + } + goto pt_; case VTYPE_MAP: map_free(*x); goto pt_; case VTYPE_ARRAY: array_free(*x); goto pt_; case VTYPE_LIST: list_free(*x); goto pt_; @@ -229,18 +262,22 @@ void libcdsb_vnode_free(vnode_t* x, vtype t) { vnode_t libcdsb_vnode_create_target(vtype xt, const void* v, vtype t) { var_t _ = { .ptr = 0 }; - if (is_integer(xt)) { - tvalue_assert(t); + if (xt <= VTYPE_LDOUBLE) { + if (t >= VTYPE_STRING) t = VTYPE_POINTER; + + if (xt <= VTYPE_INT64) + return create_value(xt, v, t); return create_value(xt, v, t); - } else if (is_float(xt)) { - tfloat_assert(t); - return create_float(xt, v, t); + } else if (t == VTYPE_POINTER && (t = xt) > VTYPE_STRING) { + v = *(void**)v; } type_assert(xt, t); switch (xt) { default: abort(); - case VTYPE_STRING: _.ptr = string_duplicate(v); + case VTYPE_STRING: if (sizeof(str_t) == sizeof(void*)) { + _.ptr = strdup(*(char**)v); + } else _.ptr = string_duplicate(v); break; case VTYPE_MAP: _.ptr = map_duplicate(v);