Merge branch 'rbtree' into discrete-tests
This commit is contained in:
commit
4edaea54b3
@ -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 */
|
||||
|
@ -1,7 +1,6 @@
|
||||
/* This software is licensed by the MIT License, see LICENSE file */
|
||||
/* Copyright © 2022 Gregory Lirent */
|
||||
|
||||
#include <assert.h>
|
||||
#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 */
|
||||
|
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 */
|
@ -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));
|
||||
|
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 */
|
53
src/__internal/rbtree.h
Normal file
53
src/__internal/rbtree.h
Normal file
@ -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 */
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
383
src/rbtree.c
Normal file
383
src/rbtree.c
Normal file
@ -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;
|
||||
}
|
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)); }
|
@ -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;
|
||||
|
@ -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 };
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <ctype.h>
|
||||
#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);
|
||||
}
|
||||
|
@ -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};
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
61
src/vnode.c
61
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);
|
||||
|
Loading…
Reference in New Issue
Block a user