Merge branch '#33-issue' of lirent/libcdsb into develop

This commit is contained in:
Gregory Lirent 2022-08-18 02:29:12 +03:00 committed by Gogs
commit 2191306e35
32 changed files with 845 additions and 733 deletions

View File

@ -7,6 +7,8 @@
#ifndef LIBCDSB_DICT_H
#define LIBCDSB_DICT_H
/*#####################################################################################################################*/
typedef int (*dict_access_callback)(const void* key, vtype key_type, void* value, vtype value_type, void* data);
extern void dict_init(vtype_dict* x) Nonnull__(1);
@ -16,6 +18,10 @@ extern void dict_init(vtype_dict* x) Nonnull__(1);
#define dict_update(x, key, value) _LIBCDSB_Generic2(libcdsb_dict, update, key, value)(x, key, value)
#define dict_remove(x, key) dict_pop(x, key, 0, 0)
#define in_dict(x, key) (dict_get(&x, key, 0, 0) == 0)
/*#####################################################################################################################*/
extern int libcdsb_dict_get_by_pointer(vtype_dict* x, const void* key, void* data, dict_access_callback, bool cut) Nonnull__(1);
extern int libcdsb_dict_get_by_cstring(vtype_dict* x, const char* key, void* data, dict_access_callback, bool cut) Nonnull__(1,2);
extern int libcdsb_dict_get_by_string (vtype_dict* x, const vtype_string* key, void* data, dict_access_callback, bool cut) Nonnull__(1,2);

View File

@ -9,7 +9,7 @@
#define dict_foreach(x, data, callback) libcdsb_dict_foreach(x, data, callback, 0)
extern bool libcdsb_dict_update (vtype_dict* x, const void* key, vtype key_type, const void* value, vtype value_type) Nonnull__(1);
extern int libcdsb_dict_get (vtype_dict* x, const void* key, vtype key_type, void* data, dict_access_callback, bool cut) Nonnull__(1);
extern int libcdsb_dict_find (vtype_dict* x, const void* key, vtype key_type, void* data, dict_access_callback, bool cut) Nonnull__(1);
extern int libcdsb_dict_foreach (vtype_dict* x, void* data, dict_access_callback, bool flush) Nonnull__(1,3);
extern bool libcdsb_dict_shrink_to_fit(vtype_dict* x) Nonnull__(1);

View File

@ -12,24 +12,29 @@ typedef struct libcdsb_stack_node {
void* value;
} stack_t;
extern void libcdsb_stack_init (stack_t* stack) Nonnull__(1);
extern void libcdsb_stack_push (stack_t* stack, void* value) Nonnull__(1);
extern void* libcdsb_stack_pop (stack_t* stack) Nonnull__(1);
extern void libcdsb_stack_flush(stack_t* stack) Nonnull__(1);
extern void libcdsb_stack_init (stack_t* stack) Nonnull__(1);
extern void libcdsb_stack_push (stack_t* stack, void* value) Nonnull__(1);
extern void libcdsb_stack_push_many(stack_t* stack, size_t n, ...) Nonnull__(1);
extern void* libcdsb_stack_pop (stack_t* stack) Nonnull__(1);
extern void libcdsb_stack_flush (stack_t* stack) Nonnull__(1);
extern void* libcdsb_aalloc (size_t a, size_t n) Warn_unused_result__;
extern void* libcdsb_malloc (size_t n) Warn_unused_result__;
extern void* libcdsb_calloc (size_t n, size_t c) Warn_unused_result__;
extern void* libcdsb_realloc(void *p, size_t n) Warn_unused_result__;
extern void libcdsb_free(void* s);
#define aligned_alloc libcdsb_aalloc
#define malloc libcdsb_malloc
#define calloc libcdsb_calloc
#define realloc libcdsb_realloc
#define free libcdsb_free
#define stack_init libcdsb_stack_init
#define stack_push libcdsb_stack_push
#define stack_pop libcdsb_stack_pop
#define stack_flush libcdsb_stack_flush
#define stack_init libcdsb_stack_init
#define stack_push libcdsb_stack_push
#define stack_push_many libcdsb_stack_push_many
#define stack_pop libcdsb_stack_pop
#define stack_flush libcdsb_stack_flush
#endif /* LIBCDSB_EXTRA_MEMORY_H */

View File

@ -8,7 +8,7 @@
/*#####################################################################################################################*/
#define string_split(x, sep, maxn) _LIBCDSB_GenericS(libcdsb_string, split, sep)(x, sep, maxn)
#define string_split(s, sep, maxn) _LIBCDSB_GenericS(libcdsb_string, split, sep)(s, sep, maxn)
#define string_case_compare string_compare_case_insensitive
#define string_replace_r(x, src, dest, maxn) _LIBCDSB_GenericS2(libcdsb_string, replace_r, src, dest)(x, src, dest, maxn)
@ -27,15 +27,15 @@ extern size_t string_align_center(vtype_string* x, size_t padsize, int padchr) N
extern size_t string_align_right (vtype_string* x, size_t padsize, int padchr) Nonnull__(1);
extern size_t string_align_left (vtype_string* x, size_t padsize, int padchr) Nonnull__(1);
extern int string_compare_case_insensitive(const vtype_string* s0, const vtype_string* s1) Pure__ Warn_unused_result__ Nonnull__(1,2);
extern void libcdsb_string_replace(vtype_string* x, char* dest, size_t dest_nmemb, const char* src, size_t nmemb) Nonnull__(1,2);
/*#####################################################################################################################*/
inline vtype_array libcdsb_string_split_string (const vtype_string* x, const vtype_string* sep, size_t maxn) Nonnull__(1) Always_inline__;
extern vtype_array libcdsb_string_split_cstring(const vtype_string* string, const char* sep, size_t maxn) Nonnull__(1);
extern vtype_array libcdsb_string_split_char (const vtype_string* string, int chr, size_t maxn) Nonnull__(1);
extern int string_compare_case_insensitive(const vtype_string* s0, const vtype_string* s1) Pure__ Warn_unused_result__ Nonnull__(1,2);
inline vtype_array libcdsb_string_split_string (const vtype_string* s, const vtype_string* sep, size_t maxn) Nonnull__(1) Always_inline__;
extern vtype_array libcdsb_string_split_cstring(const vtype_string* s, const char* sep, size_t maxn) Nonnull__(1);
extern vtype_array libcdsb_string_split_char (const vtype_string* s, int chr, size_t maxn) Nonnull__(1);
inline void libcdsb_string_trim_string (vtype_string* x, const vtype_string* s, int direction) Nonnull__(1) Always_inline__;
extern void libcdsb_string_trim_cstring(vtype_string* x, const char* s, int direction) Nonnull__(1);

View File

@ -6,8 +6,6 @@
#ifndef LIBCDSB_EXTRA_VTYPE_H
#define LIBCDSB_EXTRA_VTYPE_H
extern const size_t LIBCDSB_VTYPE_SIZES[18];
extern const char* libcdsb_vtype_name(vtype t) Warn_unused_result__;
extern const char* libcdsb_vtype_stringify(const void* value, vtype t) Warn_unused_result__;

View File

@ -11,8 +11,8 @@
typedef int (*list_access_callback)(void* value, ssize_t index, vtype type, void* data);
extern void list_init (vtype_list* x) Nonnull__(1);
extern void list_extend(vtype_list* x, const vtype_list* s) Nonnull__(1,2);
extern void list_init (vtype_list* x) Nonnull__(1);
extern void list_extend (vtype_list* x, const vtype_list* s) Nonnull__(1,2);
extern size_t list_slice (vtype_list* x, vtype_list* src, ssize_t index, size_t count, bool cut) Nonnull__(1,2);
extern void list_sort (vtype_list* x) Nonnull__(1);
extern void list_reverse(vtype_list* x) Nonnull__(1);

View File

@ -7,6 +7,8 @@
#ifndef LIBCDSB_MAP_H
#define LIBCDSB_MAP_H
/*#####################################################################################################################*/
typedef int (*map_access_callback)(const void* key, vtype key_type, void* value, vtype value_type, void* data);
extern void map_init(vtype_map* x, vtype key_type) Nonnull__(1);
@ -16,6 +18,10 @@ extern void map_init(vtype_map* x, vtype key_type) Nonnull__(1);
#define map_update(x, key, value) _LIBCDSB_Generic2(libcdsb_map, update, key, value)(x, key, value)
#define map_remove(x, key) map_pop(x, key, 0, 0)
#define in_map(x, key) (map_get(&x, key, 0, 0) == 0)
/*#####################################################################################################################*/
extern int libcdsb_map_find_pointer(vtype_map* x, const void* key, void* data, map_access_callback, bool cut) Nonnull__(1);
extern int libcdsb_map_find_cstring(vtype_map* x, const char* key, void* data, map_access_callback, bool cut) Nonnull__(1,2);
extern int libcdsb_map_find_string (vtype_map* x, const vtype_string* key, void* data, map_access_callback, bool cut) Nonnull__(1,2);

View File

@ -7,6 +7,8 @@
#ifndef LIBCDSB_SET_H
#define LIBCDSB_SET_H
/*#####################################################################################################################*/
typedef int (*vset_access_callback)(const void* value, vtype type, void* data);
extern void vset_init(vtype_set* x, vtype type) Nonnull__(1);
@ -14,8 +16,11 @@ extern void vset_init(vtype_set* x, vtype type) Nonnull__(1);
#define vset_pop(x, value, data, callback) _LIBCDSB_Generic (libcdsb_vset, find, value)(x, value, data, callback, 1)
#define vset_get(x, value, data, callback) _LIBCDSB_Generic (libcdsb_vset, find, value)(x, value, data, callback, 0)
#define vset_push(x, value) _LIBCDSB_Generic (libcdsb_vset, push, value)(x, value)
#define vset_remove(x, value) vset_pop(x, value, 0, 0)
#define in_vset(x, value) (vset_get(&x, value, 0, 0, 0) == 0)
#define in_vset(x, value) (vset_get(&x, value, 0, 0) == 0)
/*#####################################################################################################################*/
extern bool libcdsb_vset_push_pointer(vtype_set* x, const void* value) Nonnull__(1);
extern bool libcdsb_vset_push_cstring(vtype_set* x, const char* value) Nonnull__(1,2);

View File

@ -13,11 +13,11 @@
extern void string_init(vtype_string* x, const char* value) Nonnull__(1);
extern char* string_at(const vtype_string* s, ssize_t index) Nonnull__(1);
extern bool string_slice(vtype_string* x, vtype_string* s, ssize_t index, size_t nchars, bool cut) Nonnull__(1,2);
extern size_t string_slice(vtype_string* x, vtype_string* s, ssize_t index, size_t nchars, bool cut) Nonnull__(1,2);
#define string_indexof(s, arg) _LIBCDSB_GenericS(libcdsb_string, indexof, arg)(s, arg)
#define string_count(s, arg) _LIBCDSB_GenericS(libcdsb_string, count, arg)(s, arg)
#define string_concat(s, value) _LIBCDSB_GenericS(libcdsb_string, concat, value)(s, value)
#define string_concat(x, value) _LIBCDSB_GenericS(libcdsb_string, concat, value)(x, value)
#define string_trim_spaces(x) libcdsb_string_trim_spaces(x, 0)
#define string_ltrim_spaces(x) libcdsb_string_trim_spaces(x, -1)

View File

@ -31,8 +31,6 @@ typedef enum libcdsb_value_types {
VTYPE_LIST = 16,
VTYPE_SET = 17,
VTYPE_DICT = 18,
LIBCDSB_VTYPE_TERMINATION, /* It must be at the end of the enum. Never be used */
} vtype;

View File

@ -14,6 +14,8 @@
#ifndef LIBCDSB_SRC_INTERNAL_INCLUDE
#define LIBCDSB_SRC_INTERNAL_INCLUDE
extern const size_t LIBCDSB_VTYPE_SIZES[19];
#define is_x64 (sizeof(void*) == sizeof(vtype_uint64))
#define is_big_endian (*((unsigned int*)"\0\0\0\1") < (unsigned int)0xffff)
#define is_little_endian (!is_big_endian)

View File

@ -29,17 +29,4 @@ extern rbnode_t* libcdsb_rbtree_node_delete(rbnode_t** root, rbnode_t* node)
#define rbnode_is_empty(n) ((n) == rbnode_empty)
#define rbnode_is_root(n) rbnode_is_empty((n)->parent)
extern void* libcdsb_rbtree_duplicate(const rbnode_t* s, void* (*node_duplicate)(void* src, void* parent, void* info), void* info) wur__ Nonnull__(1);
extern int libcdsb_rbtree_compare (const rbnode_t* s0, const rbnode_t* s1, int (*node_compare)(const rbnode_t* s0, const rbnode_t* s1, void* info), void* info) pure__ wur__ Nonnull__(1,2);
extern hash_t libcdsb_rbtree_hash(const void* s, hash_t (*node_hash)(const void* s, void* info), void* info) pure__ wur__ Nonnull__(1);
extern size_t libcdsb_rbtree_size(const void* s) pure__ wur__ Nonnull__(1);
extern void libcdsb_rbtree_free(void* x, void (*node_free)(void* x, void* info), void* info) Nonnull__(1);
#define rbtree_duplicate libcdsb_rbtree_duplicate
#define rbtree_compare libcdsb_rbtree_compare
#define rbtree_hash libcdsb_rbtree_hash
#define rbtree_size libcdsb_rbtree_size
#define rbtree_free libcdsb_rbtree_free
#endif /* LIBCDSB_SRC_INTERNAL_RBTREE_H */

View File

@ -4,6 +4,23 @@
#include "include.h"
#include "../__internal/assert.h"
typedef void (*type_free)(void*);
static inline type_free get_type_free(vtype type) {
switch (type) {
default:
#ifndef NDEBUG
abort();
#endif
case VTYPE_STRING: return (void*)string_free;
case VTYPE_ARRAY: return (void*) array_free;
case VTYPE_LIST: return (void*) list_free;
case VTYPE_MAP: return (void*) map_free;
case VTYPE_SET: return (void*) vset_free;
case VTYPE_DICT: return (void*) dict_free;
}
}
/*#####################################################################################################################*/
hash_t array_hash(const arr_t* s) {
@ -29,21 +46,11 @@ void array_init(arr_t* x, vtype t) {
void array_free(arr_t* x) {
if (x->size && x->type >= VTYPE_STRING) {
void* p = x->mem;
void (*free_)(void*);
type_free free_;
assert(!is_null(p));
switch (x->type) {
default:
#ifndef NDEBUG
abort();
#endif
case VTYPE_STRING: free_ = (void*)string_free; break;
case VTYPE_ARRAY: free_ = (void*) array_free; break;
case VTYPE_LIST: free_ = (void*) list_free; break;
case VTYPE_MAP: free_ = (void*) map_free; break;
case VTYPE_SET: free_ = (void*) vset_free; break;
}
free_ = get_type_free(x->type);
do {
free_(p);

View File

@ -4,6 +4,22 @@
#include "include.h"
#include "../__internal/assert.h"
typedef void (*type_initializer)(void*, const void*);
static inline type_initializer get_type_initializer(vtype type) {
switch (type) {
default:
#ifndef NDEBUG
abort();
#endif
case VTYPE_STRING: return (void*)string_copy_init;
case VTYPE_ARRAY: return (void*) array_copy_init;
case VTYPE_LIST: return (void*) list_copy_init;
case VTYPE_MAP: return (void*) map_copy_init;
case VTYPE_SET: return (void*) vset_copy_init;
case VTYPE_DICT: return (void*) dict_copy_init;
}
}
arr_t array_copy(const arr_t* s) {
arr_t x = { .mem = 0, .size = 0, .type = 0 };
@ -14,19 +30,12 @@ arr_t array_copy(const arr_t* s) {
if (s->type >= VTYPE_STRING) {
void *p, *v, *e;
void (*init)(void*, const void*);
type_initializer init;
x.mem = p = malloc(x.size*vtype_size(x.type));
v = s->mem;
e = array_end(&x);
switch (s->type) { default: abort();
case VTYPE_STRING: init = (void*)string_copy_init; break;
case VTYPE_ARRAY: init = (void*) array_copy_init; break;
case VTYPE_LIST: init = (void*) list_copy_init; break;
case VTYPE_MAP: init = (void*) map_copy_init; break;
case VTYPE_SET: init = (void*) vset_copy_init; break;
}
init = get_type_initializer(s->type);
do {
init(p, v);
@ -50,19 +59,12 @@ arr_t* array_duplicate(const arr_t* s) {
if (s->type >= VTYPE_STRING) {
void *p, *v, *e;
void (*init)(void*, const void*);
type_initializer init;
x->mem = p = malloc(x->size*vtype_size(x->type));
v = s->mem;
e = array_end(x);
switch (s->type) { default: abort();
case VTYPE_STRING: init = (void*)string_copy_init; break;
case VTYPE_ARRAY: init = (void*) array_copy_init; break;
case VTYPE_LIST: init = (void*) list_copy_init; break;
case VTYPE_MAP: init = (void*) map_copy_init; break;
case VTYPE_SET: init = (void*) vset_copy_init; break;
}
init = get_type_initializer(s->type);
do {
init(p, v);
@ -84,19 +86,12 @@ void array_copy_init(arr_t* x, const arr_t* s) {
if (s->type >= VTYPE_STRING) {
void *p, *v, *e;
void (*init)(void*, const void*);
type_initializer init;
x->mem = p = malloc(x->size*vtype_size(x->type));
v = s->mem;
e = array_end(x);
switch (s->type) { default: abort();
case VTYPE_STRING: init = (void*)string_copy_init; break;
case VTYPE_ARRAY: init = (void*) array_copy_init; break;
case VTYPE_LIST: init = (void*) list_copy_init; break;
case VTYPE_MAP: init = (void*) map_copy_init; break;
case VTYPE_SET: init = (void*) vset_copy_init; break;
}
init = get_type_initializer(s->type);
do {
init(p, v);
@ -125,19 +120,12 @@ size_t array_slice(arr_t* x, arr_t* s, ssize_t i, size_t n, _Bool cut) {
if (!cut && s->type >= VTYPE_STRING) {
void *p, *v, *e;
void (*init)(void*, const void*);
type_initializer init;
p = x->mem;
v = array_internal_at(s, i);
e = array_internal_at(x, n);
switch (s->type) { default: abort();
case VTYPE_STRING: init = (void*)string_copy_init; break;
case VTYPE_ARRAY: init = (void*) array_copy_init; break;
case VTYPE_LIST: init = (void*) list_copy_init; break;
case VTYPE_MAP: init = (void*) map_copy_init; break;
case VTYPE_SET: init = (void*) vset_copy_init; break;
}
p = x->mem;
v = array_internal_at(s, i);
e = array_internal_at(x, n);
init = get_type_initializer(s->type);
do {
init(p, v);

View File

@ -3,142 +3,61 @@
#include "include.h"
#define dtree_duplicate(s) rbtree_duplicate((rbnode_t*)s, (void*)dnode_duplicate, nullptr)
#define dtree_compare(s0, s1) rbtree_compare((void*)s0, (void*)s1, (void*)dnode_compare, nullptr)
static dnode_t* dnode_duplicate(const dnode_t* s, dnode_t* p, void* not_used) {
dnode_t* x;
x = dnode_create(vnode_duplicate(&s->key, s->key_type), p, s->colored);
x->key_type = s->key_type;
x->val_type = s->val_type;
x->value = vnode_duplicate(&s->value, s->val_type);
return x;
}
static int dnode_compare(const dnode_t *s0, const dnode_t *s1, void* not_used) {
int c = vnode_compare(&s0->key, s1->key_type, &s1->key, s1->key_type);
return (!c) ? vnode_compare(&s0->value, s1->val_type, &s1->value, s1->val_type) : c;
}
/*#####################################################################################################################*/
static int dict_compare_equal_capacity(const dict_t* s0, const dict_t* s1) {
int c;
for (size_t i = 0; i < s0->capacity; ++i) {
if ((c = dtree_compare(s0->nodes[i], s1->nodes[i]))) {
return c;
}
}
return 0;
}
static int dict_compare_unequal_capacity(const dict_t* s0, const dict_t* s1) {
const dict_t *x, *y;
dnode_t *c0, *c1;
int cmp;
stack_t z;
if (s0->capacity <= s1->capacity) {
x = s0;
y = s1;
} else {
x = s1;
y = s0;
}
z.prev = 0;
z.value = 0;
for (size_t i = 0; i < x->capacity; ++i) {
if (!dnode_is_empty(x->nodes[i]))
stack_push(&z, x->nodes[i]);
}
while ((c0 = stack_pop(&z))) {
c1 = y->nodes[vnode_hash(c0->key, c0->key_type) / y->capacity];
cmp = 1;
while (!dnode_is_empty(c1)) {
cmp = vnode_compare(c0->key, c0->key_type, c1->key, c1->key_type);
if (cmp == 0) break;
c1 = (cmp < 0) ? c1->left : c1->right;
}
if (cmp) return x == s0 ? cmp : ~cmp + 1;
if (!dnode_is_empty(c0->right)) stack_push(&z, c0->right);
if (!dnode_is_empty(c0->left)) stack_push(&z, c0->left);
}
return 0;
}
/*#####################################################################################################################*/
hash_t dict_hash(const dict_t* s) {
dnode_t *l, *r;
hash_t hash;
dnode_t *min, *max;
size_t i;
dnode_t *c;
hash_t hash;
if (!s->size) return 0;
if (!s->size)
return 0;
l = dnode_empty;
r = dnode_empty;
min = max = nullptr;
i = s->capacity;
for (size_t i = 0; i < s->capacity; ++i) {
if (!dnode_is_empty(s->nodes[i])) {
if (dnode_is_empty(l) || vnode_compare(s->nodes[i]->key, s->nodes[i]->key_type, l->key, l->key_type) < 0) {
l = s->nodes[i];
}
while (i--) {
c = s->nodes[i];
if (dnode_is_empty(r) || vnode_compare(s->nodes[i]->key, s->nodes[i]->key_type, r->key, r->key_type) > 0) {
r = s->nodes[i];
}
while (!is_null(c)) {
if (is_null(min) || vnode_compare(&c->key, c->key_type, &min->key, min->key_type) < 0) min = c;
if (is_null(max) || vnode_compare(&c->key, c->key_type, &max->key, max->key_type) > 0) max = c;
c = c->prev;
}
}
while (!dnode_is_empty(l->left))
l = l->left;
hash = vnode_hash(&min->key, min->key_type);
while (!dnode_is_empty(r->right))
r = r->right;
hash = vnode_hash(l->key, l->key_type) + vnode_hash(l->value, l->val_type);
if (l != r) hash += vnode_hash(r->key, r->key_type) + vnode_hash(r->value, r->val_type);
if (s->size > 0)
hash += vnode_hash(&max->key, max->key_type);
return (hash ^ s->size) + VTYPE_DICT;
}
void dict_init(dict_t* x) {
memset(x, 0, sizeof(*x));
}
/*#####################################################################################################################*/
void dict_free(dict_t* x) {
for (size_t i = 0; i < x->capacity; ++i)
rbtree_free(x->nodes[i], (void*)dnode_free, nullptr);
while (x->capacity--) {
while (!is_null(x->nodes[x->capacity])) {
vnode_free(&x->nodes[x->capacity]->key, x->nodes[x->capacity]->key_type);
vnode_free(&x->nodes[x->capacity]->value, x->nodes[x->capacity]->value_type);
x->nodes[x->capacity] = x->nodes[x->capacity]->prev;
}
}
free(x->nodes);
memset(x, 0, sizeof(*x));
}
void libcdcb_dnode_free(dnode_t* x, void* not_used) {
vnode_free(&x->key, x->key_type);
vnode_free(&x->value, x->val_type);
}
/*#####################################################################################################################*/
size_t dict_size(const dict_t* x) {
@ -152,6 +71,9 @@ size_t dict_capacity(const dict_t* x) {
/*#####################################################################################################################*/
int dict_compare(const dict_t* s0, const dict_t* s1) {
dnode_t *c0, *c1;
size_t i;
int cmp;
if (s0 == s1)
return 0;
@ -159,48 +81,31 @@ int dict_compare(const dict_t* s0, const dict_t* s1) {
if (s0->size != s1->size)
return s0->size < s1->size ? -1 : 1;
if (s0->capacity == s1->capacity)
return dict_compare_equal_capacity(s0, s1);
i = s0->capacity;
return dict_compare_unequal_capacity(s0, s1);
}
while (i--) {
c0 = s0->nodes[i];
/*#####################################################################################################################*/
while (!is_null(c0)) {
dict_t dict_copy(const dict_t* s) {
dict_t x;
c1 = s1->nodes[vnode_hash(&c0->key, c0->key_type) % s1->capacity];
cmp = -1;
x.capacity = s->capacity;
x.size = s->size;
x.nodes = malloc(x.size * sizeof(*x.nodes));
while (!is_null(c1)) {
if ((cmp = vnode_compare(&c0->key, c0->key_type, &c1->key, c1->key_type) == 0)) {
for (size_t i = 0; i < x.capacity; ++i) {
x.nodes[i] = dtree_duplicate(s->nodes[i]);
cmp = vnode_compare(&c0->value, c0->value_type, &c1->value, c1->value_type);
break;
}
c1 = c1->prev;
}
if (cmp) return cmp;
c0 = c0->prev;
}
}
return x;
}
dict_t* dict_duplicate(const dict_t* s) {
dict_t *x = malloc(sizeof(*x));
x->capacity = s->capacity;
x->size = s->size;
x->nodes = malloc(x->size * sizeof(*x->nodes));
for (size_t i = 0; i < x->capacity; ++i) {
x->nodes[i] = dtree_duplicate(s->nodes[i]);
}
return x;
}
void dict_copy_init(dict_t* x, const dict_t* s) {
x->capacity = s->capacity;
x->size = s->size;
x->nodes = malloc(x->size * sizeof(*x->nodes));
for (size_t i = 0; i < x->capacity; ++i) {
x->nodes[i] = dtree_duplicate(s->nodes[i]);
}
return 0;
}

82
src/dict/copy.c Normal file
View File

@ -0,0 +1,82 @@
/* This software is licensed by the MIT License, see LICENSE file */
/* Copyright © 2022 Gregory Lirent */
#include "include.h"
/*#####################################################################################################################*/
static inline dnode_t* dnode_duplicate(const dnode_t* s, dnode_t* p) {
dnode_t* x = malloc(sizeof(*x));
x->prev = p;
x->key = vnode_duplicate(&s->key, s->key_type);
x->value = vnode_duplicate(&s->value, s->value_type);
x->key_type = s->key_type;
x->value_type = s->value_type;
return x;
}
/*#####################################################################################################################*/
dict_t dict_copy(const dict_t* s) {
dict_t x;
size_t i;
dnode_t *n;
x.capacity = i = s->capacity;
x.size = s->size;
x.nodes = calloc(x.capacity, sizeof(*x.nodes));
while (i--) {
n = s->nodes[i];
while (!is_null(n)) {
x.nodes[i] = dnode_duplicate(n, x.nodes[i]);
n = n->prev;
}
}
return x;
}
dict_t* dict_duplicate(const dict_t* s) {
dict_t *x = malloc(sizeof(*x));
size_t i;
dnode_t *n;
x->capacity = i = s->capacity;
x->size = s->size;
x->nodes = calloc(x->capacity, sizeof(*x->nodes));
while (i--) {
n = s->nodes[i];
while (!is_null(n)) {
x->nodes[i] = dnode_duplicate(n, x->nodes[i]);
n = n->prev;
}
}
return x;
}
void dict_copy_init(dict_t* x, const dict_t* s) {
size_t i;
dnode_t *n;
x->capacity = i = s->capacity;
x->size = s->size;
x->nodes = calloc(x->capacity, sizeof(*x->nodes));
while (i--) {
n = s->nodes[i];
while (!is_null(n)) {
x->nodes[i] = dnode_duplicate(n, x->nodes[i]);
n = n->prev;
}
}
}

View File

@ -6,72 +6,28 @@
/*#####################################################################################################################*/
static void dict_rehash(dict_t* s, size_t capacity) {
stack_t z;
int cmp;
size_t index;
dnode_t *c, *p, *n;
dnode_t **nodes, *c, *n, **p;
size_t i;
dnode_t **nodes = calloc(capacity, sizeof(*nodes));
i = s->capacity;
nodes = calloc(sizeof(*nodes), capacity);
z.prev = 0;
z.value = 0;
index = s->capacity;
while (i--) {
c = s->nodes[i];
while (index--) {
if (!dnode_is_empty(s->nodes[index]))
stack_push(&z, s->nodes[index]);
}
while (!is_null(c)) {
p = nodes + (vnode_hash(&c->key, c->key_type) % capacity);
n = c->prev;
c->prev = *p;
while ((c = stack_pop(&z))) {
if (!dnode_is_empty(c->right)) {
stack_push(&z, c->right);
c->right = dnode_empty;
}
if (!dnode_is_empty(c->left)) {
stack_push(&z, c->left);
c->left = dnode_empty;
}
index = vnode_hash(&c->key, c->key_type) % capacity;
n = nodes[index];
if (!is_null(nodes[index])) {
do {
p = n;
cmp = vnode_compare(&c->key, c->key_type, &n->key, n->key_type);
n = (cmp <= 0) ? n->left : n->right;
} while (!dnode_is_empty(n));
if (cmp < 0) p->left = c;
else p->right = c;
c->parent = p;
c->colored = 1;
if (!dnode_is_root(p))
dnode_fixup(nodes + index, n);
} else {
nodes[index] = c;
c->colored = 0;
c->parent = dnode_empty;
*p = c;
c = n;
}
}
free(s->nodes);
s->nodes = nodes;
if (capacity > s->capacity) {
s->capacity = capacity;
while (capacity--) {
if (is_null(*nodes))
*nodes = dnode_empty;
++nodes;
}
} else s->capacity = capacity;
s->capacity = capacity;
}
/*#####################################################################################################################*/
@ -96,86 +52,62 @@ bool libcdsb_dict_shrink_to_fit(dict_t* s) {
bool libcdsb_dict_update(dict_t* x, const void* k, vtype kt, const void* v, vtype vt) {
dnode_t *n, *p;
vnode_t kn, vn;
int cmp;
size_t index;
dnode_t *c, **p;
if (!x->capacity || (double)x->size / x->capacity > REBUILD_POINT_MAX)
dict_rehash(x, x->capacity + CAPACITY_BLOCK);
index = vtype_hash(k, kt) % x->capacity;
n = x->nodes[index];
kn = vnode_create(k, kt);
vn = vnode_create(v, vt);
c = *(p = x->nodes + (vtype_hash(k, kt) % x->capacity));
if (!dnode_is_empty(n)) {
do {
p = n;
cmp = vtype_compare(k, kt, vnode_peek(&n->key, n->key_type), n->key_type);
while (!is_null(c)) {
if (vtype_compare(k, kt, vnode_peek(&c->key, c->key_type), c->key_type) == 0) {
vnode_free(&c->value, c->value_type);
if (cmp == 0) {
dnode_free(n, nullptr);
c->value = vnode_create(v, vt);
c->value_type = vt;
n->key = kn;
n->value = vn;
n->key_type = kt;
n->val_type = vt;
return true;
} else c = c->prev;
}
return true;
}
c = malloc(sizeof(*c));
n = (cmp < 0) ? n->left : n->right;
} while (!dnode_is_empty(n));
n = dnode_create(kn, p, 1);
if (cmp < 0) p->left = n;
else p->right = n;
if (!dnode_is_root(p))
dnode_fixup(x->nodes + index, n);
} else x->nodes[index] = n = dnode_create(kn, dnode_empty, 0);
n->value = vn;
n->key_type = kt;
n->val_type = vt;
c->prev = *p;
c->key = vnode_create(k, kt);
c->value = vnode_create(v, vt);
c->key_type = kt;
c->value_type = vt;
*p = c;
++x->size;
return false;
}
int libcdsb_dict_get(dict_t* x, const void* k, vtype t, void* _, dict_access_callback callback, bool cut) {
dnode_t *c;
void* key;
int cmp;
size_t index;
int libcdsb_dict_find(dict_t* x, const void* k, vtype t, void* dt, dict_access_callback callback, bool cut) {
dnode_t *c, **p;
int r;
void* key;
if (x->capacity) {
index = vtype_hash(k, t) % x->capacity;
c = x->nodes[index];
c = *(p = x->nodes + (vtype_hash(k, t) % x->capacity));
while (!dnode_is_empty(c)) {
while (!is_null(c)) {
key = vnode_peek(&c->key, c->key_type);
cmp = vtype_compare(k, t, key, c->key_type);
if (cmp == 0) {
cmp = (callback) ? callback(key, c->key_type, vnode_peek(&c->value, c->val_type), c->val_type, _) : 0;
if (vtype_compare(k, t, key, c->key_type) == 0) {
r = (callback) ? callback(key, c->key_type, vnode_peek(&c->value, c->value_type), c->value_type, dt) : 0;
if (cut) {
c = dnode_delete(x->nodes + index, c);
dnode_free(c, nullptr);
*p = c->prev;
vnode_free(&c->key, c->key_type);
vnode_free(&c->value, c->value_type);
free(c);
--x->size;
}
return cmp;
} else c = (cmp < 0) ? c->left : c->right;
return r;
} else c = *(p = &c->prev);
}
}
@ -184,49 +116,54 @@ int libcdsb_dict_get(dict_t* x, const void* k, vtype t, void* _, dict_access_cal
int libcdsb_dict_foreach(dict_t* x, void* dt, dict_access_callback callback, bool flush) {
stack_t z;
int r;
dnode_t* c;
dnode_t *c;
ssize_t i;
int r;
r = 0;
z.prev = 0;
z.value = 0;
r = 0;
i = x->capacity;
for (size_t i = 0; i < x->capacity; ++i) {
if (!dnode_is_empty(x->nodes[i]))
stack_push(&z, x->nodes[i]);
}
while (i) {
c = x->nodes[--i];
while ((c = stack_pop(&z))) {
void* k = vnode_peek(&c->key, c->key_type);
void* v = vnode_peek(&c->value, c->val_type);
while (!is_null(c)) {
r = callback(vnode_peek(&c->key, c->key_type), c->key_type,
vnode_peek(&c->value, c->value_type), c->value_type, dt);
if ((r = callback(k, c->key_type, v, c->val_type, dt)))
break;
c = c->prev;
if (!dnode_is_empty(c->right)) stack_push(&z, c->right);
if (!dnode_is_empty(c->left)) stack_push(&z, c->left);
if (r) {
if (!flush) goto end_;
else goto flush_loop_;
} else if (flush) {
vnode_free(&x->nodes[i]->key, x->nodes[i]->key_type);
vnode_free(&x->nodes[i]->value, x->nodes[i]->value_type);
free(x->nodes[i]);
if (flush) {
dnode_free(c, nullptr);
free(c);
x->nodes[i] = c;
}
}
}
if (flush) {
while (c) {
if (!dnode_is_empty(c->right)) stack_push(&z, c->right);
if (!dnode_is_empty(c->left)) stack_push(&z, c->left);
while (i) {
--i;
dnode_free(c, nullptr);
free(c);
while (!is_null(x->nodes[i])) { flush_loop_:
vnode_free(&x->nodes[i]->key, x->nodes[i]->key_type);
vnode_free(&x->nodes[i]->value, x->nodes[i]->value_type);
c = stack_pop(&z);
c = x->nodes[i]->prev;
free(x->nodes[i]);
x->nodes[i] = c;
}
}
free(x->nodes);
memset(x, 0, sizeof(*x));
} else stack_flush(&z);
}
end_:
return r;
}

View File

@ -3,26 +3,26 @@
#include "include.h"
int libcdsb_dict_get_by_pointer(dict_t* x, const void* k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_get(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_get_by_cstring(dict_t* x, const char* k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_get(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_get_by_string (dict_t* x, const str_t* k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_get(x, k, vtypeof( k), _, cb, cut); }
int libcdsb_dict_get_by_array (dict_t* x, const arr_t* k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_get(x, k, vtypeof( k), _, cb, cut); }
int libcdsb_dict_get_by_list (dict_t* x, const list_t* k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_get(x, k, vtypeof( k), _, cb, cut); }
int libcdsb_dict_get_by_map (dict_t* x, const map_t* k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_get(x, k, vtypeof( k), _, cb, cut); }
int libcdsb_dict_get_by_vset (dict_t* x, const set_t* k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_get(x, k, vtypeof( k), _, cb, cut); }
int libcdsb_dict_get_by_dict (dict_t* x, const dict_t* k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_get(x, k, vtypeof( k), _, cb, cut); }
int libcdsb_dict_get_by_boolean(dict_t* x, bool k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_get(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_get_by_int8 (dict_t* x, s8_t k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_get(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_get_by_int16 (dict_t* x, s16_t k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_get(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_get_by_int32 (dict_t* x, s32_t k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_get(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_get_by_int64 (dict_t* x, s64_t k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_get(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_get_by_uint8 (dict_t* x, u8_t k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_get(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_get_by_uint16 (dict_t* x, u16_t k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_get(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_get_by_uint32 (dict_t* x, u32_t k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_get(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_get_by_uint64 (dict_t* x, u64_t k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_get(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_get_by_float (dict_t* x, fl_t k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_get(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_get_by_double (dict_t* x, dbl_t k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_get(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_get_by_ldouble(dict_t* x, ldbl_t k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_get(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_find_by_pointer(dict_t* x, const void* k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_find(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_find_by_cstring(dict_t* x, const char* k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_find(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_find_by_string (dict_t* x, const str_t* k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_find(x, k, vtypeof( k), _, cb, cut); }
int libcdsb_dict_find_by_array (dict_t* x, const arr_t* k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_find(x, k, vtypeof( k), _, cb, cut); }
int libcdsb_dict_find_by_list (dict_t* x, const list_t* k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_find(x, k, vtypeof( k), _, cb, cut); }
int libcdsb_dict_find_by_map (dict_t* x, const map_t* k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_find(x, k, vtypeof( k), _, cb, cut); }
int libcdsb_dict_find_by_vset (dict_t* x, const set_t* k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_find(x, k, vtypeof( k), _, cb, cut); }
int libcdsb_dict_find_by_dict (dict_t* x, const dict_t* k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_find(x, k, vtypeof( k), _, cb, cut); }
int libcdsb_dict_find_by_boolean(dict_t* x, bool k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_find(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_find_by_int8 (dict_t* x, s8_t k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_find(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_find_by_int16 (dict_t* x, s16_t k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_find(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_find_by_int32 (dict_t* x, s32_t k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_find(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_find_by_int64 (dict_t* x, s64_t k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_find(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_find_by_uint8 (dict_t* x, u8_t k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_find(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_find_by_uint16 (dict_t* x, u16_t k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_find(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_find_by_uint32 (dict_t* x, u32_t k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_find(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_find_by_uint64 (dict_t* x, u64_t k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_find(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_find_by_float (dict_t* x, fl_t k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_find(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_find_by_double (dict_t* x, dbl_t k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_find(x, &k, vtypeof(&k), _, cb, cut); }
int libcdsb_dict_find_by_ldouble(dict_t* x, ldbl_t k, void* _, dict_access_callback cb, bool cut) { return libcdsb_dict_find(x, &k, vtypeof(&k), _, cb, cut); }
bool libcdsb_dict_update_pointer_pointer(dict_t* x, const void* k, const void* v) { return libcdsb_dict_update(x, &k, vtypeof(&k), &v, vtypeof(&v)); }
bool libcdsb_dict_update_pointer_cstring(dict_t* x, const void* k, const char* v) { return libcdsb_dict_update(x, &k, vtypeof(&k), &v, vtypeof(&v)); }

View File

@ -15,34 +15,16 @@
#endif
#define REBUILD_POINT_MAX 0.65
typedef struct libcdsb_dict_node {
struct libcdsb_dict_node* left;
struct libcdsb_dict_node* right;
struct libcdsb_dict_node* parent;
struct libcdsb_dict_node* prev;
vnode_t key;
short colored;
u8_t key_type;
u8_t val_type;
vnode_t value;
u16_t key_type;
u16_t value_type;
} dnode_t;
static_assert(offsetof(struct libcdsb_rbtree_node, left) == offsetof(struct libcdsb_dict_node, left), "Implementation assert");
static_assert(offsetof(struct libcdsb_rbtree_node, right) == offsetof(struct libcdsb_dict_node, right), "Implementation assert");
static_assert(offsetof(struct libcdsb_rbtree_node, parent) == offsetof(struct libcdsb_dict_node, parent), "Implementation assert");
static_assert(offsetof(struct libcdsb_rbtree_node, colored) == offsetof(struct libcdsb_dict_node, colored), "Implementation assert");
static_assert(offsetof(struct libcdsb_rbtree_node, value) == offsetof(struct libcdsb_dict_node, key), "Implementation assert");
#define dnode_empty ((dnode_t*)LIBCDSB_RBTREE_NODE_EMPTY)
#define dnode_create(k, p, c) ((dnode_t*)libcdsb_rbtree_node_create(k, (rbnode_t*)p, c, sizeof(dnode_t)))
#define dnode_fixup(r, n) libcdsb_rbtree_node_fixup((rbnode_t**)(r), (rbnode_t*)(n))
#define dnode_delete(r, n) (dnode_t*)libcdsb_rbtree_node_delete((rbnode_t**)(r), (rbnode_t*)(n))
#define dnode_is_empty(n) ((n) == dnode_empty)
#define dnode_is_root(n) dnode_is_empty((n)->parent)
extern void libcdcb_dnode_free(dnode_t* x, void* not_used);
#define dnode_free libcdcb_dnode_free
#endif /* LIBCDSB_SRC_MAP_INCLUDE_H */
#endif /* LIBCDSB_SRC_DICT_INCLUDE_H */

View File

@ -8,6 +8,7 @@
#undef malloc
#undef realloc
#undef calloc
#undef free
void* libcdsb_aalloc(size_t a, size_t n) {
void* x;
@ -73,3 +74,7 @@ char* libcdsb_strndup(const char* s, size_t n) {
}
abort();
}
void libcdsb_free(void* s) {
free(s);
}

View File

@ -1,9 +1,11 @@
/* This software is licensed by the MIT License, see LICENSE file */
/* Copyright © 2022 Gregory Lirent */
#include <stdarg.h>
#include <stdlib.h>
#include "__internal/include.h"
#undef malloc
#undef free
void libcdsb_stack_init(stack_t* x) {
memset(x, 0, sizeof(*x));
@ -25,6 +27,31 @@ void libcdsb_stack_push(stack_t* x, void* value) {
x->value = value;
}
void libcdsb_stack_push_many(stack_t* x, size_t c, ...) {
va_list args;
stack_t* n;
va_start(args, c);
if (c) {
if (!x->value) {
x->value = va_arg(args, void*);
--c;
}
while (c--) {
if (!(n = malloc(sizeof(*n))))
abort();
n->prev = x->prev;
n->value = x->value;
x->prev = n;
}
}
va_end(args);
}
void* libcdsb_stack_pop(stack_t* x) {
stack_t* n;

View File

@ -3,89 +3,158 @@
#include "include.h"
#define mtree_duplicate(s, t) rbtree_duplicate((rbnode_t*)s, (void*)mnode_duplicate, t)
#define mtree_compare(s0, s1, t) rbtree_compare((void*)s0, (void*)s1, (void*)mnode_compare, (void*)t)
/*#####################################################################################################################*/
static mnode_t* mnode_duplicate(const mnode_t* s, mnode_t* p, const vtype* t) {
mnode_t* x;
x = mnode_create(vnode_duplicate(&s->key, *t), p, s->colored);
x->type = s->type;
x->value = vnode_duplicate(&s->value, s->type);
return x;
}
static int mnode_compare(const mnode_t* s0, const mnode_t* s1, vtype* t) {
int c = vnode_compare_eq(&s0->key, &s1->key, *t);
static inline int mnode_compare(const mnode_t* s0, const mnode_t* s1, vtype t) {
int c = vnode_compare_eq(&s0->key, &s1->key, t);
return !c ? vnode_compare(&s0->value, s0->type, &s1->value, s1->type) : c;
}
static hash_t mnode_hash(const mnode_t* s, vtype* tp) {
vtype t = (!is_null(tp)) ? *tp : VTYPE_POINTER;
return vnode_hash(s->key, t) + vnode_hash(s->value, s->type) + t;
}
void libcdsb_mnode_free(mnode_t* x, vtype* t) {
vnode_free(&x->key, *t);
vnode_free(&x->value, x->type);
static inline hash_t mnode_hash(const mnode_t* s, vtype t) {
return vnode_hash(&s->key, t) + vnode_hash(&s->value, s->type) + t;
}
/*#####################################################################################################################*/
hash_t map_hash(const map_t* s) {
return rbtree_hash(s->root, (void*)mnode_hash, (void*)&s->type) + VTYPE_MAP;
mnode_t *c0, *c1;
hash_t hash, v;
stack_t z;
if (mnode_is_empty(s->root)) return 0;
z.prev = 0;
hash = 1;
c1 = s->root;
if (!rbnode_is_empty(z.value = c1->left)) {
do {
c0 = stack_pop(&z);
++hash;
if (!mnode_is_empty(c0->right)) stack_push(&z, c1 = c0->right);
if (!mnode_is_empty(c0->left)) stack_push(&z, c1 = c0->left);
} while (!is_null(z.value));
}
v = mnode_hash(c1, s->type);
c1 = s->root;
if (!rbnode_is_empty(z.value = c1->right)) {
do {
c0 = stack_pop(&z);
++hash;
if (!mnode_is_empty(c0->right)) stack_push(&z, c1 = c0->right);
if (!mnode_is_empty(c0->left)) stack_push(&z, c1 = c0->left);
} while (!is_null(z.value));
}
v += mnode_hash(c1, s->type);
return (hash ^ v) + VTYPE_MAP;
}
/*#####################################################################################################################*/
void map_init(map_t* x, vtype t) {
x->root = mnode_empty;
x->type = t;
}
void map_free(map_t* x) {
rbtree_free(x->root, (void*)mnode_free, &x->type);
mnode_t *t, *c;
c = x->root;
while (!mnode_is_empty(x->root)) {
if (!mnode_is_empty(c->left)) {
c = c->left;
} else if (!mnode_is_empty(c->right)) {
c = c->right;
} else if (!mnode_is_root(c)) {
vnode_free(&c->key, x->type);
vnode_free(&c->value, c->type);
t = c;
c = c->parent;
if (t == c->left) c->left = mnode_empty;
else c->right = mnode_empty;
free(t);
} else {
vnode_free(&c->key, x->type);
vnode_free(&c->value, c->type);
x->root = mnode_empty;
}
}
x->root = mnode_empty;
x->type = 0;
}
/*#####################################################################################################################*/
size_t map_size(const map_t* x) {
return rbtree_size(x->root);
stack_t z = { .prev = 0, .value = x->root };
size_t n = 0;
rbnode_t* c;
if (!mnode_is_empty(x->root)) {
while ((c = stack_pop(&z))) {
++n;
if (!rbnode_is_empty(c->right)) stack_push(&z, c->right);
if (!rbnode_is_empty(c->left)) stack_push(&z, c->left);
}
}
return n;
}
/*#####################################################################################################################*/
int map_compare(const map_t* s0, const map_t* s1) {
if (s0 == s1) return 0;
if (s0->type != s1->type) return s0->type - s1->type;
mnode_t *c0, *c1;
stack_t z;
int c = 0;
return mtree_compare(s0->root, s1->root, &s0->type);
}
/*#####################################################################################################################*/
map_t map_copy(const map_t* s) {
map_t x;
x.type = s->type;
x.root = mtree_duplicate(s->root, &x.type);
return x;
}
map_t* map_duplicate(const map_t* s) {
map_t *x = malloc(sizeof(*x));
x->type = s->type;
x->root = mtree_duplicate(s->root, &x->type);
return x;
}
void map_copy_init(map_t* x, const map_t* s) {
x->type = s->type;
x->root = mtree_duplicate(s->root, &x->type);
if (s0 == s1 || s0->root == s1->root)
return 0;
if (s0->type != s1->type)
return s0->type - s1->type;
z.prev = 0;
z.value = 0;
stack_push_many(&z, 2, (void*)s1, (void*)s0);
do {
c0 = stack_pop(&z);
c1 = stack_pop(&z);
if (mnode_is_empty(c0) || mnode_is_empty(c1)) {
if (c0 != c1) {
stack_flush(&z);
return mnode_is_empty(c0) ? -1 : 1;
}
} else if ((c = mnode_compare(c0, c1, s0->type))) {
if (c0->left == c1->right) { // == mnode_empty
c = mnode_compare(c0->right, c1, s0->type);
if (!c) c = mnode_compare(c0, c1->left, s0->type);
} else if (c0->right == c1->left) { // == mnode_empty
c = mnode_compare(c0, c1->right, s0->type);
if (!c) c = mnode_compare(c0->left, c1, s0->type);
}
if (c) {
stack_flush(&z);
return c;
}
} else stack_push_many(&z, 4, c1->right, c0->right, c1->left, c0->left);
} while (!is_null(z.value));
return 0;
}

113
src/map/copy.c Normal file
View File

@ -0,0 +1,113 @@
/* This software is licensed by the MIT License, see LICENSE file */
/* Copyright © 2022 Gregory Lirent */
#include "include.h"
/*#####################################################################################################################*/
static inline mnode_t* mnode_duplicate(const mnode_t* s, mnode_t* p, const vtype t) {
mnode_t* x;
x = mnode_create(vnode_duplicate(&s->key, t), p, s->colored);
x->type = s->type;
x->value = vnode_duplicate(&s->value, s->type);
return x;
}
/*#####################################################################################################################*/
map_t map_copy(const map_t* s) {
map_t x;
stack_t z = { .prev = 0, .value = s->root };
x.type = s->type;
if (!mnode_is_empty(s->root)) {
x.root = mnode_duplicate(s->root, mnode_empty, s->type);
stack_push(&z, x.root);
do {
mnode_t *p0 = stack_pop(&z);
mnode_t *p1 = stack_pop(&z);
if (!mnode_is_empty(p1->left)) {
p0->left = mnode_duplicate(p1->left, p0, s->type);
stack_push_many(&z, 2, p1->left, p0->left);
}
if (!mnode_is_empty(p1->right)) {
p0->right = mnode_duplicate(p1->right, p0, s->type);
stack_push_many(&z, 2, p1->right, p0->right);
}
} while (!is_null(z.value));
} else x.root = mnode_empty;
return x;
}
map_t* map_duplicate(const map_t* s) {
map_t* x = malloc(sizeof(*x));
stack_t z = { .prev = 0, .value = s->root };
x->type = s->type;
if (!mnode_is_empty(s->root)) {
x->root = mnode_duplicate(s->root, mnode_empty, s->type);
stack_push(&z, x->root);
do {
mnode_t *p0 = stack_pop(&z);
mnode_t *p1 = stack_pop(&z);
if (!mnode_is_empty(p1->left)) {
p0->left = mnode_duplicate(p1->left, p0, s->type);
stack_push_many(&z, 2, p1->left, p0->left);
}
if (!mnode_is_empty(p1->right)) {
p0->right = mnode_duplicate(p1->right, p0, s->type);
stack_push_many(&z, 2, p1->right, p0->right);
}
} while (!is_null(z.value));
} else x->root = mnode_empty;
return x;
}
void map_copy_init(map_t* x, const map_t* s) {
stack_t z = { .prev = 0, .value = s->root };
x->type = s->type;
if (!mnode_is_empty(s->root)) {
x->root = mnode_duplicate(s->root, mnode_empty, s->type);
stack_push(&z, x->root);
do {
mnode_t *p0 = stack_pop(&z);
mnode_t *p1 = stack_pop(&z);
if (!mnode_is_empty(p1->left)) {
p0->left = mnode_duplicate(p1->left, p0, s->type);
stack_push_many(&z, 2, p1->left, p0->left);
}
if (!mnode_is_empty(p1->right)) {
p0->right = mnode_duplicate(p1->right, p0, s->type);
stack_push_many(&z, 2, p1->right, p0->right);
}
} while (!is_null(z.value));
} else x->root = mnode_empty;
}

View File

@ -20,7 +20,8 @@ bool libcdsb_map_update(map_t* x, const void* k, vtype kt, const void* v, vtype
cmp = vtype_compare(k, kt, vnode_peek(&n->key, kt), kt);
if (cmp == 0) {
mnode_free(n, &kt);
vnode_free(&n->key, x->type);
vnode_free(&n->value, n->type);
n->key = kn;
n->value = vnode_create(v, vt);
@ -65,7 +66,8 @@ int libcdsb_map_find(map_t* x, const void* k, vtype t, void* _, map_access_callb
if (cut) {
c = mnode_delete(&x->root, c);
mnode_free(c, &x->type);
vnode_free(&c->key, x->type);
vnode_free(&c->value, c->type);
free(c);
}
@ -92,7 +94,8 @@ int libcdsb_map_foreach(map_t* x, void* dt, map_access_callback callback, bool f
if (!mnode_is_empty(c->left)) stack_push(&z, c->left);
if (flush) {
mnode_free(c, &x->type);
vnode_free(&c->key, x->type);
vnode_free(&c->value, c->type);
free(c);
}
}
@ -102,7 +105,8 @@ int libcdsb_map_foreach(map_t* x, void* dt, map_access_callback callback, bool f
if (!mnode_is_empty(c->right)) stack_push(&z, c->right);
if (!mnode_is_empty(c->left)) stack_push(&z, c->left);
mnode_free(c, &x->type);
vnode_free(&c->key, x->type);
vnode_free(&c->value, c->type);
free(c);
c = stack_pop(&z);

View File

@ -28,8 +28,6 @@ static_assert(offsetof(struct libcdsb_rbtree_node, value) == offsetof(struct lib
static_assert(offsetof(struct libcdsb_set, root) == offsetof(struct libcdsb_map, root), "Implementation assert");
static_assert(offsetof(struct libcdsb_set, type) == offsetof(struct libcdsb_map, type), "Implementation assert");
extern void libcdsb_mnode_free(mnode_t* x, vtype* t);
#define mnode_empty ((mnode_t*)LIBCDSB_RBTREE_NODE_EMPTY)
#define mnode_create(k, p, c) ((mnode_t*)libcdsb_rbtree_node_create(k, (rbnode_t*)p, c, sizeof(mnode_t)))
#define mnode_fixup(r, n) libcdsb_rbtree_node_fixup((rbnode_t**)(r), (rbnode_t*)(n))
@ -38,6 +36,4 @@ extern void libcdsb_mnode_free(mnode_t* x, vtype* t);
#define mnode_is_empty(n) ((n) == mnode_empty)
#define mnode_is_root(n) mnode_is_empty((n)->parent)
#define mnode_free libcdsb_mnode_free
#endif /* LIBCDSB_SRC_MAP_INCLUDE_H */

View File

@ -1,206 +0,0 @@
/* This software is licensed by the MIT License, see LICENSE file */
/* Copyright © 2022 Gregory Lirent */
#include "__internal/rbtree.h"
/*#####################################################################################################################*/
static rbnode_t* rbnode_duplicate(const rbnode_t* s, rbnode_t* p, const vtype* info) {
return rbnode_create(vnode_duplicate(&s->value, (info) ? *info : VTYPE_POINTER), p, s->colored);
}
static int rbnode_compare(const rbnode_t* s0, const rbnode_t* s1, vtype* tp) {
vtype t = !is_null(tp) ? *tp : VTYPE_POINTER;
return vnode_compare(s0->value, t, s1->value, t);
}
static hash_t rbnode_hash(const rbnode_t* s, vtype* tp) {
vtype t = (!is_null(tp)) ? *tp : VTYPE_POINTER;
return vnode_hash(s->value, t);
}
static void rbnode_free(rbnode_t* x, vtype *t) {
if (!is_null(t)) vnode_free(&x->value, *t);
}
/*#####################################################################################################################*/
hash_t libcdsb_rbtree_hash(const void* s, hash_t (*node_hash)(const void* s, void* info), void* info) {
rbnode_t *c0, *c1;
hash_t hash, v;
stack_t z;
if (rbnode_is_empty(s)) return 0;
if (is_null(node_hash)) node_hash = (void*)rbnode_hash;
z.prev = 0;
hash = 1;
c1 = (void*)s;
if (!rbnode_is_empty(z.value = c1->left)) do {
c0 = stack_pop(&z);
++hash;
if (!rbnode_is_empty(c0->left))
stack_push(&z, c1 = c0->left);
if (!rbnode_is_empty(c0->right))
stack_push(&z, c0->right);
} while (!is_null(z.value));
v = node_hash(c1, info);
c1 = (void*)s;
if (!rbnode_is_empty(z.value = c1->right)) do {
c0 = stack_pop(&z);
++hash;
if (!rbnode_is_empty(c0->left))
stack_push(&z, c1 = c0->left);
if (!rbnode_is_empty(c0->right))
stack_push(&z, c0->right);
} while (!is_null(z.value));
v += node_hash(c1, info);
return hash ^ v;
}
/*#####################################################################################################################*/
void* libcdsb_rbtree_duplicate(const rbnode_t* s, void* (*node_duplicate)(void* src, void* parent, void* info), void* info) {
rbnode_t *p0, *p1, *x;
stack_t z;
z.prev = 0;
z.value = (void*)s;
if (is_null(node_duplicate)) {
node_duplicate = (void*)rbnode_duplicate;
}
if (!rbnode_is_empty(s)) {
x = node_duplicate(z.value, rbnode_empty, info);
stack_push(&z, x);
do {
p0 = stack_pop(&z);
p1 = stack_pop(&z);
if (!rbnode_is_empty(p1->left)) {
p0->left = node_duplicate(p1->left, p0, info);
stack_push(&z, p1->left);
stack_push(&z, p0->left);
}
if (!rbnode_is_empty(p1->right)) {
p0->right = node_duplicate(p1->right, p0, info);
stack_push(&z, p1->right);
stack_push(&z, p0->right);
}
} while (!is_null(z.value));
} else x = rbnode_empty;
return x;
}
/*#####################################################################################################################*/
int libcdsb_rbtree_compare(const rbnode_t* s0, const rbnode_t* s1, int (*node_compare)(const rbnode_t* s0, const rbnode_t* s1, void* info), void* info) {
rbnode_t *c0, *c1;
stack_t z;
int c = 0;
if (s0 == s1) return 0;
if (is_null(node_compare)) node_compare = (void*)rbnode_compare;
z.prev = 0;
z.value = 0;
stack_push(&z, (void*)s1);
stack_push(&z, (void*)s0);
do {
c0 = stack_pop(&z);
c1 = stack_pop(&z);
if (rbnode_is_empty(c0) || rbnode_is_empty(c1)) {
if (c0 != c1) {
stack_flush(&z);
return rbnode_is_empty(c0) ? -1 : 1;
}
} else if ((c = node_compare(c0, c1, info))) {
if (c0->left == c1->right) { // <-- rbnode_empty
c = node_compare(c0->right, c1, info);
if (!c) c = node_compare(c0, c1->left, info);
} else if (c0->right == c1->left) { // <-- rbnode_empty
c = node_compare(c0, c1->right, info);
if (!c) c = node_compare(c0->left, c1, info);
}
if (c) {
stack_flush(&z);
return c;
}
} else {
stack_push(&z, c1->right);
stack_push(&z, c0->right);
stack_push(&z, c1->left);
stack_push(&z, c0->left);
}
} while (!is_null(z.value));
return 0;
}
size_t libcdsb_rbtree_size(const void* s) {
stack_t z = { .prev = 0, .value = (void*)s };
size_t n = 0;
rbnode_t* c;
if (!rbnode_is_empty(s)) {
while ((c = stack_pop(&z))) {
++n;
if (!rbnode_is_empty(c->left))
stack_push(&z, c->left);
if (!rbnode_is_empty(c->right))
stack_push(&z, c->right);
}
}
return n;
}
void libcdsb_rbtree_free(void* x, void (*node_free)(void* x, void* info), void* info) {
rbnode_t *t, *c;
c = x;
if (is_null(node_free)) node_free = (void*)rbnode_free;
while (!rbnode_is_empty(x)) {
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)) {
node_free(c, info);
t = c;
c = c->parent;
if (t == c->left) c->left = rbnode_empty;
else c->right = rbnode_empty;
free(t);
} else {
node_free(c, info);
x = rbnode_empty;
}
}
}

View File

@ -6,10 +6,58 @@
/*#####################################################################################################################*/
hash_t vset_hash(const set_t* s) {
return rbtree_hash(s->root, nullptr, (void*)&s->type) + VTYPE_SET;
static inline int rbnode_compare(const rbnode_t* s0, const rbnode_t* s1, vtype t) {
return vnode_compare(s0->value, t, s1->value, t);
}
static inline hash_t rbnode_hash(const rbnode_t* s, vtype t) {
return vnode_hash(&s->value, t);
}
/*#####################################################################################################################*/
hash_t vset_hash(const set_t* s) {
rbnode_t *c0, *c1;
hash_t hash, v;
stack_t z;
if (rbnode_is_empty(s->root)) return 0;
z.prev = 0;
hash = 1;
c1 = s->root;
if (!rbnode_is_empty(z.value = c1->left)) {
do {
c0 = stack_pop(&z);
++hash;
if (!rbnode_is_empty(c0->right)) stack_push(&z, c1 = c0->right);
if (!rbnode_is_empty(c0->left)) stack_push(&z, c1 = c0->left);
} while (!is_null(z.value));
}
v = rbnode_hash(c1, s->type);
c1 = s->root;
if (!rbnode_is_empty(z.value = c1->right)) {
do {
c0 = stack_pop(&z);
++hash;
if (!rbnode_is_empty(c0->right)) stack_push(&z, c1 = c0->right);
if (!rbnode_is_empty(c0->left)) stack_push(&z, c1 = c0->left);
} while (!is_null(z.value));
}
v += rbnode_hash(c1, s->type);
return (hash ^ v) + VTYPE_SET;
}
/*#####################################################################################################################*/
void vset_init(set_t* x, vtype t) {
x->root = rbnode_empty;
x->type = t;
@ -17,48 +65,94 @@ void vset_init(set_t* x, vtype t) {
void vset_free(set_t* x) {
rbtree_free(x->root, nullptr, &x->type);
rbnode_t *t, *c;
c = x->root;
while (!rbnode_is_empty(x->root)) {
if (!rbnode_is_empty(c->left)) {
c = c->left;
} else if (!rbnode_is_empty(c->right)) {
c = c->right;
} else if (!rbnode_is_root(c)) {
vnode_free(&c->value, x->type);
t = c;
c = c->parent;
if (t == c->left) c->left = rbnode_empty;
else c->right = rbnode_empty;
free(t);
} else {
vnode_free(&c->value, x->type);
x->root = rbnode_empty;
}
}
x->root = rbnode_empty;
x->type = 0;
}
/*#####################################################################################################################*/
size_t vset_size(const set_t* x) {
return rbtree_size(x->root);
stack_t z = { .prev = 0, .value = x->root };
size_t n = 0;
rbnode_t* c;
if (!rbnode_is_empty(x->root)) {
while ((c = stack_pop(&z))) {
++n;
if (!rbnode_is_empty(c->right)) stack_push(&z, c->right);
if (!rbnode_is_empty(c->left)) stack_push(&z, c->left);
}
}
return n;
}
/*#####################################################################################################################*/
int vset_compare(const set_t* s0, const set_t* s1) {
if (s0 == s1) return 0;
if (s0->type != s1->type) return s0->type - s1->type;
rbnode_t *c0, *c1;
stack_t z;
int c = 0;
return rbtree_compare(s0->root, s1->root, nullptr, (void*)&s0->type);
}
/*#####################################################################################################################*/
set_t vset_copy(const set_t* s) {
set_t x;
x.type = s->type;
x.root = rbtree_duplicate(s->root, nullptr, &x.type);
return x;
}
set_t* vset_duplicate(const set_t* s) {
set_t *x = malloc(sizeof(*x));
x->type = s->type;
x->root = rbtree_duplicate(s->root, nullptr, &x->type);
return x;
}
void vset_copy_init(set_t* x, const set_t* s) {
x->type = s->type;
x->root = rbtree_duplicate(s->root, nullptr, &x->type);
if (s0 == s1 || s0->root == s1->root)
return 0;
if (s0->type != s1->type)
return s0->type - s1->type;
z.prev = 0;
z.value = 0;
stack_push_many(&z, 2, (void*)s1, (void*)s0);
do {
c0 = stack_pop(&z);
c1 = stack_pop(&z);
if (rbnode_is_empty(c0) || rbnode_is_empty(c1)) {
if (c0 != c1) {
stack_flush(&z);
return rbnode_is_empty(c0) ? -1 : 1;
}
} else if ((c = rbnode_compare(c0, c1, s0->type))) {
if (c0->left == c1->right) { // == rbnode_empty
c = rbnode_compare(c0->right, c1, s0->type);
if (!c) c = rbnode_compare(c0, c1->left, s0->type);
} else if (c0->right == c1->left) { // == rbnode_empty
c = rbnode_compare(c0, c1->right, s0->type);
if (!c) c = rbnode_compare(c0->left, c1, s0->type);
}
if (c) {
stack_flush(&z);
return c;
}
} else stack_push_many(&z, 4, c1->right, c0->right, c1->left, c0->left);
} while (!is_null(z.value));
return 0;
}

97
src/set/copy.c Normal file
View File

@ -0,0 +1,97 @@
/* This software is licensed by the MIT License, see LICENSE file */
/* Copyright © 2022 Gregory Lirent */
#include "../../include/set.h"
#include "../__internal/rbtree.h"
set_t vset_copy(const set_t* s) {
set_t x = { .type = s->type };
stack_t z = { .prev = 0, .value = s->root };
vtype t = s->type;
if (!rbnode_is_empty(s->root)) {
x.root = rbnode_create(vnode_duplicate(&s->root->value, t), rbnode_empty, 0);
stack_push(&z, x.root);
do {
rbnode_t *p0 = stack_pop(&z);
rbnode_t *p1 = stack_pop(&z);
if (!rbnode_is_empty(p1->left)) {
p0->left = rbnode_create(vnode_duplicate(&p1->left->value, t), p0, p1->left->colored);
stack_push_many(&z, 2, p1->left, p0->left);
}
if (!rbnode_is_empty(p1->right)) {
p0->right = rbnode_create(vnode_duplicate(&p1->right->value, t), p0, p1->right->colored);
stack_push_many(&z, 2, p1->right, p0->right);
}
} while (!is_null(z.value));
} else x.root = rbnode_empty;
return x;
}
set_t* vset_duplicate(const set_t* s) {
set_t* x = malloc(sizeof(*x));
stack_t z = { .prev = 0, .value = s->root };
vtype t = x->type = s->type;
if (!rbnode_is_empty(s->root)) {
x->root = rbnode_create(vnode_duplicate(&s->root->value, t), rbnode_empty, 0);
stack_push(&z, x->root);
do {
rbnode_t *p0 = stack_pop(&z);
rbnode_t *p1 = stack_pop(&z);
if (!rbnode_is_empty(p1->left)) {
p0->left = rbnode_create(vnode_duplicate(&p1->left->value, t), p0, p1->left->colored);
stack_push_many(&z, 2, p1->left, p0->left);
}
if (!rbnode_is_empty(p1->right)) {
p0->right = rbnode_create(vnode_duplicate(&p1->right->value, t), p0, p1->right->colored);
stack_push_many(&z, 2, p1->right, p0->right);
}
} while (!is_null(z.value));
} else x->root = rbnode_empty;
return x;
}
void vset_copy_init(set_t* x, const set_t* s) {
stack_t z = { .prev = 0, .value = s->root };
vtype t = x->type = s->type;
if (!rbnode_is_empty(s->root)) {
x->root = rbnode_create(vnode_duplicate(&s->root->value, t), rbnode_empty, 0);
stack_push(&z, x->root);
do {
rbnode_t *p0 = stack_pop(&z);
rbnode_t *p1 = stack_pop(&z);
if (!rbnode_is_empty(p1->left)) {
p0->left = rbnode_create(vnode_duplicate(&p1->left->value, t), p0, p1->left->colored);
stack_push_many(&z, 2, p1->left, p0->left);
}
if (!rbnode_is_empty(p1->right)) {
p0->right = rbnode_create(vnode_duplicate(&p1->right->value, t), p0, p1->right->colored);
stack_push_many(&z, 2, p1->right, p0->right);
}
} while (!is_null(z.value));
} else x->root = rbnode_empty;
}

View File

@ -200,6 +200,8 @@ size_t string_reverse(str_t* x) {
p = memcpy(p - cs, v, cs);
v += cs;
} else *(--p) = *(v++);
++n;
}
free(x->buffer);

View File

@ -32,31 +32,34 @@ char* string_at(const str_t* s, ssize_t i) {
}
bool string_slice(str_t* x, str_t* s, ssize_t i, size_t c, bool cut) {
size_t string_slice(str_t* x, str_t* s, ssize_t i, size_t c, bool cut) {
char *e, *p, *v;
size_t n = 0;
memset(x, 0, sizeof(*x));
if (!c) return true;
if (!c) return n;
p = string_at(s, i);
if (is_null(p) || (e = p + strlen(p)) > p + c)
return false;
if (is_null(p))
return n;
e = p + strlen(p);
v = p;
do { v = next_char(v); } while (--c && v < e);
while (c-- && v < e) {
v = next_char(v);
++n;
}
if (!c) {
x->buffer = strndup(p, v - p);
x->buffer = strndup(p, v - p);
if (cut) {
memmove(p, v, strlen(v) + 1);
}
if (cut) {
memmove(p, v, strlen(v) + 1);
}
return true;
} else return false;
return n;
}

View File

@ -26,13 +26,13 @@ static _Thread_local char STRINGIFY_BUFFER[64];
/*#####################################################################################################################*/
const size_t LIBCDSB_VTYPE_SIZES[18] = {
const size_t LIBCDSB_VTYPE_SIZES[19] = {
sizeof(void*), sizeof(bool),
sizeof(u8_t), sizeof(u16_t), sizeof(u32_t), sizeof(u64_t),
sizeof(s8_t), sizeof(s16_t), sizeof(s32_t), sizeof(s64_t),
sizeof(fl_t), sizeof(dbl_t), sizeof(ldbl_t),
sizeof(str_t), sizeof(map_t), sizeof(arr_t),
sizeof(list_t), sizeof(set_t)
sizeof(list_t), sizeof(set_t), sizeof(dict_t)
};

View File

@ -9,7 +9,7 @@ static int remove_callback(const void* k, vtype kt, void* v, vtype vt, void* _)
if (!d->n--) {
print_container_value(0, k, kt, 0, d->hp);
if (libcdsb_dict_get(d->x, k, kt, 0, 0, 1) == 0) {
if (libcdsb_dict_find(d->x, k, kt, 0, 0, 1) == 0) {
printf("\e[%dG\e[32;1mSUCCESS\e[m\n", d->hp+1);
} else printf("\e[%dG\e[31;1mFAILURE\e[m\n", d->hp+1);