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_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_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_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_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 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 */
|
#endif /* LIBCDSB_EXTRA_ARRAY_H */
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
/* This software is licensed by the MIT License, see LICENSE file */
|
/* This software is licensed by the MIT License, see LICENSE file */
|
||||||
/* Copyright © 2022 Gregory Lirent */
|
/* Copyright © 2022 Gregory Lirent */
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include "../list.h"
|
#include "../list.h"
|
||||||
|
|
||||||
#ifndef LIBCDSB_EXTRA_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_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_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 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__;
|
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 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 */
|
#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_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 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 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));
|
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
|
#ifndef LIBCDSB_SRC_INTERNAL_VNODE_H
|
||||||
#define 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))
|
#define is_permissible(T) (sizeof(void*) >= sizeof(T) && _Alignof(void*) >= _Alignof(T))
|
||||||
|
|
||||||
typedef union {
|
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* p;
|
||||||
void* e;
|
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;
|
lnode_t* c;
|
||||||
size_t n;
|
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 n;
|
||||||
size_t xn;
|
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 xn;
|
||||||
size_t n;
|
size_t n;
|
||||||
char *e;
|
char *e;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "include.h"
|
#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 };
|
arr_t x = { .mem = 0, .size = 0, .type = VTYPE_STRING };
|
||||||
|
|
||||||
size_t n;
|
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 };
|
arr_t x = { .mem = 0, .size = 0, .type = VTYPE_STRING };
|
||||||
char a[5] = { 0 };
|
char a[5] = { 0 };
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "include.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;
|
const char *p0, *p1, *t0, *t1;
|
||||||
ssize_t n0, n1;
|
ssize_t n0, n1;
|
||||||
u32_t uc0, uc1;
|
u32_t uc0, uc1;
|
||||||
@ -76,7 +76,7 @@ size_t string_to_lower(str_t* x) {
|
|||||||
es = tochar_unicode(ps, uc1);
|
es = tochar_unicode(ps, uc1);
|
||||||
|
|
||||||
if (!is_null(es)) {
|
if (!is_null(es)) {
|
||||||
string_replace(x, p, e-p, ps, es-ps);
|
libcdsb_string_replace(x, p, e-p, ps, es-ps);
|
||||||
++n;
|
++n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -112,7 +112,7 @@ size_t string_to_upper(str_t* x) {
|
|||||||
es = tochar_unicode(ps, uc1);
|
es = tochar_unicode(ps, uc1);
|
||||||
|
|
||||||
if (!is_null(es)) {
|
if (!is_null(es)) {
|
||||||
string_replace(x, p, e-p, ps, es-ps);
|
libcdsb_string_replace(x, p, e-p, ps, es-ps);
|
||||||
++n;
|
++n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,7 +146,7 @@ size_t string_capitalize(str_t* x) {
|
|||||||
es = tochar_unicode(ps, uc1);
|
es = tochar_unicode(ps, uc1);
|
||||||
|
|
||||||
if (!is_null(es)) {
|
if (!is_null(es)) {
|
||||||
string_replace(x, p, e-p, ps, es-ps);
|
libcdsb_string_replace(x, p, e-p, ps, es-ps);
|
||||||
++n;
|
++n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,7 +164,7 @@ size_t string_capitalize(str_t* x) {
|
|||||||
es = tochar_unicode(ps, uc1);
|
es = tochar_unicode(ps, uc1);
|
||||||
|
|
||||||
if (!is_null(es)) {
|
if (!is_null(es)) {
|
||||||
string_replace(x, p, e-p, ps, es-ps);
|
libcdsb_string_replace(x, p, e-p, ps, es-ps);
|
||||||
++n;
|
++n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -207,3 +207,22 @@ size_t string_reverse(str_t* x) {
|
|||||||
|
|
||||||
return n;
|
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;
|
char *e, *p;
|
||||||
size_t n;
|
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;
|
size_t n;
|
||||||
char* e;
|
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;
|
char* p;
|
||||||
size_t n, c;
|
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;
|
size_t n, c;
|
||||||
|
|
||||||
char a[5] = {0};
|
char a[5] = {0};
|
||||||
|
@ -29,35 +29,4 @@ ainline(char* prev_char(char* s)) {
|
|||||||
return 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 */
|
#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"
|
#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;
|
char *p, *t, *r;
|
||||||
size_t c, n, an, dn;
|
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))) {
|
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;
|
p += an;
|
||||||
++c;
|
++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 *p, *t;
|
||||||
char d[4];
|
char d[4];
|
||||||
size_t c, n, an, dn;
|
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))) {
|
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;
|
p += an;
|
||||||
++c;
|
++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 *p, *t;
|
||||||
char a[4];
|
char a[4];
|
||||||
size_t c, n, an, dn;
|
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))) {
|
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;
|
p += an;
|
||||||
++c;
|
++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* p;
|
||||||
char a[4];
|
char a[4];
|
||||||
char d[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;
|
c = 0;
|
||||||
|
|
||||||
while (maxn-- && !is_null(p = strstr(p, a))) {
|
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;
|
p += an;
|
||||||
++c;
|
++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;
|
char *restrict p;
|
||||||
size_t c, an, dn;
|
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;
|
c = 0;
|
||||||
|
|
||||||
while (maxn-- && !is_null(p = strstr(p, a))) {
|
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;
|
p += an;
|
||||||
++c;
|
++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 *restrict p;
|
||||||
char d[4];
|
char d[4];
|
||||||
size_t c, an, dn;
|
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;
|
c = 0;
|
||||||
|
|
||||||
while (maxn-- && !is_null(p = strstr(p, a))) {
|
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;
|
p += an;
|
||||||
++c;
|
++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 *restrict p;
|
||||||
char a[4];
|
char a[4];
|
||||||
size_t c, an, dn;
|
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;
|
c = 0;
|
||||||
|
|
||||||
while (maxn-- && !is_null(p = strstr(p, a))) {
|
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;
|
p += an;
|
||||||
++c;
|
++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};
|
static size_t m[32/(sizeof(size_t))] = {0};
|
||||||
|
|
||||||
u8_t* l;
|
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* l;
|
||||||
u8_t* r;
|
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* l;
|
||||||
u8_t* r;
|
u8_t* r;
|
||||||
|
61
src/vnode.c
61
src/vnode.c
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "__internal/assert.h"
|
#include "__internal/assert.h"
|
||||||
#include "__internal/vnode.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) {
|
static vnode_t create_value(vtype xt, const void* v, vtype t) {
|
||||||
var_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 (sizeof(void*) == 8) {
|
||||||
if (t == VTYPE_UINT8 || t == VTYPE_INT8 || t == VTYPE_BOOLEAN ) {
|
if (t == VTYPE_UINT8 || t == VTYPE_INT8 || t == VTYPE_BOOLEAN ) {
|
||||||
_.u64 = *(u8_t*)v;
|
_.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) {
|
static vnode_t create_float(vtype xt, const void* v, vtype t) {
|
||||||
var_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;
|
_.ld = *(fl_t*)v;
|
||||||
} else if (t == VTYPE_DOUBLE) {
|
} else if (t == VTYPE_DOUBLE) {
|
||||||
_.ld = *(dbl_t*)v;
|
_.ld = *(dbl_t*)v;
|
||||||
} else { // (t == VTYPE_LDOUBLE)
|
} else {
|
||||||
_.ld = *(ldbl_t*)v;
|
_.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)) {
|
if (!is_permissible(dbl_t)) {
|
||||||
_.ptr = memndup(&_.d, sizeof(_.d));
|
_.ptr = memndup(&_.d, sizeof(_.d));
|
||||||
}
|
}
|
||||||
} else { // (xt == VTYPE_LDOUBLE)
|
} else {
|
||||||
if (!is_permissible(ldbl_t)) {
|
if (!is_permissible(ldbl_t)) {
|
||||||
_.ptr = memndup(&_.ld, sizeof(_.ld));
|
_.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;
|
case VTYPE_POINTER: _.ptr = *(void**)v;
|
||||||
break;
|
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;
|
break;
|
||||||
|
|
||||||
case VTYPE_MAP: _.ptr = map_duplicate(v);
|
case VTYPE_MAP: _.ptr = map_duplicate(v);
|
||||||
@ -178,7 +208,7 @@ void* libcdsb_vnode_peek(const vnode_t* x, vtype t) {
|
|||||||
case VTYPE_UINT32:
|
case VTYPE_UINT32:
|
||||||
vt_: return (void*)x;
|
vt_: return (void*)x;
|
||||||
|
|
||||||
case VTYPE_STRING:
|
case VTYPE_STRING: if (sizeof(str_t) == sizeof(void*)) goto vt_;
|
||||||
case VTYPE_MAP:
|
case VTYPE_MAP:
|
||||||
case VTYPE_ARRAY:
|
case VTYPE_ARRAY:
|
||||||
case VTYPE_LIST:
|
case VTYPE_LIST:
|
||||||
@ -210,7 +240,10 @@ void libcdsb_vnode_free(vnode_t* x, vtype t) {
|
|||||||
vt_:
|
vt_:
|
||||||
break;
|
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_MAP: map_free(*x); goto pt_;
|
||||||
case VTYPE_ARRAY: array_free(*x); goto pt_;
|
case VTYPE_ARRAY: array_free(*x); goto pt_;
|
||||||
case VTYPE_LIST: list_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) {
|
vnode_t libcdsb_vnode_create_target(vtype xt, const void* v, vtype t) {
|
||||||
var_t _ = { .ptr = 0 };
|
var_t _ = { .ptr = 0 };
|
||||||
|
|
||||||
if (is_integer(xt)) {
|
if (xt <= VTYPE_LDOUBLE) {
|
||||||
tvalue_assert(t);
|
if (t >= VTYPE_STRING) t = VTYPE_POINTER;
|
||||||
|
|
||||||
|
if (xt <= VTYPE_INT64)
|
||||||
|
return create_value(xt, v, t);
|
||||||
return create_value(xt, v, t);
|
return create_value(xt, v, t);
|
||||||
} else if (is_float(xt)) {
|
} else if (t == VTYPE_POINTER && (t = xt) > VTYPE_STRING) {
|
||||||
tfloat_assert(t);
|
v = *(void**)v;
|
||||||
return create_float(xt, v, t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type_assert(xt, t);
|
type_assert(xt, t);
|
||||||
|
|
||||||
switch (xt) { default: abort();
|
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;
|
break;
|
||||||
|
|
||||||
case VTYPE_MAP: _.ptr = map_duplicate(v);
|
case VTYPE_MAP: _.ptr = map_duplicate(v);
|
||||||
|
Loading…
Reference in New Issue
Block a user