Merge branch '#43-issue' of lirent/libcdsb into develop
This commit is contained in:
		
						commit
						e257d4ba29
					
				@ -1,6 +1,7 @@
 | 
			
		||||
/* This software is licensed by the MIT License, see LICENSE file */
 | 
			
		||||
/*                                Copyright © 2022 Gregory Lirent */
 | 
			
		||||
 | 
			
		||||
#include "bits/__generics.h"
 | 
			
		||||
#include "vtype.h"
 | 
			
		||||
 | 
			
		||||
#ifndef LIBCDSB_ARRAY_H
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										20
									
								
								include/bits/__rbtree.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								include/bits/__rbtree.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
			
		||||
/* This software is licensed by the MIT License, see LICENSE file */
 | 
			
		||||
/*                                Copyright © 2022 Gregory Lirent */
 | 
			
		||||
 | 
			
		||||
#ifndef LIBCDSB_BITS_RBTREE_H
 | 
			
		||||
#define LIBCDSB_BITS_RBTREE_H
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
    RBFOREACH_UNSPECIFIED           = 0x00,
 | 
			
		||||
    RBFOREACH_REVERSE               = 0x80,
 | 
			
		||||
    RBFOREACH_INORDER               = 0x01,
 | 
			
		||||
    RBFOREACH_PREORDER              = 0x02,
 | 
			
		||||
    RBFOREACH_POSTORDER             = 0x04,
 | 
			
		||||
    RBFOREACH_BREADTH_FIRST         = 0x08,
 | 
			
		||||
    RBFOREACH_INORDER_REVERSE       = RBFOREACH_INORDER       | RBFOREACH_REVERSE,
 | 
			
		||||
    RBFOREACH_PREORDER_REVERSE      = RBFOREACH_PREORDER      | RBFOREACH_REVERSE,
 | 
			
		||||
    RBFOREACH_POSTORDER_REVERSE     = RBFOREACH_POSTORDER     | RBFOREACH_REVERSE,
 | 
			
		||||
    RBFOREACH_BREADTH_FIRST_REVERSE = RBFOREACH_BREADTH_FIRST | RBFOREACH_REVERSE
 | 
			
		||||
} rbforeach_t;
 | 
			
		||||
 | 
			
		||||
#endif /* LIBCDSB_BITS_RBTREE_H */
 | 
			
		||||
@ -16,6 +16,7 @@ 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_reverse  (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__;
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,7 @@
 | 
			
		||||
/* This software is licensed by the MIT License, see LICENSE file */
 | 
			
		||||
/*                                Copyright © 2022 Gregory Lirent */
 | 
			
		||||
 | 
			
		||||
#include "bits/__generics.h"
 | 
			
		||||
#include "vtype.h"
 | 
			
		||||
 | 
			
		||||
#ifndef LIBCDSB_DICT_H
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,7 @@
 | 
			
		||||
/* This software is licensed by the MIT License, see LICENSE file */
 | 
			
		||||
/*                                Copyright © 2022 Gregory Lirent */
 | 
			
		||||
 | 
			
		||||
#include "bits/__generics.h"
 | 
			
		||||
#include "vtype.h"
 | 
			
		||||
 | 
			
		||||
#ifndef LIBCDSB_LIST_H
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,8 @@
 | 
			
		||||
/* This software is licensed by the MIT License, see LICENSE file */
 | 
			
		||||
/*                                Copyright © 2022 Gregory Lirent */
 | 
			
		||||
 | 
			
		||||
#include "bits/__generics.h"
 | 
			
		||||
#include "bits/__rbtree.h"
 | 
			
		||||
#include "vtype.h"
 | 
			
		||||
 | 
			
		||||
#ifndef LIBCDSB_MAP_H
 | 
			
		||||
@ -18,7 +20,7 @@ extern void map_init(vtype_map* x, vtype key_type) Nonnull__(1);
 | 
			
		||||
#define map_get(x, key, data, callback) libcdsb_map_find        (x, _LIBCDSB_value_pointer(key), _LIBCDSB_vtypeof(key), data, callback, 0)
 | 
			
		||||
#define map_update(x, key, value)       libcdsb_map_update      (x, _LIBCDSB_value_pointer(key), _LIBCDSB_vtypeof(key), _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value))
 | 
			
		||||
#define map_inject(x, key, value)       libcdsb_map_inject      (x, _LIBCDSB_value_pointer(key), _LIBCDSB_vtypeof(key), _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value))
 | 
			
		||||
#define map_foreach(x, data, callback)  libcdsb_map_foreach     (x, data, callback, 0)
 | 
			
		||||
#define map_foreach(x, data, callback)  libcdsb_map_foreach     (x, data, callback, RBFOREACH_UNSPECIFIED, 0)
 | 
			
		||||
#define map_remove(x, key)              map_pop                 (x, key, 0, 0)
 | 
			
		||||
 | 
			
		||||
#define in_map(x, key)                 (map_get(x, key, 0, 0) == 0)
 | 
			
		||||
@ -28,6 +30,6 @@ extern void map_init(vtype_map* x, vtype key_type) Nonnull__(1);
 | 
			
		||||
extern bool libcdsb_map_update (vtype_map* x, const void* key, vtype key_type, const void* value, vtype value_type)       Nonnull__(1);
 | 
			
		||||
extern bool libcdsb_map_inject (vtype_map* x, const void* key, vtype key_type, const void* value, vtype value_type)       Nonnull__(1);
 | 
			
		||||
extern int  libcdsb_map_find   (vtype_map* x, const void* key, vtype key_type, void* data, map_access_callback, bool cut) Nonnull__(1);
 | 
			
		||||
extern int  libcdsb_map_foreach(vtype_map* x, void* data, map_access_callback, bool flush)                                Nonnull__(1,3);
 | 
			
		||||
extern int  libcdsb_map_foreach(vtype_map* x, void* data, map_access_callback, rbforeach_t, bool flush)                   Nonnull__(1,3);
 | 
			
		||||
 | 
			
		||||
#endif /* LIBCDSB_MAP_H */
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,8 @@
 | 
			
		||||
/* This software is licensed by the MIT License, see LICENSE file */
 | 
			
		||||
/*                                Copyright © 2022 Gregory Lirent */
 | 
			
		||||
 | 
			
		||||
#include "bits/__generics.h"
 | 
			
		||||
#include "bits/__rbtree.h"
 | 
			
		||||
#include "vtype.h"
 | 
			
		||||
 | 
			
		||||
#ifndef LIBCDSB_SET_H
 | 
			
		||||
@ -18,7 +20,7 @@ extern void vset_init(vtype_set* x, vtype type) Nonnull__(1);
 | 
			
		||||
#define vset_get(x, value, data, callback) libcdsb_vset_find   (x, _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value), data, callback, 0)
 | 
			
		||||
#define vset_push(x, value)                libcdsb_vset_insert (x, _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value))
 | 
			
		||||
#define vset_attach(x, value)              libcdsb_vset_attach (x, _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value))
 | 
			
		||||
#define vset_foreach(x, data, callback)    libcdsb_vset_foreach(x, data, callback, 0)
 | 
			
		||||
#define vset_foreach(x, data, callback)    libcdsb_vset_foreach(x, data, callback, RBFOREACH_UNSPECIFIED, 0)
 | 
			
		||||
#define vset_remove(x, value)              vset_pop            (x, value, 0, 0)
 | 
			
		||||
 | 
			
		||||
#define in_vset(x, value)                 (vset_get(x, value, 0, 0) == 0)
 | 
			
		||||
@ -28,6 +30,6 @@ extern void vset_init(vtype_set* x, vtype type) Nonnull__(1);
 | 
			
		||||
extern bool libcdsb_vset_insert (vtype_set* x, const void* value, vtype type)                                             Nonnull__(1);
 | 
			
		||||
extern bool libcdsb_vset_attach (vtype_set* x, const void* value, vtype type)                                             Nonnull__(1);
 | 
			
		||||
extern int  libcdsb_vset_find   (vtype_set* x, const void* value, vtype type, void* data, vset_access_callback, bool cut) Nonnull__(1);
 | 
			
		||||
extern int  libcdsb_vset_foreach(vtype_set* x, void* data, vset_access_callback, bool flush)                              Nonnull__(1,3);
 | 
			
		||||
extern int  libcdsb_vset_foreach(vtype_set* x, void* data, vset_access_callback, rbforeach_t, bool flush)                 Nonnull__(1,3);
 | 
			
		||||
 | 
			
		||||
#endif /* LIBCDSB_SET_H */
 | 
			
		||||
 | 
			
		||||
@ -34,7 +34,6 @@
 | 
			
		||||
 | 
			
		||||
#define abs(v) _Generic((v), ldbl_t: fabsl, dbl_t: fabs, fl_t: fabsf)(v)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef vtype_uint8   u8_t;
 | 
			
		||||
typedef vtype_uint16 u16_t;
 | 
			
		||||
typedef vtype_uint32 u32_t;
 | 
			
		||||
@ -59,12 +58,22 @@ typedef vtype_dict   dict_t;
 | 
			
		||||
typedef vtype_hash   hash_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
extern const size_t LIBCDSB_VTYPE_SIZES[19];
 | 
			
		||||
extern const size_t LIBCDSB_BUILTIN_VTYPE_SIZES[19];
 | 
			
		||||
 | 
			
		||||
extern int    libcdsb_vtype_compare_values   (const void* s0, vtype t0, const void* s1, vtype t1) pure__ wur__;
 | 
			
		||||
extern int    libcdsb_vtype_compare_values_eq(const void* s0, const void* s1, vtype t)            pure__ wur__;
 | 
			
		||||
extern hash_t libcdsb_vtype_hash             (const void* value, vtype type)                      pure__ wur__;
 | 
			
		||||
extern int    libcdsb_builtin_vtype_compare_values   (const void* s0, vtype t0, const void* s1, vtype t1) pure__ wur__;
 | 
			
		||||
extern int    libcdsb_builtin_vtype_compare_values_eq(const void* s0, const void* s1, vtype t)            pure__ wur__;
 | 
			
		||||
extern hash_t libcdsb_builtin_vtype_hash             (const void* value, vtype type)                      pure__ wur__;
 | 
			
		||||
 | 
			
		||||
ainline(stack_t* libcdsb_builtin_stack_insert(stack_t* x, void* v)) {
 | 
			
		||||
    stack_t* p = x->prev;
 | 
			
		||||
 | 
			
		||||
    if (!is_null(x->prev = malloc(sizeof(*x)))) {
 | 
			
		||||
        x->prev->prev  = p;
 | 
			
		||||
        x->prev->value = v;
 | 
			
		||||
    } else abort();
 | 
			
		||||
 | 
			
		||||
    return x->prev;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define aligned_alloc   libcdsb_aalloc
 | 
			
		||||
#define malloc          libcdsb_malloc
 | 
			
		||||
@ -74,7 +83,9 @@ extern hash_t libcdsb_vtype_hash             (const void* value, vtype type)
 | 
			
		||||
#define stack_init      libcdsb_stack_init
 | 
			
		||||
#define stack_push      libcdsb_stack_push
 | 
			
		||||
#define stack_push_many libcdsb_stack_push_many
 | 
			
		||||
#define stack_insert    libcdsb_builtin_stack_insert
 | 
			
		||||
#define stack_pop       libcdsb_stack_pop
 | 
			
		||||
#define stack_reverse   libcdsb_stack_reverse
 | 
			
		||||
#define stack_flush     libcdsb_stack_flush
 | 
			
		||||
#define strlen          libcdsb_strlen
 | 
			
		||||
#define strasciilen     libcdsb_strasciilen
 | 
			
		||||
@ -84,32 +95,9 @@ extern hash_t libcdsb_vtype_hash             (const void* value, vtype type)
 | 
			
		||||
 | 
			
		||||
#define vtype_stringify   libcdsb_vtype_stringify
 | 
			
		||||
#define vtype_name        libcdsb_vtype_name
 | 
			
		||||
#define vtype_compare     libcdsb_vtype_compare_values
 | 
			
		||||
#define vtype_compare_eq  libcdsb_vtype_compare_values_eq
 | 
			
		||||
#define vtype_hash        libcdsb_vtype_hash
 | 
			
		||||
#define vtype_size(type) (LIBCDSB_VTYPE_SIZES[type])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define vtypeof(x) (vtype)(_Generic((x),\
 | 
			
		||||
    const void**:  VTYPE_POINTER, void**:  VTYPE_POINTER, const void*: VTYPE_POINTER, void*: VTYPE_POINTER,\
 | 
			
		||||
    const char**:  VTYPE_STRING,  char**:  VTYPE_STRING,  const char*: VTYPE_STRING,  char*: VTYPE_STRING,\
 | 
			
		||||
    const str_t*:  VTYPE_STRING,  str_t*:  VTYPE_STRING, str_t:  VTYPE_STRING,\
 | 
			
		||||
    const arr_t*:  VTYPE_ARRAY,   arr_t*:  VTYPE_ARRAY,  arr_t:  VTYPE_ARRAY,\
 | 
			
		||||
    const list_t*: VTYPE_LIST,    list_t*: VTYPE_LIST,   list_t: VTYPE_LIST,\
 | 
			
		||||
    const map_t*:  VTYPE_MAP,     map_t*:  VTYPE_MAP,    map_t:  VTYPE_MAP,\
 | 
			
		||||
    const set_t*:  VTYPE_SET,     set_t*:  VTYPE_SET,    set_t:  VTYPE_SET,\
 | 
			
		||||
    const dict_t*: VTYPE_DICT,    dict_t*: VTYPE_DICT,   dict_t: VTYPE_DICT,\
 | 
			
		||||
    const vtype_bool*:    VTYPE_BOOLEAN, vtype_bool*:    VTYPE_BOOLEAN, vtype_bool:    VTYPE_BOOLEAN,\
 | 
			
		||||
    const vtype_uint8*:   VTYPE_UINT8,   vtype_uint8*:   VTYPE_UINT8,   vtype_uint8:   VTYPE_UINT8,\
 | 
			
		||||
    const vtype_uint16*:  VTYPE_UINT16,  vtype_uint16*:  VTYPE_UINT16,  vtype_uint16:  VTYPE_UINT16,\
 | 
			
		||||
    const vtype_uint32*:  VTYPE_UINT32,  vtype_uint32*:  VTYPE_UINT32,  vtype_uint32:  VTYPE_UINT32,\
 | 
			
		||||
    const vtype_uint64*:  VTYPE_UINT64,  vtype_uint64*:  VTYPE_UINT64,  vtype_uint64:  VTYPE_UINT64,\
 | 
			
		||||
    const vtype_int8*:    VTYPE_INT8,    vtype_int8*:    VTYPE_INT8,    vtype_int8:    VTYPE_INT8,\
 | 
			
		||||
    const vtype_int16*:   VTYPE_INT16,   vtype_int16*:   VTYPE_INT16,   vtype_int16:   VTYPE_INT16,\
 | 
			
		||||
    const vtype_int32*:   VTYPE_INT32,   vtype_int32*:   VTYPE_INT32,   vtype_int32:   VTYPE_INT32,\
 | 
			
		||||
    const vtype_int64*:   VTYPE_INT64,   vtype_int64*:   VTYPE_INT64,   vtype_int64:   VTYPE_INT64,\
 | 
			
		||||
    const vtype_float*:   VTYPE_FLOAT,   vtype_float*:   VTYPE_FLOAT,   vtype_float:   VTYPE_FLOAT,\
 | 
			
		||||
    const vtype_double*:  VTYPE_DOUBLE,  vtype_double*:  VTYPE_DOUBLE,  vtype_double:  VTYPE_DOUBLE,\
 | 
			
		||||
    const vtype_ldouble*: VTYPE_LDOUBLE, vtype_ldouble*: VTYPE_LDOUBLE, vtype_ldouble: VTYPE_LDOUBLE))
 | 
			
		||||
#define vtype_compare     libcdsb_builtin_vtype_compare_values
 | 
			
		||||
#define vtype_compare_eq  libcdsb_builtin_vtype_compare_values_eq
 | 
			
		||||
#define vtype_hash        libcdsb_builtin_vtype_hash
 | 
			
		||||
#define vtype_size(type) (LIBCDSB_BUILTIN_VTYPE_SIZES[type])
 | 
			
		||||
 | 
			
		||||
#endif /* LIBCDSB_SRC_INTERNAL_INCLUDE */
 | 
			
		||||
 | 
			
		||||
@ -15,18 +15,28 @@ typedef struct libcdsb_rbtree_node {
 | 
			
		||||
    short colored;
 | 
			
		||||
} rbnode_t;
 | 
			
		||||
 | 
			
		||||
extern rbnode_t LIBCDSB_RBTREE_NODE_EMPTY[1];
 | 
			
		||||
extern rbnode_t LIBCDSB_BUILTIN_RBTREE_NODE_EMPTY[1];
 | 
			
		||||
 | 
			
		||||
extern void*     libcdsb_rbtree_node_create(void* value, rbnode_t* parent, int colored, int size) Nonnull__(  2);
 | 
			
		||||
extern void      libcdsb_rbtree_node_fixup (rbnode_t** root, rbnode_t* node)                      Nonnull__(1,2);
 | 
			
		||||
extern rbnode_t* libcdsb_rbtree_node_delete(rbnode_t** root, rbnode_t* node)                      Nonnull__(1,2);
 | 
			
		||||
extern void*     libcdsb_builtin_rbtree_node_create(void* value, rbnode_t* parent, int colored, int size) Nonnull__(  2);
 | 
			
		||||
extern void      libcdsb_builtin_rbtree_node_fixup (rbnode_t** root, rbnode_t* node)                      Nonnull__(1,2);
 | 
			
		||||
extern rbnode_t* libcdsb_builtin_rbtree_node_delete(rbnode_t** root, rbnode_t* node)                      Nonnull__(1,2);
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
extern stack_t libcdsb_builtin_rbtree_iter_inorder     (rbnode_t** root, bool reverse);
 | 
			
		||||
extern stack_t libcdsb_builtin_rbtree_iter_preorder    (rbnode_t** root, bool reverse);
 | 
			
		||||
extern stack_t libcdsb_builtin_rbtree_iter_postorder   (rbnode_t** root, bool reverse);
 | 
			
		||||
extern stack_t libcdsb_builtin_rbtree_iter_breath_first(rbnode_t** root, bool reverse);
 | 
			
		||||
 | 
			
		||||
#define rbnode_empty           ((rbnode_t*)LIBCDSB_BUILTIN_RBTREE_NODE_EMPTY)
 | 
			
		||||
#define rbnode_create(v, p, c) ((rbnode_t*)libcdsb_builtin_rbtree_node_create(v, p, c, sizeof(rbnode_t)))
 | 
			
		||||
#define rbnode_fixup           libcdsb_builtin_rbtree_node_fixup
 | 
			
		||||
#define rbnode_delete          libcdsb_builtin_rbtree_node_delete
 | 
			
		||||
 | 
			
		||||
#define rbnode_is_empty(n) ((n) == rbnode_empty)
 | 
			
		||||
#define rbnode_is_root(n)  rbnode_is_empty((n)->parent)
 | 
			
		||||
 | 
			
		||||
#define rbiter_inorder      libcdsb_builtin_rbtree_iter_inorder
 | 
			
		||||
#define rbiter_preorder     libcdsb_builtin_rbtree_iter_preorder
 | 
			
		||||
#define rbiter_postorder    libcdsb_builtin_rbtree_iter_postorder
 | 
			
		||||
#define rbiter_breath_first libcdsb_builtin_rbtree_iter_breath_first
 | 
			
		||||
 | 
			
		||||
#endif /* LIBCDSB_SRC_INTERNAL_RBTREE_H */
 | 
			
		||||
 | 
			
		||||
@ -19,15 +19,15 @@ typedef union {
 | 
			
		||||
 | 
			
		||||
typedef void* vnode_t;
 | 
			
		||||
 | 
			
		||||
extern vnode_t libcdsb_vnode_create       (const void* value, vtype type)                    wur__;
 | 
			
		||||
extern vnode_t libcdsb_vnode_create_target(vtype target_type, const void* value, vtype type) wur__;
 | 
			
		||||
extern vnode_t libcdsb_builtin_vnode_create       (const void* value, vtype type)                    wur__;
 | 
			
		||||
extern vnode_t libcdsb_builtin_vnode_create_target(vtype target_type, const void* value, vtype type) wur__;
 | 
			
		||||
 | 
			
		||||
extern void  libcdsb_vnode_free(vnode_t* x, vtype type)                    Nonnull__(1);
 | 
			
		||||
extern void* libcdsb_vnode_peek(const vnode_t* x, vtype type) pure__ wur__ Nonnull__(1);
 | 
			
		||||
extern void  libcdsb_builtin_vnode_free(vnode_t* x, vtype type)                    Nonnull__(1);
 | 
			
		||||
extern void* libcdsb_builtin_vnode_peek(const vnode_t* x, vtype type) pure__ wur__ Nonnull__(1);
 | 
			
		||||
 | 
			
		||||
ainline(void vnode_attach(vnode_t* node, const void* value, vtype type)) {
 | 
			
		||||
ainline(void libcdsb_builtin_vnode_attach(vnode_t* node, const void* value, vtype type)) {
 | 
			
		||||
    if (type < VTYPE_STRING) {
 | 
			
		||||
        *node = libcdsb_vnode_create(value, type);
 | 
			
		||||
        *node = libcdsb_builtin_vnode_create(value, type);
 | 
			
		||||
    } else if (sizeof(str_t) == sizeof(void*) && type == VTYPE_STRING) {
 | 
			
		||||
        *node = *(char**)value;
 | 
			
		||||
    } else {
 | 
			
		||||
@ -36,9 +36,9 @@ ainline(void vnode_attach(vnode_t* node, const void* value, vtype type)) {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ainline(void vnode_tattach(vnode_t* node, vtype target_type, const void* value, vtype type)) {
 | 
			
		||||
ainline(void libcdsb_builtin_vnode_tattach(vnode_t* node, vtype target_type, const void* value, vtype type)) {
 | 
			
		||||
    if (type < VTYPE_STRING) {
 | 
			
		||||
        *node = libcdsb_vnode_create_target(target_type, value, type);
 | 
			
		||||
        *node = libcdsb_builtin_vnode_create_target(target_type, value, type);
 | 
			
		||||
    } else {
 | 
			
		||||
        type_assert(target_type, type);
 | 
			
		||||
 | 
			
		||||
@ -51,16 +51,18 @@ ainline(void vnode_tattach(vnode_t* node, vtype target_type, const void* value,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define vnode_create  libcdsb_vnode_create
 | 
			
		||||
#define vnode_tcreate libcdsb_vnode_create_target
 | 
			
		||||
#define vnode_peek    libcdsb_vnode_peek
 | 
			
		||||
#define vnode_free    libcdsb_vnode_free
 | 
			
		||||
#define vnode_create  libcdsb_builtin_vnode_create
 | 
			
		||||
#define vnode_tcreate libcdsb_builtin_vnode_create_target
 | 
			
		||||
#define vnode_attach  libcdsb_builtin_vnode_attach
 | 
			
		||||
#define vnode_tattach libcdsb_builtin_vnode_tattach
 | 
			
		||||
#define vnode_peek    libcdsb_builtin_vnode_peek
 | 
			
		||||
#define vnode_free    libcdsb_builtin_vnode_free
 | 
			
		||||
 | 
			
		||||
#define vnode_hash(vnode, type)                    vtype_hash(vnode_peek(vnode, type), type)
 | 
			
		||||
#define vnode_compare(s0, t0, s1, t1)              vtype_compare(vnode_peek(s0, t0), t0, vnode_peek(s1, t1), t1)
 | 
			
		||||
#define vnode_compare_eq(s0, s1, t)                vtype_compare_eq(vnode_peek(s0, t), vnode_peek(s1, t), t)
 | 
			
		||||
#define vnode_duplicate(vnode, type)               libcdsb_vnode_create(vnode_peek(vnode, type), type)
 | 
			
		||||
#define vnode_tduplicate(target_type, vnode, type) libcdsb_vnode_create_target(target_type, vnode_peek(vnode, type), type)
 | 
			
		||||
#define vnode_duplicate(vnode, type)               vnode_create(vnode_peek(vnode, type), type)
 | 
			
		||||
#define vnode_tduplicate(target_type, vnode, type) vnode_tcreate(target_type, vnode_peek(vnode, type), type)
 | 
			
		||||
 | 
			
		||||
#define vnode_stringify(n, t) vtype_stringify(vnode_peek(n, t), t)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -4,78 +4,42 @@
 | 
			
		||||
#include "include.h"
 | 
			
		||||
#include "../__internal/assert.h"
 | 
			
		||||
 | 
			
		||||
static_assert((
 | 
			
		||||
    VTYPE_UINT8   ==  2 &&
 | 
			
		||||
    VTYPE_UINT16  ==  3 &&
 | 
			
		||||
    VTYPE_UINT32  ==  4 &&
 | 
			
		||||
    VTYPE_UINT64  ==  5 &&
 | 
			
		||||
    VTYPE_INT8    ==  6 &&
 | 
			
		||||
    VTYPE_INT16   ==  7 &&
 | 
			
		||||
    VTYPE_INT32   ==  8 &&
 | 
			
		||||
    VTYPE_INT64   ==  9 &&
 | 
			
		||||
    VTYPE_FLOAT   == 10 &&
 | 
			
		||||
    VTYPE_DOUBLE  == 11 &&
 | 
			
		||||
    VTYPE_LDOUBLE == 12 &&
 | 
			
		||||
    VTYPE_STRING  == 13 &&
 | 
			
		||||
    VTYPE_MAP     == 14 &&
 | 
			
		||||
    VTYPE_ARRAY   == 15 &&
 | 
			
		||||
    VTYPE_LIST    == 16 &&
 | 
			
		||||
    VTYPE_SET     == 17
 | 
			
		||||
), "enum values assertion");
 | 
			
		||||
typedef int (*compare_f)(const void*, const void*);
 | 
			
		||||
 | 
			
		||||
static int uint8_compare  (const   u8_t* s0, const   u8_t* s1) { if (*s0 == *s1) return 0; return *s0 < *s1 ? -1 : 1; }
 | 
			
		||||
static int uint16_compare (const  u16_t* s0, const  u16_t* s1) { if (*s0 == *s1) return 0; return *s0 < *s1 ? -1 : 1; }
 | 
			
		||||
static int uint32_compare (const  u32_t* s0, const  u32_t* s1) { if (*s0 == *s1) return 0; return *s0 < *s1 ? -1 : 1; }
 | 
			
		||||
static int uint64_compare (const  u64_t* s0, const  u64_t* s1) { if (*s0 == *s1) return 0; return *s0 < *s1 ? -1 : 1; }
 | 
			
		||||
static int int8_compare   (const   s8_t* s0, const   s8_t* s1) { if (*s0 == *s1) return 0; return *s0 < *s1 ? -1 : 1; }
 | 
			
		||||
static int int16_compare  (const  s16_t* s0, const  s16_t* s1) { if (*s0 == *s1) return 0; return *s0 < *s1 ? -1 : 1; }
 | 
			
		||||
static int int32_compare  (const  s32_t* s0, const  s32_t* s1) { if (*s0 == *s1) return 0; return *s0 < *s1 ? -1 : 1; }
 | 
			
		||||
static int int64_compare  (const  s64_t* s0, const  s64_t* s1) { if (*s0 == *s1) return 0; return *s0 < *s1 ? -1 : 1; }
 | 
			
		||||
static int float_compare  (const   fl_t* s0, const   fl_t* s1) { if (*s0 == *s1) return 0; return *s0 < *s1 ? -1 : 1; }
 | 
			
		||||
static int double_compare (const  dbl_t* s0, const  dbl_t* s1) { if (*s0 == *s1) return 0; return *s0 < *s1 ? -1 : 1; }
 | 
			
		||||
static int ldouble_compare(const ldbl_t* s0, const ldbl_t* s1) { if (*s0 == *s1) return 0; return *s0 < *s1 ? -1 : 1; }
 | 
			
		||||
static int libcdsb_builtin_compare_uint8  (const   u8_t* s0, const   u8_t* s1) { if (*s0 == *s1) return 0; return *s0 < *s1 ? -1 : 1; }
 | 
			
		||||
static int libcdsb_builtin_compare_uint16 (const  u16_t* s0, const  u16_t* s1) { if (*s0 == *s1) return 0; return *s0 < *s1 ? -1 : 1; }
 | 
			
		||||
static int libcdsb_builtin_compare_uint32 (const  u32_t* s0, const  u32_t* s1) { if (*s0 == *s1) return 0; return *s0 < *s1 ? -1 : 1; }
 | 
			
		||||
static int libcdsb_builtin_compare_uint64 (const  u64_t* s0, const  u64_t* s1) { if (*s0 == *s1) return 0; return *s0 < *s1 ? -1 : 1; }
 | 
			
		||||
static int libcdsb_builtin_compare_int8   (const   s8_t* s0, const   s8_t* s1) { if (*s0 == *s1) return 0; return *s0 < *s1 ? -1 : 1; }
 | 
			
		||||
static int libcdsb_builtin_compare_int16  (const  s16_t* s0, const  s16_t* s1) { if (*s0 == *s1) return 0; return *s0 < *s1 ? -1 : 1; }
 | 
			
		||||
static int libcdsb_builtin_compare_int32  (const  s32_t* s0, const  s32_t* s1) { if (*s0 == *s1) return 0; return *s0 < *s1 ? -1 : 1; }
 | 
			
		||||
static int libcdsb_builtin_compare_int64  (const  s64_t* s0, const  s64_t* s1) { if (*s0 == *s1) return 0; return *s0 < *s1 ? -1 : 1; }
 | 
			
		||||
static int libcdsb_builtin_compare_float  (const   fl_t* s0, const   fl_t* s1) { if (*s0 == *s1) return 0; return *s0 < *s1 ? -1 : 1; }
 | 
			
		||||
static int libcdsb_builtin_compare_double (const  dbl_t* s0, const  dbl_t* s1) { if (*s0 == *s1) return 0; return *s0 < *s1 ? -1 : 1; }
 | 
			
		||||
static int libcdsb_builtin_compare_ldouble(const ldbl_t* s0, const ldbl_t* s1) { if (*s0 == *s1) return 0; return *s0 < *s1 ? -1 : 1; }
 | 
			
		||||
 | 
			
		||||
static int (*COMPARE[16])(const void*, const void*) = {
 | 
			
		||||
    (void*)   uint8_compare,
 | 
			
		||||
    (void*)  uint16_compare,
 | 
			
		||||
    (void*)  uint32_compare,
 | 
			
		||||
    (void*)  uint64_compare,
 | 
			
		||||
    (void*)    int8_compare,
 | 
			
		||||
    (void*)   int16_compare,
 | 
			
		||||
    (void*)   int32_compare,
 | 
			
		||||
    (void*)   int64_compare,
 | 
			
		||||
    (void*)   float_compare,
 | 
			
		||||
    (void*)  double_compare,
 | 
			
		||||
    (void*) ldouble_compare,
 | 
			
		||||
    (void*)  string_compare,
 | 
			
		||||
    (void*)     map_compare,
 | 
			
		||||
    (void*)   array_compare,
 | 
			
		||||
    (void*)    list_compare,
 | 
			
		||||
    (void*)    vset_compare
 | 
			
		||||
};
 | 
			
		||||
static compare_f libcdsb_builtin_get_comparator(vtype t) {
 | 
			
		||||
    static void* comparators[17] = { libcdsb_builtin_compare_uint8,   libcdsb_builtin_compare_uint16,
 | 
			
		||||
                                     libcdsb_builtin_compare_uint32,  libcdsb_builtin_compare_uint64,
 | 
			
		||||
                                     libcdsb_builtin_compare_int8,    libcdsb_builtin_compare_int16,
 | 
			
		||||
                                     libcdsb_builtin_compare_int32,   libcdsb_builtin_compare_int64,
 | 
			
		||||
                                     libcdsb_builtin_compare_float,   libcdsb_builtin_compare_double,
 | 
			
		||||
                                     libcdsb_builtin_compare_ldouble, string_compare, map_compare,
 | 
			
		||||
                                     array_compare, list_compare, vset_compare, dict_compare };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ainline(int get_compare_index(vtype t)) {
 | 
			
		||||
    if (t == VTYPE_POINTER) {
 | 
			
		||||
        if (is_x64) t = VTYPE_UINT64;
 | 
			
		||||
        else        t = VTYPE_UINT32;
 | 
			
		||||
    } else if (t == VTYPE_BOOLEAN) t = VTYPE_UINT8;
 | 
			
		||||
 | 
			
		||||
    return t - VTYPE_UINT8;
 | 
			
		||||
    return comparators[t - VTYPE_UINT8];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void array_sort(arr_t* x) {
 | 
			
		||||
    int i = get_compare_index(x->type);
 | 
			
		||||
 | 
			
		||||
    if (x->size > 1)
 | 
			
		||||
        qsort(x->mem, x->size, vtype_size(x->type), COMPARE[i]);
 | 
			
		||||
        qsort(x->mem, x->size, vtype_size(x->type), libcdsb_builtin_get_comparator(x->type));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void array_reverse(arr_t* x) {
 | 
			
		||||
 | 
			
		||||
@ -4,21 +4,21 @@
 | 
			
		||||
#include "../modules/libunic/include.h"
 | 
			
		||||
#include "__internal/include.h"
 | 
			
		||||
 | 
			
		||||
static _Thread_local int  CHAR_BUFFER_POS = 0;
 | 
			
		||||
static _Thread_local char CHAR_BUFFER[16][5];
 | 
			
		||||
static _Thread_local int  LIBCDSB_BUILTIN_COUNTER = 0;
 | 
			
		||||
static _Thread_local char LIBCDSB_BUILTIN_BUFFER[16][5];
 | 
			
		||||
 | 
			
		||||
const char* libcdsb_char_to_cstring(int c) {
 | 
			
		||||
 | 
			
		||||
    char* p;
 | 
			
		||||
 | 
			
		||||
    if (CHAR_BUFFER_POS > 15)
 | 
			
		||||
        CHAR_BUFFER_POS = 0;
 | 
			
		||||
    if (LIBCDSB_BUILTIN_COUNTER > 15)
 | 
			
		||||
        LIBCDSB_BUILTIN_COUNTER = 0;
 | 
			
		||||
 | 
			
		||||
    if (is_null(p = tochar_unicode(CHAR_BUFFER[CHAR_BUFFER_POS], c))) {
 | 
			
		||||
        CHAR_BUFFER[CHAR_BUFFER_POS][0] = 0;
 | 
			
		||||
    if (is_null(p = tochar_unicode(LIBCDSB_BUILTIN_BUFFER[LIBCDSB_BUILTIN_COUNTER], c))) {
 | 
			
		||||
        LIBCDSB_BUILTIN_BUFFER[LIBCDSB_BUILTIN_COUNTER][0] = 0;
 | 
			
		||||
    } else *p = 0;
 | 
			
		||||
 | 
			
		||||
    return CHAR_BUFFER[CHAR_BUFFER_POS++];
 | 
			
		||||
    return LIBCDSB_BUILTIN_BUFFER[LIBCDSB_BUILTIN_COUNTER++];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -3,16 +3,6 @@
 | 
			
		||||
 | 
			
		||||
#include "include.h"
 | 
			
		||||
 | 
			
		||||
size_t dict_size(const dict_t* x) {
 | 
			
		||||
    return x->size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
size_t dict_capacity(const dict_t* x) {
 | 
			
		||||
    return x->capacity;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
hash_t dict_hash(const dict_t* s) {
 | 
			
		||||
    dnode_t *min, *max;
 | 
			
		||||
    size_t           i;
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,10 @@
 | 
			
		||||
/* This software is licensed by the MIT License, see LICENSE file */
 | 
			
		||||
/*                                Copyright © 2022 Gregory Lirent */
 | 
			
		||||
 | 
			
		||||
#include "../../include/list.h"
 | 
			
		||||
#include "../list/include.h"
 | 
			
		||||
#include "include.h"
 | 
			
		||||
 | 
			
		||||
static inline dnode_t* dnode_duplicate(const dnode_t* s, dnode_t* p) {
 | 
			
		||||
static inline dnode_t* libcdsb_builtin_duplicate(const dnode_t* s, dnode_t* p) {
 | 
			
		||||
    dnode_t* x = malloc(sizeof(*x));
 | 
			
		||||
 | 
			
		||||
    x->prev       = p;
 | 
			
		||||
@ -31,7 +31,7 @@ dict_t dict_copy(const dict_t* s) {
 | 
			
		||||
        n = s->nodes[i];
 | 
			
		||||
 | 
			
		||||
        while (!is_null(n)) {
 | 
			
		||||
            x.nodes[i] = dnode_duplicate(n, x.nodes[i]);
 | 
			
		||||
            x.nodes[i] = libcdsb_builtin_duplicate(n, x.nodes[i]);
 | 
			
		||||
            n          = n->prev;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -53,7 +53,7 @@ dict_t* dict_duplicate(const dict_t* s) {
 | 
			
		||||
        n = s->nodes[i];
 | 
			
		||||
 | 
			
		||||
        while (!is_null(n)) {
 | 
			
		||||
            x->nodes[i] = dnode_duplicate(n, x->nodes[i]);
 | 
			
		||||
            x->nodes[i] = libcdsb_builtin_duplicate(n, x->nodes[i]);
 | 
			
		||||
            n           = n->prev;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -74,17 +74,17 @@ void dict_copy_init(dict_t* x, const dict_t* s) {
 | 
			
		||||
        n = s->nodes[i];
 | 
			
		||||
 | 
			
		||||
        while (!is_null(n)) {
 | 
			
		||||
            x->nodes[i] = dnode_duplicate(n, x->nodes[i]);
 | 
			
		||||
            x->nodes[i] = libcdsb_builtin_duplicate(n, x->nodes[i]);
 | 
			
		||||
            n           = n->prev;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
vtype_list libcdsb_dict_copy_keys(const vtype_dict* s) {
 | 
			
		||||
    vtype_list x;
 | 
			
		||||
    dnode_t   *c;
 | 
			
		||||
    size_t     i;
 | 
			
		||||
list_t libcdsb_dict_copy_keys(const dict_t* s) {
 | 
			
		||||
    list_t   x;
 | 
			
		||||
    dnode_t *c;
 | 
			
		||||
    size_t   i;
 | 
			
		||||
 | 
			
		||||
    i = s->capacity;
 | 
			
		||||
 | 
			
		||||
@ -94,7 +94,11 @@ vtype_list libcdsb_dict_copy_keys(const vtype_dict* s) {
 | 
			
		||||
        c = s->nodes[i];
 | 
			
		||||
 | 
			
		||||
        while (!is_null(c)) {
 | 
			
		||||
            libcdsb_list_insert(&x, -1, vnode_peek(&c->key, c->key_type), c->key_type, 1);
 | 
			
		||||
 | 
			
		||||
            if (is_null(x.first)) {
 | 
			
		||||
                libcdsb_builtin_init(&x, vnode_duplicate(&c->key, c->key_type), c->key_type);
 | 
			
		||||
            } else libcdsb_builtin_push(&x, vnode_duplicate(&c->key, c->key_type), c->key_type);
 | 
			
		||||
 | 
			
		||||
            c = c->prev;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -103,10 +107,10 @@ vtype_list libcdsb_dict_copy_keys(const vtype_dict* s) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
vtype_list* libcdsb_dict_duplicate_keys(const vtype_dict* s) {
 | 
			
		||||
    vtype_list* x;
 | 
			
		||||
    dnode_t    *c;
 | 
			
		||||
    size_t      i;
 | 
			
		||||
list_t* libcdsb_dict_duplicate_keys(const dict_t* s) {
 | 
			
		||||
    list_t*  x;
 | 
			
		||||
    dnode_t *c;
 | 
			
		||||
    size_t   i;
 | 
			
		||||
 | 
			
		||||
    x = malloc(sizeof(*x));
 | 
			
		||||
    i = s->capacity;
 | 
			
		||||
@ -117,7 +121,9 @@ vtype_list* libcdsb_dict_duplicate_keys(const vtype_dict* s) {
 | 
			
		||||
        c = s->nodes[i];
 | 
			
		||||
 | 
			
		||||
        while (!is_null(c)) {
 | 
			
		||||
            libcdsb_list_insert(x, -1, vnode_peek(&c->key, c->key_type), c->key_type, 1);
 | 
			
		||||
            if (is_null(x->first)) {
 | 
			
		||||
                libcdsb_builtin_init(x, vnode_duplicate(&c->key, c->key_type), c->key_type);
 | 
			
		||||
            } else libcdsb_builtin_push(x, vnode_duplicate(&c->key, c->key_type), c->key_type);
 | 
			
		||||
            c = c->prev;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -126,9 +132,9 @@ vtype_list* libcdsb_dict_duplicate_keys(const vtype_dict* s) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void libcdsb_dict_init_keys(vtype_list* x, const vtype_dict* s) {
 | 
			
		||||
    dnode_t    *c;
 | 
			
		||||
    size_t      i;
 | 
			
		||||
void libcdsb_dict_init_keys(list_t* x, const dict_t* s) {
 | 
			
		||||
    dnode_t *c;
 | 
			
		||||
    size_t   i;
 | 
			
		||||
 | 
			
		||||
    x = malloc(sizeof(*x));
 | 
			
		||||
    i = s->capacity;
 | 
			
		||||
@ -139,7 +145,9 @@ void libcdsb_dict_init_keys(vtype_list* x, const vtype_dict* s) {
 | 
			
		||||
        c = s->nodes[i];
 | 
			
		||||
 | 
			
		||||
        while (!is_null(c)) {
 | 
			
		||||
            libcdsb_list_insert(x, -1, vnode_peek(&c->key, c->key_type), c->key_type, 1);
 | 
			
		||||
            if (is_null(x->first)) {
 | 
			
		||||
                libcdsb_builtin_init(x, vnode_duplicate(&c->key, c->key_type), c->key_type);
 | 
			
		||||
            } else libcdsb_builtin_push(x, vnode_duplicate(&c->key, c->key_type), c->key_type);
 | 
			
		||||
            c = c->prev;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@
 | 
			
		||||
#include "../../include/list.h"
 | 
			
		||||
#include "include.h"
 | 
			
		||||
 | 
			
		||||
static void dict_rehash(dict_t* s, size_t capacity) {
 | 
			
		||||
static void libcdsb_builtin_rehash(dict_t* s, size_t capacity) {
 | 
			
		||||
    dnode_t **nodes, *c, *n, **p;
 | 
			
		||||
    size_t  i;
 | 
			
		||||
 | 
			
		||||
@ -44,7 +44,7 @@ bool libcdsb_dict_shrink_to_fit(dict_t* s) {
 | 
			
		||||
    if (capacity >= s->capacity)
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    dict_rehash(s, capacity);
 | 
			
		||||
    libcdsb_builtin_rehash(s, capacity);
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
@ -54,7 +54,7 @@ bool libcdsb_dict_update(dict_t* x, const void* k, vtype kt, const void* v, vtyp
 | 
			
		||||
    dnode_t *c, **p;
 | 
			
		||||
 | 
			
		||||
    if (!x->capacity || (double)x->size / x->capacity > REBUILD_POINT_MAX)
 | 
			
		||||
        dict_rehash(x, x->capacity + CAPACITY_BLOCK);
 | 
			
		||||
        libcdsb_builtin_rehash(x, x->capacity + CAPACITY_BLOCK);
 | 
			
		||||
 | 
			
		||||
    c = *(p = x->nodes + (vtype_hash(k, kt) % x->capacity));
 | 
			
		||||
 | 
			
		||||
@ -88,7 +88,7 @@ bool libcdsb_dict_inject(dict_t* x, const void* k, vtype kt, const void* v, vtyp
 | 
			
		||||
    dnode_t *c, **p;
 | 
			
		||||
 | 
			
		||||
    if (!x->capacity || (double)x->size / x->capacity > REBUILD_POINT_MAX)
 | 
			
		||||
        dict_rehash(x, x->capacity + CAPACITY_BLOCK);
 | 
			
		||||
        libcdsb_builtin_rehash(x, x->capacity + CAPACITY_BLOCK);
 | 
			
		||||
 | 
			
		||||
    c = *(p = x->nodes + (vtype_hash(k, kt) % x->capacity));
 | 
			
		||||
 | 
			
		||||
@ -123,7 +123,7 @@ bool libcdsb_dict_inject_key(dict_t* x, const void* k, vtype kt, const void* v,
 | 
			
		||||
    dnode_t *c, **p;
 | 
			
		||||
 | 
			
		||||
    if (!x->capacity || (double)x->size / x->capacity > REBUILD_POINT_MAX)
 | 
			
		||||
        dict_rehash(x, x->capacity + CAPACITY_BLOCK);
 | 
			
		||||
        libcdsb_builtin_rehash(x, x->capacity + CAPACITY_BLOCK);
 | 
			
		||||
 | 
			
		||||
    c = *(p = x->nodes + (vtype_hash(k, kt) % x->capacity));
 | 
			
		||||
 | 
			
		||||
@ -158,7 +158,7 @@ bool libcdsb_dict_inject_value(dict_t* x, const void* k, vtype kt, const void* v
 | 
			
		||||
    dnode_t *c, **p;
 | 
			
		||||
 | 
			
		||||
    if (!x->capacity || (double)x->size / x->capacity > REBUILD_POINT_MAX)
 | 
			
		||||
        dict_rehash(x, x->capacity + CAPACITY_BLOCK);
 | 
			
		||||
        libcdsb_builtin_rehash(x, x->capacity + CAPACITY_BLOCK);
 | 
			
		||||
 | 
			
		||||
    c = *(p = x->nodes + (vtype_hash(k, kt) % x->capacity));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -3,7 +3,7 @@
 | 
			
		||||
 | 
			
		||||
#include "include.h"
 | 
			
		||||
 | 
			
		||||
static void lnode_cut(list_t* s, lnode_t* cur) {
 | 
			
		||||
static void libcdsb_builtin_cut(list_t* s, lnode_t* cur) {
 | 
			
		||||
 | 
			
		||||
    vnode_free(&cur->node, cur->type);
 | 
			
		||||
 | 
			
		||||
@ -45,7 +45,7 @@ int libcdsb_list_get(vtype_list* x, ssize_t i, void* _, list_access_callback cal
 | 
			
		||||
 | 
			
		||||
    i = (callback) ? callback(vnode_peek(&c->node, c->type), i, c->type, _) : 0;
 | 
			
		||||
 | 
			
		||||
    if (cut) lnode_cut(x, c);
 | 
			
		||||
    if (cut) libcdsb_builtin_cut(x, c);
 | 
			
		||||
 | 
			
		||||
    return i;
 | 
			
		||||
}
 | 
			
		||||
@ -67,7 +67,7 @@ int libcdsb_list_find(vtype_list* x, const void* v, vtype t, void* _, list_acces
 | 
			
		||||
        if (cmp == 0) {
 | 
			
		||||
            i = (callback) ? callback(vnode_peek(&c->node, c->type), (r)?~i:i, c->type, _) : 0;
 | 
			
		||||
 | 
			
		||||
            if (cut) lnode_cut(x, c);
 | 
			
		||||
            if (cut) libcdsb_builtin_cut(x, c);
 | 
			
		||||
 | 
			
		||||
            return i;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -3,33 +3,6 @@
 | 
			
		||||
 | 
			
		||||
#include "include.h"
 | 
			
		||||
 | 
			
		||||
static void init_first(list_t* x, vnode_t v, vtype t) {
 | 
			
		||||
    lnode_t* node = malloc(sizeof(*node));
 | 
			
		||||
 | 
			
		||||
    node->next = nullptr;
 | 
			
		||||
    node->prev = nullptr;
 | 
			
		||||
    node->node = v;
 | 
			
		||||
    node->type = t;
 | 
			
		||||
 | 
			
		||||
    x->first = node;
 | 
			
		||||
    x->last  = node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void push_next(list_t* x, vnode_t v, vtype t) {
 | 
			
		||||
    lnode_t* node = malloc(sizeof(*node));
 | 
			
		||||
 | 
			
		||||
    node->next = nullptr;
 | 
			
		||||
    node->prev = x->last;
 | 
			
		||||
    node->node = v;
 | 
			
		||||
    node->type = t;
 | 
			
		||||
 | 
			
		||||
    x->last->next = node;
 | 
			
		||||
    x->last       = node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
list_t list_copy(const list_t* s) {
 | 
			
		||||
    list_t   x;
 | 
			
		||||
    lnode_t* c;
 | 
			
		||||
@ -40,10 +13,10 @@ list_t list_copy(const list_t* s) {
 | 
			
		||||
    if (is_null(c))
 | 
			
		||||
        return x;
 | 
			
		||||
 | 
			
		||||
    init_first(&x, vnode_duplicate(&c->node, c->type), c->type);
 | 
			
		||||
    libcdsb_builtin_init(&x, vnode_duplicate(&c->node, c->type), c->type);
 | 
			
		||||
 | 
			
		||||
    while (!is_null(c = c->next)) {
 | 
			
		||||
        push_next(&x, vnode_duplicate(&c->node, c->type), c->type);
 | 
			
		||||
        libcdsb_builtin_push(&x, vnode_duplicate(&c->node, c->type), c->type);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return x;
 | 
			
		||||
@ -60,10 +33,10 @@ list_t* list_duplicate(const list_t* s) {
 | 
			
		||||
    if (is_null(c))
 | 
			
		||||
        return x;
 | 
			
		||||
 | 
			
		||||
    init_first(x, vnode_duplicate(&c->node, c->type), c->type);
 | 
			
		||||
    libcdsb_builtin_init(x, vnode_duplicate(&c->node, c->type), c->type);
 | 
			
		||||
 | 
			
		||||
    while (!is_null(c = c->next)) {
 | 
			
		||||
        push_next(x, vnode_duplicate(&c->node, c->type), c->type);
 | 
			
		||||
        libcdsb_builtin_push(x, vnode_duplicate(&c->node, c->type), c->type);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return x;
 | 
			
		||||
@ -79,10 +52,10 @@ void list_copy_init(list_t* x, const list_t* s) {
 | 
			
		||||
    if (is_null(c))
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    init_first(x, vnode_duplicate(&c->node, c->type), c->type);
 | 
			
		||||
    libcdsb_builtin_init(x, vnode_duplicate(&c->node, c->type), c->type);
 | 
			
		||||
 | 
			
		||||
    while (!is_null(c = c->next)) {
 | 
			
		||||
        push_next(x, vnode_duplicate(&c->node, c->type), c->type);
 | 
			
		||||
        libcdsb_builtin_push(x, vnode_duplicate(&c->node, c->type), c->type);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -96,7 +69,7 @@ void list_extend(list_t* x, const list_t* s) {
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if (is_null(x->first)) {
 | 
			
		||||
        init_first(x, vnode_duplicate(&c->node, c->type), c->type);
 | 
			
		||||
        libcdsb_builtin_init(x, vnode_duplicate(&c->node, c->type), c->type);
 | 
			
		||||
        c = c->next;
 | 
			
		||||
 | 
			
		||||
        if (is_null(c))
 | 
			
		||||
@ -104,7 +77,7 @@ void list_extend(list_t* x, const list_t* s) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
        push_next(x, vnode_duplicate(&c->node, c->type), c->type);
 | 
			
		||||
        libcdsb_builtin_push(x, vnode_duplicate(&c->node, c->type), c->type);
 | 
			
		||||
    } while (!is_null(c = c->next));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -157,13 +130,13 @@ size_t list_slice(list_t* x, list_t* s, ssize_t i, size_t n, _Bool cut) {
 | 
			
		||||
    else r -= n;
 | 
			
		||||
 | 
			
		||||
    if (!cut) {
 | 
			
		||||
        init_first(x, vnode_duplicate(&c->node, c->type), c->type);
 | 
			
		||||
        libcdsb_builtin_init(x, vnode_duplicate(&c->node, c->type), c->type);
 | 
			
		||||
 | 
			
		||||
        while ((c = c->next) != e) {
 | 
			
		||||
            push_next(x, vnode_duplicate(&c->node, c->type), c->type);
 | 
			
		||||
            libcdsb_builtin_push(x, vnode_duplicate(&c->node, c->type), c->type);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        push_next(x, vnode_duplicate(&e->node, e->type), e->type);
 | 
			
		||||
        libcdsb_builtin_push(x, vnode_duplicate(&e->node, e->type), e->type);
 | 
			
		||||
    } else {
 | 
			
		||||
        if (c->prev) {
 | 
			
		||||
            c->prev->next = e->next;
 | 
			
		||||
 | 
			
		||||
@ -20,6 +20,31 @@ typedef struct libcdsb_list_node {
 | 
			
		||||
    vtype   type;
 | 
			
		||||
} lnode_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ainline(void libcdsb_builtin_init(list_t* x, vnode_t v, vtype t)) {
 | 
			
		||||
    lnode_t* node = malloc(sizeof(*node));
 | 
			
		||||
 | 
			
		||||
    node->next = nullptr;
 | 
			
		||||
    node->prev = nullptr;
 | 
			
		||||
    node->node = v;
 | 
			
		||||
    node->type = t;
 | 
			
		||||
 | 
			
		||||
    x->first = node;
 | 
			
		||||
    x->last  = node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ainline(void libcdsb_builtin_push(list_t* x, vnode_t v, vtype t)) {
 | 
			
		||||
    lnode_t* node = malloc(sizeof(*node));
 | 
			
		||||
 | 
			
		||||
    node->next = nullptr;
 | 
			
		||||
    node->prev = x->last;
 | 
			
		||||
    node->node = v;
 | 
			
		||||
    node->type = t;
 | 
			
		||||
 | 
			
		||||
    x->last->next = node;
 | 
			
		||||
    x->last       = node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define ldir_dir(cur, d) (&((cur)->prev))[(d)>>1]
 | 
			
		||||
#define ldir_inv(cur, d) (&((cur)->prev))[(d)&1]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -3,9 +3,7 @@
 | 
			
		||||
 | 
			
		||||
#include "include.h"
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
static inline void lnode_swap(lnode_t* s0, lnode_t* s1) {
 | 
			
		||||
static inline void libcdsb_builtin_swap(lnode_t* s0, lnode_t* s1) {
 | 
			
		||||
    vnode_t v = s0->node;
 | 
			
		||||
    vtype   t = s0->type;
 | 
			
		||||
 | 
			
		||||
@ -16,6 +14,7 @@ static inline void lnode_swap(lnode_t* s0, lnode_t* s1) {
 | 
			
		||||
    s1->type = t;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
void list_sort(list_t* x) {
 | 
			
		||||
    stack_t  z;
 | 
			
		||||
@ -37,12 +36,12 @@ void list_sort(list_t* x) {
 | 
			
		||||
            for (lnode_t* c = l; c != r; c = c->next) {
 | 
			
		||||
                if (lnode_compare(c, r) <= 0) {
 | 
			
		||||
                    p = (is_null(p)) ? l : p->next;
 | 
			
		||||
                    lnode_swap(p, c);
 | 
			
		||||
                    libcdsb_builtin_swap(p, c);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            p = (is_null(p)) ? l : p->next;
 | 
			
		||||
            lnode_swap(p, r);
 | 
			
		||||
            libcdsb_builtin_swap(p, r);
 | 
			
		||||
 | 
			
		||||
            stack_push(&z, r);
 | 
			
		||||
            stack_push(&z, p->next);
 | 
			
		||||
@ -58,7 +57,7 @@ void list_reverse(list_t* x) {
 | 
			
		||||
    lnode_t *r = x->last;
 | 
			
		||||
 | 
			
		||||
    while (l != r) {
 | 
			
		||||
        lnode_swap(l, r);
 | 
			
		||||
        libcdsb_builtin_swap(l, r);
 | 
			
		||||
        if ((r = r->prev) == l)
 | 
			
		||||
            break;
 | 
			
		||||
        l = l->next;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										100
									
								
								src/map/access.c
									
									
									
									
									
								
							
							
						
						
									
										100
									
								
								src/map/access.c
									
									
									
									
									
								
							@ -3,6 +3,48 @@
 | 
			
		||||
 | 
			
		||||
#include "include.h"
 | 
			
		||||
 | 
			
		||||
static int libcdsb_builtin_foreach(map_t* x, void* data, map_access_callback callback) {
 | 
			
		||||
    stack_t z, *top, *bot, *cur;
 | 
			
		||||
    mnode_t* n;
 | 
			
		||||
    int  r = 0;
 | 
			
		||||
 | 
			
		||||
    memset(&z, 0, sizeof(z));
 | 
			
		||||
 | 
			
		||||
    if (rbnode_is_empty(z.value = x->root))
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    for (top = bot = &z;;) {
 | 
			
		||||
        for (cur = bot;;) {
 | 
			
		||||
 | 
			
		||||
            n = top->value;
 | 
			
		||||
 | 
			
		||||
            if (!mnode_is_empty(n->left))  cur = stack_insert(cur, n->left);
 | 
			
		||||
            if (!mnode_is_empty(n->right)) cur = stack_insert(cur, n->right);
 | 
			
		||||
 | 
			
		||||
            if (!r) {
 | 
			
		||||
                r = callback(vnode_peek(&n->key, x->type), x->type, vnode_peek(&n->value, n->type), n->type, data);
 | 
			
		||||
            } else {
 | 
			
		||||
                stack_flush(&z);
 | 
			
		||||
                return r;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (top == bot) {
 | 
			
		||||
                top = top->prev;
 | 
			
		||||
                break;
 | 
			
		||||
            } else top = top->prev;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!is_null(top)) {
 | 
			
		||||
            while (!is_null(bot->prev)) bot = bot->prev;
 | 
			
		||||
        } else break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    stack_flush(&z);
 | 
			
		||||
    return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
int libcdsb_map_find(map_t* x, const void* k, vtype t, void* _, map_access_callback callback, bool cut) {
 | 
			
		||||
    mnode_t*  c;
 | 
			
		||||
    void   *key;
 | 
			
		||||
@ -32,47 +74,41 @@ int libcdsb_map_find(map_t* x, const void* k, vtype t, void* _, map_access_callb
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int libcdsb_map_foreach(map_t* x, void* dt, map_access_callback callback, bool flush) {
 | 
			
		||||
    stack_t  z;
 | 
			
		||||
    int      r;
 | 
			
		||||
    mnode_t* c;
 | 
			
		||||
int libcdsb_map_foreach(map_t* x, void* data, map_access_callback callback, rbforeach_t type, bool flush) {
 | 
			
		||||
    bool reverse;
 | 
			
		||||
    stack_t iter;
 | 
			
		||||
    mnode_t*   n;
 | 
			
		||||
    int    r = 0;
 | 
			
		||||
 | 
			
		||||
    stack_init(&z);
 | 
			
		||||
    stack_push(&z, x->root);
 | 
			
		||||
    reverse = type&RBFOREACH_REVERSE;
 | 
			
		||||
 | 
			
		||||
    r = 0;
 | 
			
		||||
    switch (type&(RBFOREACH_INORDER|RBFOREACH_PREORDER|RBFOREACH_POSTORDER|RBFOREACH_BREADTH_FIRST)) {
 | 
			
		||||
        case RBFOREACH_INORDER:       iter = miter_inorder  (&x->root, reverse); break;
 | 
			
		||||
        case RBFOREACH_PREORDER:      iter = miter_preorder (&x->root, reverse); break;
 | 
			
		||||
        case RBFOREACH_POSTORDER:     iter = miter_postorder(&x->root, reverse); break;
 | 
			
		||||
 | 
			
		||||
    if (mnode_is_empty(x->root))
 | 
			
		||||
        return 0;
 | 
			
		||||
        default:
 | 
			
		||||
        case RBFOREACH_BREADTH_FIRST: if (reverse || flush) {
 | 
			
		||||
                                          iter = miter_breath_first(&x->root, type&RBFOREACH_REVERSE);
 | 
			
		||||
                                          break;
 | 
			
		||||
                                      } else return libcdsb_builtin_foreach(x, data, callback);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    while ((c = stack_pop(&z))) {
 | 
			
		||||
        if ((r = callback(vnode_peek(&c->key, x->type), x->type, vnode_peek(&c->value, c->type), c->type, dt)))
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        if (!mnode_is_empty(c->right)) stack_push(&z, c->right);
 | 
			
		||||
        if (!mnode_is_empty(c->left))  stack_push(&z, c->left);
 | 
			
		||||
    while ((n = stack_pop(&iter))) {
 | 
			
		||||
        if (!r) {
 | 
			
		||||
            r = callback(vnode_peek(&n->key, x->type), x->type, vnode_peek(&n->value, n->type), n->type, data);
 | 
			
		||||
        } else if (!flush) {
 | 
			
		||||
            stack_flush(&iter);
 | 
			
		||||
            return r;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (flush) {
 | 
			
		||||
            vnode_free(&c->key,   x->type);
 | 
			
		||||
            vnode_free(&c->value, c->type);
 | 
			
		||||
            free(c);
 | 
			
		||||
            vnode_free(&n->value, x->type);
 | 
			
		||||
            free(n);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (flush) {
 | 
			
		||||
        while (c) {
 | 
			
		||||
            if (!mnode_is_empty(c->right)) stack_push(&z, c->right);
 | 
			
		||||
            if (!mnode_is_empty(c->left))  stack_push(&z, c->left);
 | 
			
		||||
 | 
			
		||||
            vnode_free(&c->key,   x->type);
 | 
			
		||||
            vnode_free(&c->value, c->type);
 | 
			
		||||
            free(c);
 | 
			
		||||
 | 
			
		||||
            c = stack_pop(&z);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        memset(x, 0, sizeof(*x));
 | 
			
		||||
    } else stack_flush(&z);
 | 
			
		||||
    if (flush) x->root = mnode_empty;
 | 
			
		||||
 | 
			
		||||
    return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -3,7 +3,7 @@
 | 
			
		||||
 | 
			
		||||
#include "include.h"
 | 
			
		||||
 | 
			
		||||
static inline int mnode_compare(const mnode_t* s0, const mnode_t* s1, vtype t) {
 | 
			
		||||
static inline int libcdsb_builtin_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;
 | 
			
		||||
@ -35,13 +35,13 @@ int map_compare(const map_t* s0, const map_t* s1) {
 | 
			
		||||
                stack_flush(&z);
 | 
			
		||||
                return mnode_is_empty(c0) ? -1 : 1;
 | 
			
		||||
            }
 | 
			
		||||
        } else if ((cmp = mnode_compare(c0, c1, s0->type))) {
 | 
			
		||||
        } else if ((cmp = libcdsb_builtin_compare(c0, c1, s0->type))) {
 | 
			
		||||
            if (c0->left == c1->right) {  // == mnode_empty
 | 
			
		||||
                          cmp = mnode_compare(c0->right, c1, s0->type);
 | 
			
		||||
                if (!cmp) cmp = mnode_compare(c0, c1->left, s0->type);
 | 
			
		||||
                          cmp = libcdsb_builtin_compare(c0->right, c1, s0->type);
 | 
			
		||||
                if (!cmp) cmp = libcdsb_builtin_compare(c0, c1->left, s0->type);
 | 
			
		||||
            } else if (c0->right == c1->left) { // == mnode_empty
 | 
			
		||||
                          cmp = mnode_compare(c0, c1->right, s0->type);
 | 
			
		||||
                if (!cmp) cmp = mnode_compare(c0->left, c1, s0->type);
 | 
			
		||||
                          cmp = libcdsb_builtin_compare(c0, c1->right, s0->type);
 | 
			
		||||
                if (!cmp) cmp = libcdsb_builtin_compare(c0->left, c1, s0->type);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (cmp) {
 | 
			
		||||
 | 
			
		||||
@ -3,7 +3,7 @@
 | 
			
		||||
 | 
			
		||||
#include "include.h"
 | 
			
		||||
 | 
			
		||||
static inline hash_t mnode_hash(const mnode_t* s, vtype t) {
 | 
			
		||||
static inline hash_t libcdsb_builtin_hash(const mnode_t* s, vtype t) {
 | 
			
		||||
    return vnode_hash(&s->key, t) + vnode_hash(&s->value, s->type) + t;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -53,7 +53,7 @@ hash_t map_hash(const map_t* s) {
 | 
			
		||||
        } while (!is_null(c0 = stack_pop(&z)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    v  = mnode_hash(c1, s->type);
 | 
			
		||||
    v  = libcdsb_builtin_hash(c1, s->type);
 | 
			
		||||
    stack_push(&z, s->root->right);
 | 
			
		||||
 | 
			
		||||
    if (!mnode_is_empty(c0 = stack_pop(&z))) {
 | 
			
		||||
@ -64,7 +64,7 @@ hash_t map_hash(const map_t* s) {
 | 
			
		||||
        } while (!is_null(c0 = stack_pop(&z)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    v += mnode_hash(c1, s->type);
 | 
			
		||||
    v += libcdsb_builtin_hash(c1, s->type);
 | 
			
		||||
 | 
			
		||||
    return (hash ^ v) + VTYPE_MAP;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -3,7 +3,7 @@
 | 
			
		||||
 | 
			
		||||
#include "include.h"
 | 
			
		||||
 | 
			
		||||
static inline mnode_t* mnode_duplicate(const mnode_t* s, mnode_t* p, const vtype t) {
 | 
			
		||||
static inline mnode_t* libcdsb_builtin_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);
 | 
			
		||||
@ -26,7 +26,7 @@ map_t map_copy(const map_t* s) {
 | 
			
		||||
    x.type = s->type;
 | 
			
		||||
 | 
			
		||||
    if (!mnode_is_empty(s->root)) {
 | 
			
		||||
        x.root = mnode_duplicate(s->root, mnode_empty, s->type);
 | 
			
		||||
        x.root = libcdsb_builtin_duplicate(s->root, mnode_empty, s->type);
 | 
			
		||||
        stack_push(&z, x.root);
 | 
			
		||||
 | 
			
		||||
        do {
 | 
			
		||||
@ -34,12 +34,12 @@ map_t map_copy(const map_t* s) {
 | 
			
		||||
            mnode_t *p1 = stack_pop(&z);
 | 
			
		||||
 | 
			
		||||
            if (!mnode_is_empty(p1->left)) {
 | 
			
		||||
                p0->left = mnode_duplicate(p1->left, p0, s->type);
 | 
			
		||||
                p0->left = libcdsb_builtin_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);
 | 
			
		||||
                p0->right = libcdsb_builtin_duplicate(p1->right, p0, s->type);
 | 
			
		||||
                stack_push_many(&z, 2, p1->right, p0->right);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -63,7 +63,7 @@ map_t* map_duplicate(const map_t* s) {
 | 
			
		||||
    x->type = s->type;
 | 
			
		||||
 | 
			
		||||
    if (!mnode_is_empty(s->root)) {
 | 
			
		||||
        x->root = mnode_duplicate(s->root, mnode_empty, s->type);
 | 
			
		||||
        x->root = libcdsb_builtin_duplicate(s->root, mnode_empty, s->type);
 | 
			
		||||
        stack_push(&z, x->root);
 | 
			
		||||
 | 
			
		||||
        do {
 | 
			
		||||
@ -71,12 +71,12 @@ map_t* map_duplicate(const map_t* s) {
 | 
			
		||||
            mnode_t *p1 = stack_pop(&z);
 | 
			
		||||
 | 
			
		||||
            if (!mnode_is_empty(p1->left)) {
 | 
			
		||||
                p0->left = mnode_duplicate(p1->left, p0, s->type);
 | 
			
		||||
                p0->left = libcdsb_builtin_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);
 | 
			
		||||
                p0->right = libcdsb_builtin_duplicate(p1->right, p0, s->type);
 | 
			
		||||
                stack_push_many(&z, 2, p1->right, p0->right);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -98,7 +98,7 @@ void map_copy_init(map_t* x, const map_t* s) {
 | 
			
		||||
    x->type = s->type;
 | 
			
		||||
 | 
			
		||||
    if (!mnode_is_empty(s->root)) {
 | 
			
		||||
        x->root = mnode_duplicate(s->root, mnode_empty, s->type);
 | 
			
		||||
        x->root = libcdsb_builtin_duplicate(s->root, mnode_empty, s->type);
 | 
			
		||||
        stack_push(&z, x->root);
 | 
			
		||||
 | 
			
		||||
        do {
 | 
			
		||||
@ -106,12 +106,12 @@ void map_copy_init(map_t* x, const map_t* s) {
 | 
			
		||||
            mnode_t *p1 = stack_pop(&z);
 | 
			
		||||
 | 
			
		||||
            if (!mnode_is_empty(p1->left)) {
 | 
			
		||||
                p0->left = mnode_duplicate(p1->left, p0, s->type);
 | 
			
		||||
                p0->left = libcdsb_builtin_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);
 | 
			
		||||
                p0->right = libcdsb_builtin_duplicate(p1->right, p0, s->type);
 | 
			
		||||
                stack_push_many(&z, 2, p1->right, p0->right);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -27,12 +27,17 @@ static_assert(offsetof(struct libcdsb_rbtree_node, value)   == offsetof(struct l
 | 
			
		||||
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");
 | 
			
		||||
 | 
			
		||||
#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))
 | 
			
		||||
#define mnode_delete(r, n)    (mnode_t*)libcdsb_rbtree_node_delete((rbnode_t**)(r), (rbnode_t*)(n))
 | 
			
		||||
#define mnode_empty           ((mnode_t*)rbnode_empty)
 | 
			
		||||
#define mnode_create(k, p, c) ((mnode_t*)libcdsb_builtin_rbtree_node_create(k, (rbnode_t*)p, c, sizeof(mnode_t)))
 | 
			
		||||
#define mnode_fixup(r, n)     libcdsb_builtin_rbtree_node_fixup((rbnode_t**)(r), (rbnode_t*)(n))
 | 
			
		||||
#define mnode_delete(r, n)    (mnode_t*)libcdsb_builtin_rbtree_node_delete((rbnode_t**)(r), (rbnode_t*)(n))
 | 
			
		||||
 | 
			
		||||
#define mnode_is_empty(n) ((n) == mnode_empty)
 | 
			
		||||
#define mnode_is_root(n)  mnode_is_empty((n)->parent)
 | 
			
		||||
 | 
			
		||||
#define miter_inorder(x, reverse)      rbiter_inorder((void*)x, reverse)
 | 
			
		||||
#define miter_preorder(x, reverse)     rbiter_preorder((void*)x, reverse)
 | 
			
		||||
#define miter_postorder(x, reverse)    rbiter_postorder((void*)x, reverse)
 | 
			
		||||
#define miter_breath_first(x, reverse) rbiter_breath_first((void*)x, reverse)
 | 
			
		||||
 | 
			
		||||
#endif /* LIBCDSB_SRC_MAP_INCLUDE_H */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										196
									
								
								src/rbtree.c
									
									
									
									
									
								
							
							
						
						
									
										196
									
								
								src/rbtree.c
									
									
									
									
									
								
							@ -11,19 +11,12 @@ typedef enum libcdsb_rbtree_node_direction {
 | 
			
		||||
#define rbdir_dir(cur, d) (&((cur)->left))[(d)>>1]
 | 
			
		||||
#define rbdir_inv(cur, d) (&((cur)->left))[(d)&1]
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
#define rotate  libcdsb_builtin_rotate
 | 
			
		||||
#define replace libcdsb_builtin_replace
 | 
			
		||||
#define fixup   libcdsb_builtin_fixup
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
static void libcdsb_builtin_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);
 | 
			
		||||
@ -41,7 +34,8 @@ static inline void rotate(rbnode_t **x, rbnode_t *c, rbdir_t d) {
 | 
			
		||||
    c->parent = n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void replace(rbnode_t** x, rbnode_t* c, rbnode_t* n) {
 | 
			
		||||
 | 
			
		||||
static void libcdsb_builtin_replace(rbnode_t** x, rbnode_t* c, rbnode_t* n) {
 | 
			
		||||
    if (!rbnode_is_root(c)) {
 | 
			
		||||
        if (c->parent->left == c) {
 | 
			
		||||
            c->parent->left = n;
 | 
			
		||||
@ -51,10 +45,7 @@ static inline void replace(rbnode_t** x, rbnode_t* c, rbnode_t* n) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void delete_fixup(rbnode_t** x, rbnode_t* n) {
 | 
			
		||||
static void libcdsb_builtin_fixup(rbnode_t** x, rbnode_t* n) {
 | 
			
		||||
    rbdir_t d;
 | 
			
		||||
    rbnode_t *s, *p;
 | 
			
		||||
 | 
			
		||||
@ -98,8 +89,16 @@ static void delete_fixup(rbnode_t** x, rbnode_t* n) {
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
rbnode_t LIBCDSB_BUILTIN_RBTREE_NODE_EMPTY[1] = {{
 | 
			
		||||
   .colored = 0,
 | 
			
		||||
   .value   = 0,
 | 
			
		||||
   .parent  = rbnode_empty,
 | 
			
		||||
   .left    = rbnode_empty,
 | 
			
		||||
   .right   = rbnode_empty
 | 
			
		||||
}};
 | 
			
		||||
 | 
			
		||||
rbnode_t* libcdsb_rbtree_node_delete(rbnode_t** x, rbnode_t* c) {
 | 
			
		||||
 | 
			
		||||
rbnode_t* libcdsb_builtin_rbtree_node_delete(rbnode_t** x, rbnode_t* c) {
 | 
			
		||||
    rbnode_t *n, *t;
 | 
			
		||||
    int s;
 | 
			
		||||
 | 
			
		||||
@ -135,14 +134,14 @@ rbnode_t* libcdsb_rbtree_node_delete(rbnode_t** x, rbnode_t* c) {
 | 
			
		||||
        t->left = c->left;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!s) delete_fixup(x, n);
 | 
			
		||||
    if (!s) fixup(x, n);
 | 
			
		||||
 | 
			
		||||
    return c;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void libcdsb_rbtree_node_fixup(rbnode_t** x, rbnode_t* n) {
 | 
			
		||||
void libcdsb_builtin_rbtree_node_fixup(rbnode_t** x, rbnode_t* n) {
 | 
			
		||||
    rbdir_t d[2];
 | 
			
		||||
    rbnode_t *u, *p, *gp;
 | 
			
		||||
 | 
			
		||||
@ -181,7 +180,7 @@ void libcdsb_rbtree_node_fixup(rbnode_t** x, rbnode_t* n) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void* libcdsb_rbtree_node_create(void* v, rbnode_t* p, int c, int n) {
 | 
			
		||||
void* libcdsb_builtin_rbtree_node_create(void* v, rbnode_t* p, int c, int n) {
 | 
			
		||||
    rbnode_t* x;
 | 
			
		||||
 | 
			
		||||
    x = malloc(n);
 | 
			
		||||
@ -194,3 +193,160 @@ void* libcdsb_rbtree_node_create(void* v, rbnode_t* p, int c, int n) {
 | 
			
		||||
 | 
			
		||||
    return x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
stack_t libcdsb_builtin_rbtree_iter_inorder(rbnode_t** root, bool reverse) {
 | 
			
		||||
    rbnode_t *n, hack;
 | 
			
		||||
    stack_t   z, *bot;
 | 
			
		||||
 | 
			
		||||
    memset(&z, 0, sizeof(z));
 | 
			
		||||
 | 
			
		||||
    if (rbnode_is_empty(*root))
 | 
			
		||||
        return z;
 | 
			
		||||
 | 
			
		||||
    hack.right = *root;
 | 
			
		||||
    n          = &hack;
 | 
			
		||||
 | 
			
		||||
    for (bot = &z;;) {
 | 
			
		||||
        for (;;) {
 | 
			
		||||
            if (rbnode_is_empty(n->right)) {
 | 
			
		||||
 | 
			
		||||
                if (rbnode_is_root(n->parent) || n->parent->left == n) {
 | 
			
		||||
                    n = n->parent;
 | 
			
		||||
                    break;
 | 
			
		||||
                } else n = n->parent;
 | 
			
		||||
 | 
			
		||||
                if (rbnode_is_root(n->parent) || n->parent->left == n) {
 | 
			
		||||
                    n = n->parent;
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                do {
 | 
			
		||||
                    n = n->parent;
 | 
			
		||||
                } while (n->parent->right == n);
 | 
			
		||||
 | 
			
		||||
                n = n->parent;
 | 
			
		||||
            } else {
 | 
			
		||||
                n = n->right;
 | 
			
		||||
 | 
			
		||||
                while (!rbnode_is_empty(n->left))
 | 
			
		||||
                    n = n->left;
 | 
			
		||||
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (rbnode_is_root(n)) {
 | 
			
		||||
                bot = z.prev;
 | 
			
		||||
                z   = *bot;
 | 
			
		||||
 | 
			
		||||
                free(bot);
 | 
			
		||||
 | 
			
		||||
                if (reverse)
 | 
			
		||||
                    stack_reverse(&z);
 | 
			
		||||
 | 
			
		||||
                return z;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        bot = stack_insert(bot, n);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
stack_t libcdsb_builtin_rbtree_iter_preorder(rbnode_t** root, bool reverse) {
 | 
			
		||||
    stack_t z, *cur, *next;
 | 
			
		||||
    rbnode_t *n;
 | 
			
		||||
 | 
			
		||||
    memset(&z, 0, sizeof(z));
 | 
			
		||||
 | 
			
		||||
    if (rbnode_is_empty(*root))
 | 
			
		||||
        return z;
 | 
			
		||||
 | 
			
		||||
    z.value = *root;
 | 
			
		||||
    cur     = &z;
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
        n = (next = cur)->value;
 | 
			
		||||
 | 
			
		||||
        if (!rbnode_is_empty(n->left)) next = stack_insert(cur,  n->left);
 | 
			
		||||
        if (!rbnode_is_empty(n->right))       stack_insert(next, n->right);
 | 
			
		||||
    } while (!is_null(cur = cur->prev));
 | 
			
		||||
 | 
			
		||||
    if (reverse)
 | 
			
		||||
        stack_reverse(&z);
 | 
			
		||||
 | 
			
		||||
    return z;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
stack_t libcdsb_builtin_rbtree_iter_postorder(rbnode_t** root, bool reverse) {
 | 
			
		||||
    rbnode_t *p, *n;
 | 
			
		||||
    stack_t z, *bot;
 | 
			
		||||
 | 
			
		||||
    bot     = &z;
 | 
			
		||||
    z.prev  = 0;
 | 
			
		||||
    z.value = 0;
 | 
			
		||||
 | 
			
		||||
    if (rbnode_is_empty(p = *root))
 | 
			
		||||
        return z;
 | 
			
		||||
 | 
			
		||||
    goto mid_;
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
        if (n->parent->right != n && !rbnode_is_empty(n->parent->right)) {
 | 
			
		||||
            p = n->parent->right;
 | 
			
		||||
            do { mid_:
 | 
			
		||||
                n = p;
 | 
			
		||||
                p = !rbnode_is_empty(p->left) ? p->left : p->right;
 | 
			
		||||
            } while (!rbnode_is_empty(p));
 | 
			
		||||
        } else n = n->parent;
 | 
			
		||||
 | 
			
		||||
        bot = stack_insert(bot, n);
 | 
			
		||||
    } while (!rbnode_is_root(n));
 | 
			
		||||
 | 
			
		||||
    bot = z.prev;
 | 
			
		||||
    z   = *bot;
 | 
			
		||||
 | 
			
		||||
    free(bot);
 | 
			
		||||
 | 
			
		||||
    if (reverse)
 | 
			
		||||
        stack_reverse(&z);
 | 
			
		||||
 | 
			
		||||
    return z;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
stack_t libcdsb_builtin_rbtree_iter_breath_first(rbnode_t** root, bool reverse) {
 | 
			
		||||
 | 
			
		||||
    stack_t z, *top, *bot, *cur;
 | 
			
		||||
    rbnode_t* n;
 | 
			
		||||
 | 
			
		||||
    memset(&z, 0, sizeof(z));
 | 
			
		||||
 | 
			
		||||
    if (rbnode_is_empty(z.value = *root))
 | 
			
		||||
        return z;
 | 
			
		||||
 | 
			
		||||
    for (top = bot = &z;;) {
 | 
			
		||||
        for (cur = bot;;) {
 | 
			
		||||
 | 
			
		||||
            n = top->value;
 | 
			
		||||
 | 
			
		||||
            if (!rbnode_is_empty(n->left))  cur = stack_insert(cur, n->left);
 | 
			
		||||
            if (!rbnode_is_empty(n->right)) cur = stack_insert(cur, n->right);
 | 
			
		||||
 | 
			
		||||
            if (top == bot) {
 | 
			
		||||
                top = top->prev;
 | 
			
		||||
                break;
 | 
			
		||||
            } else top = top->prev;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!is_null(top)) {
 | 
			
		||||
            while (!is_null(bot->prev)) bot = bot->prev;
 | 
			
		||||
        } else break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (reverse)
 | 
			
		||||
        stack_reverse(&z);
 | 
			
		||||
 | 
			
		||||
    return z;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										101
									
								
								src/set/access.c
									
									
									
									
									
								
							
							
						
						
									
										101
									
								
								src/set/access.c
									
									
									
									
									
								
							@ -4,6 +4,48 @@
 | 
			
		||||
#include "../../include/set.h"
 | 
			
		||||
#include "../__internal/rbtree.h"
 | 
			
		||||
 | 
			
		||||
static int libcdsb_builtin_foreach(set_t* x, void* data, vset_access_callback callback) {
 | 
			
		||||
    stack_t z, *top, *bot, *cur;
 | 
			
		||||
    rbnode_t* n;
 | 
			
		||||
    int   r = 0;
 | 
			
		||||
 | 
			
		||||
    memset(&z, 0, sizeof(z));
 | 
			
		||||
 | 
			
		||||
    if (rbnode_is_empty(z.value = x->root))
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    for (top = bot = &z;;) {
 | 
			
		||||
        for (cur = bot;;) {
 | 
			
		||||
 | 
			
		||||
            n = top->value;
 | 
			
		||||
 | 
			
		||||
            if (!rbnode_is_empty(n->left))  cur = stack_insert(cur, n->left);
 | 
			
		||||
            if (!rbnode_is_empty(n->right)) cur = stack_insert(cur, n->right);
 | 
			
		||||
 | 
			
		||||
            if (!r) {
 | 
			
		||||
                r = callback(vnode_peek(&n->value, x->type), x->type, data);
 | 
			
		||||
            } else {
 | 
			
		||||
                stack_flush(&z);
 | 
			
		||||
                return r;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (top == bot) {
 | 
			
		||||
                top = top->prev;
 | 
			
		||||
                break;
 | 
			
		||||
            } else top = top->prev;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!is_null(top)) {
 | 
			
		||||
            while (!is_null(bot->prev)) bot = bot->prev;
 | 
			
		||||
        } else break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    stack_flush(&z);
 | 
			
		||||
    return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
int libcdsb_vset_find(vtype_set* x, const void* v, vtype t, void* _, vset_access_callback callback, bool cut) {
 | 
			
		||||
    rbnode_t* c;
 | 
			
		||||
    void   *val;
 | 
			
		||||
@ -32,46 +74,41 @@ int libcdsb_vset_find(vtype_set* x, const void* v, vtype t, void* _, vset_access
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int libcdsb_vset_foreach(set_t* x, void* data, vset_access_callback callback, bool flush) {
 | 
			
		||||
    stack_t   z;
 | 
			
		||||
    int       r;
 | 
			
		||||
    rbnode_t* c;
 | 
			
		||||
int libcdsb_vset_foreach(set_t* x, void* data, vset_access_callback callback, rbforeach_t type, bool flush) {
 | 
			
		||||
    bool reverse;
 | 
			
		||||
    stack_t iter;
 | 
			
		||||
    rbnode_t*  n;
 | 
			
		||||
    int    r = 0;
 | 
			
		||||
 | 
			
		||||
    stack_init(&z);
 | 
			
		||||
    stack_push(&z, x->root);
 | 
			
		||||
    reverse = type&RBFOREACH_REVERSE;
 | 
			
		||||
 | 
			
		||||
    r = 0;
 | 
			
		||||
    switch (type&(RBFOREACH_INORDER|RBFOREACH_PREORDER|RBFOREACH_POSTORDER|RBFOREACH_BREADTH_FIRST)) {
 | 
			
		||||
        case RBFOREACH_INORDER:       iter = rbiter_inorder  (&x->root, reverse); break;
 | 
			
		||||
        case RBFOREACH_PREORDER:      iter = rbiter_preorder (&x->root, reverse); break;
 | 
			
		||||
        case RBFOREACH_POSTORDER:     iter = rbiter_postorder(&x->root, reverse); break;
 | 
			
		||||
        
 | 
			
		||||
        default:
 | 
			
		||||
        case RBFOREACH_BREADTH_FIRST: if (reverse || flush) {
 | 
			
		||||
                                          iter = rbiter_breath_first(&x->root, type&RBFOREACH_REVERSE);
 | 
			
		||||
                                          break;
 | 
			
		||||
                                      } else return libcdsb_builtin_foreach(x, data, callback);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (rbnode_is_empty(x->root))
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    while ((c = stack_pop(&z))) {
 | 
			
		||||
        if ((r = callback(vnode_peek(&c->value, x->type), x->type, data)))
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        if (!rbnode_is_empty(c->right)) stack_push(&z, c->right);
 | 
			
		||||
        if (!rbnode_is_empty(c->left))  stack_push(&z, c->left);
 | 
			
		||||
    while ((n = stack_pop(&iter))) {
 | 
			
		||||
        if (!r) {
 | 
			
		||||
            r = callback(vnode_peek(&n->value, x->type), x->type, data);
 | 
			
		||||
        } else if (!flush) {
 | 
			
		||||
            stack_flush(&iter);
 | 
			
		||||
            return r;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (flush) {
 | 
			
		||||
            vnode_free(&c->value, x->type);
 | 
			
		||||
            free(c);
 | 
			
		||||
            vnode_free(&n->value, x->type);
 | 
			
		||||
            free(n);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (flush) {
 | 
			
		||||
        while (c) {
 | 
			
		||||
            if (!rbnode_is_empty(c->right)) stack_push(&z, c->right);
 | 
			
		||||
            if (!rbnode_is_empty(c->left))  stack_push(&z, c->left);
 | 
			
		||||
 | 
			
		||||
            vnode_free(&c->value, x->type);
 | 
			
		||||
            free(c);
 | 
			
		||||
 | 
			
		||||
            c = stack_pop(&z);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        memset(x, 0, sizeof(*x));
 | 
			
		||||
    } else stack_flush(&z);
 | 
			
		||||
    if (flush) x->root = rbnode_empty;
 | 
			
		||||
 | 
			
		||||
    return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@
 | 
			
		||||
#include "../../include/set.h"
 | 
			
		||||
#include "../__internal/rbtree.h"
 | 
			
		||||
 | 
			
		||||
static inline int rbnode_compare(const rbnode_t* s0, const rbnode_t* s1, vtype t) {
 | 
			
		||||
static inline int libcdsb_builtin_compare(const rbnode_t* s0, const rbnode_t* s1, vtype t) {
 | 
			
		||||
    return vnode_compare(s0->value, t, s1->value, t);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -34,13 +34,13 @@ int vset_compare(const set_t* s0, const set_t* s1) {
 | 
			
		||||
                stack_flush(&z);
 | 
			
		||||
                return rbnode_is_empty(c0) ? -1 : 1;
 | 
			
		||||
            }
 | 
			
		||||
        } else if ((cmp = rbnode_compare(c0, c1, s0->type))) {
 | 
			
		||||
        } else if ((cmp = libcdsb_builtin_compare(c0, c1, s0->type))) {
 | 
			
		||||
            if (c0->left == c1->right) {  // == rbnode_empty
 | 
			
		||||
                          cmp = rbnode_compare(c0->right, c1, s0->type);
 | 
			
		||||
                if (!cmp) cmp = rbnode_compare(c0, c1->left, s0->type);
 | 
			
		||||
                          cmp = libcdsb_builtin_compare(c0->right, c1, s0->type);
 | 
			
		||||
                if (!cmp) cmp = libcdsb_builtin_compare(c0, c1->left, s0->type);
 | 
			
		||||
            } else if (c0->right == c1->left) { // == rbnode_empty
 | 
			
		||||
                          cmp = rbnode_compare(c0, c1->right, s0->type);
 | 
			
		||||
                if (!cmp) cmp = rbnode_compare(c0->left, c1, s0->type);
 | 
			
		||||
                          cmp = libcdsb_builtin_compare(c0, c1->right, s0->type);
 | 
			
		||||
                if (!cmp) cmp = libcdsb_builtin_compare(c0->left, c1, s0->type);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (cmp) {
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@
 | 
			
		||||
#include "../../include/set.h"
 | 
			
		||||
#include "../__internal/rbtree.h"
 | 
			
		||||
 | 
			
		||||
static inline hash_t rbnode_hash(const rbnode_t* s, vtype t) {
 | 
			
		||||
static inline hash_t libcdsb_builtin_hash(const rbnode_t* s, vtype t) {
 | 
			
		||||
    return vnode_hash(&s->value, t);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -54,7 +54,7 @@ hash_t vset_hash(const set_t* s) {
 | 
			
		||||
        } while (!is_null(c0 = stack_pop(&z)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    v  = rbnode_hash(c1, s->type);
 | 
			
		||||
    v  = libcdsb_builtin_hash(c1, s->type);
 | 
			
		||||
    stack_push(&z, s->root->right);
 | 
			
		||||
 | 
			
		||||
    if (!rbnode_is_empty(c0 = stack_pop(&z))) {
 | 
			
		||||
@ -65,7 +65,7 @@ hash_t vset_hash(const set_t* s) {
 | 
			
		||||
        } while (!is_null(c0 = stack_pop(&z)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    v += rbnode_hash(c1, s->type);
 | 
			
		||||
    v += libcdsb_builtin_hash(c1, s->type);
 | 
			
		||||
 | 
			
		||||
    return (hash ^ v) + VTYPE_SET;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -27,6 +27,7 @@ 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;
 | 
			
		||||
@ -52,6 +53,7 @@ void libcdsb_stack_push_many(stack_t* x, size_t c, ...) {
 | 
			
		||||
    va_end(args);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void* libcdsb_stack_pop(stack_t* x) {
 | 
			
		||||
 | 
			
		||||
    stack_t* n;
 | 
			
		||||
@ -70,14 +72,50 @@ void* libcdsb_stack_pop(stack_t* x) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void libcdsb_stack_flush(stack_t* stack) {
 | 
			
		||||
void libcdsb_stack_reverse(stack_t* x) {
 | 
			
		||||
 | 
			
		||||
    stack_t z, *iter, *n, copy;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    if (x->prev) {
 | 
			
		||||
        z.prev  = 0;
 | 
			
		||||
        z.value = x->value;
 | 
			
		||||
        iter    = x->prev;
 | 
			
		||||
 | 
			
		||||
        while (iter->prev) {
 | 
			
		||||
            n = iter;
 | 
			
		||||
            iter = n->prev;
 | 
			
		||||
 | 
			
		||||
            copy.prev  = z.prev;
 | 
			
		||||
            copy.value = z.value;
 | 
			
		||||
 | 
			
		||||
            z.prev  = n;
 | 
			
		||||
            z.value = n->value;
 | 
			
		||||
 | 
			
		||||
            n->prev  = copy.prev;
 | 
			
		||||
            n->value = copy.value;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        copy.prev  = z.prev;
 | 
			
		||||
        copy.value = z.value;
 | 
			
		||||
 | 
			
		||||
        x->prev  = iter;
 | 
			
		||||
        x->value = iter->value;
 | 
			
		||||
 | 
			
		||||
        iter->prev  = copy.prev;
 | 
			
		||||
        iter->value = copy.value;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void libcdsb_stack_flush(stack_t* x) {
 | 
			
		||||
    stack_t* c;
 | 
			
		||||
 | 
			
		||||
    while (stack->prev) {
 | 
			
		||||
        c = stack->prev;
 | 
			
		||||
        stack->prev = c->prev;
 | 
			
		||||
    while (x->prev) {
 | 
			
		||||
        c = x->prev;
 | 
			
		||||
        x->prev = c->prev;
 | 
			
		||||
        free(c);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    stack->value = 0;
 | 
			
		||||
    x->value = 0;
 | 
			
		||||
}
 | 
			
		||||
@ -8,14 +8,14 @@
 | 
			
		||||
#ifndef LIBCDSB_SRC_STRING_INCLUDE_H
 | 
			
		||||
#define LIBCDSB_SRC_STRING_INCLUDE_H
 | 
			
		||||
 | 
			
		||||
ainline(char* next_char(char* s)) {
 | 
			
		||||
ainline(char* libcdsb_builtin_next_char(char* s)) {
 | 
			
		||||
    int cs = charsize(s);
 | 
			
		||||
 | 
			
		||||
    if (cs) return s + cs;
 | 
			
		||||
    return ++s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ainline(char* prev_char(char* s)) {
 | 
			
		||||
ainline(char* libcdsb_builtin_prev_char(char* s)) {
 | 
			
		||||
 | 
			
		||||
    if (*(--s)&0x80) {
 | 
			
		||||
        char* p = s;
 | 
			
		||||
@ -29,4 +29,7 @@ ainline(char* prev_char(char* s)) {
 | 
			
		||||
    return s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define next_char libcdsb_builtin_next_char
 | 
			
		||||
#define prev_char libcdsb_builtin_prev_char
 | 
			
		||||
 | 
			
		||||
#endif /* LIBCDSB_SRC_STRING_INCLUDE_H */
 | 
			
		||||
 | 
			
		||||
@ -3,7 +3,7 @@
 | 
			
		||||
 | 
			
		||||
#include "include.h"
 | 
			
		||||
 | 
			
		||||
static void string_replace_builtin(str_t* x, char* p, size_t n, const char* v, size_t vn) {
 | 
			
		||||
static void libcdsb_builtin_replace(str_t* x, char* p, size_t n, const char* v, size_t vn) {
 | 
			
		||||
    if (n != vn) {
 | 
			
		||||
        size_t l = strlen(x->buffer);
 | 
			
		||||
 | 
			
		||||
@ -75,7 +75,7 @@ size_t string_to_lower(str_t* x) {
 | 
			
		||||
                es = tochar_unicode(ps, uc1);
 | 
			
		||||
 | 
			
		||||
                if (!is_null(es)) {
 | 
			
		||||
                    string_replace_builtin(x, p, e-p, ps, es-ps);
 | 
			
		||||
                    libcdsb_builtin_replace(x, p, e-p, ps, es-ps);
 | 
			
		||||
                    ++n;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@ -111,7 +111,7 @@ size_t string_to_upper(str_t* x) {
 | 
			
		||||
                es = tochar_unicode(ps, uc1);
 | 
			
		||||
 | 
			
		||||
                if (!is_null(es)) {
 | 
			
		||||
                    string_replace_builtin(x, p, e-p, ps, es-ps);
 | 
			
		||||
                    libcdsb_builtin_replace(x, p, e-p, ps, es-ps);
 | 
			
		||||
                    ++n;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@ -145,7 +145,7 @@ size_t string_capitalize(str_t* x) {
 | 
			
		||||
            es = tochar_unicode(ps, uc1);
 | 
			
		||||
 | 
			
		||||
            if (!is_null(es)) {
 | 
			
		||||
                string_replace_builtin(x, p, e-p, ps, es-ps);
 | 
			
		||||
                libcdsb_builtin_replace(x, p, e-p, ps, es-ps);
 | 
			
		||||
                ++n;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@ -163,7 +163,7 @@ size_t string_capitalize(str_t* x) {
 | 
			
		||||
                es = tochar_unicode(ps, uc1);
 | 
			
		||||
 | 
			
		||||
                if (!is_null(es)) {
 | 
			
		||||
                    string_replace_builtin(x, p, e-p, ps, es-ps);
 | 
			
		||||
                    libcdsb_builtin_replace(x, p, e-p, ps, es-ps);
 | 
			
		||||
                    ++n;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -4,8 +4,6 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include "__internal/include.h"
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
#define sh__(a) #a
 | 
			
		||||
#define s__(a) sh__(a)
 | 
			
		||||
 | 
			
		||||
@ -19,14 +17,14 @@
 | 
			
		||||
    double:      "%."s__(DBL_DIG)"lg",\
 | 
			
		||||
    long double: "%."s__(LDBL_DIG)"Lg")
 | 
			
		||||
 | 
			
		||||
#define stringify(v) sprintf(STRINGIFY_BUFFER[STRINGIFY_BUFFER_POS], fstring(v), (v))
 | 
			
		||||
#define stringify(v) sprintf(LIBCDSB_BUILTIN_BUFFER[LIBCDSB_BUILTIN_COUNTER], fstring(v), (v))
 | 
			
		||||
 | 
			
		||||
static _Thread_local int  STRINGIFY_BUFFER_POS = 0;
 | 
			
		||||
static _Thread_local char STRINGIFY_BUFFER[16][64];
 | 
			
		||||
static _Thread_local int  LIBCDSB_BUILTIN_COUNTER = 0;
 | 
			
		||||
static _Thread_local char LIBCDSB_BUILTIN_BUFFER[16][64];
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
const size_t LIBCDSB_VTYPE_SIZES[19] = {
 | 
			
		||||
const size_t LIBCDSB_BUILTIN_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),
 | 
			
		||||
@ -35,7 +33,6 @@ const size_t LIBCDSB_VTYPE_SIZES[19] = {
 | 
			
		||||
    sizeof(list_t), sizeof(set_t), sizeof(dict_t)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
const char* libcdsb_vtype_name(vtype t) {
 | 
			
		||||
    switch (t) {
 | 
			
		||||
@ -70,8 +67,8 @@ const char* libcdsb_vtype_stringify(const void* v, vtype t) {
 | 
			
		||||
    if (t == VTYPE_BOOLEAN) return (*(vtype_bool*)v) ? "true" : "false";
 | 
			
		||||
    if (t == VTYPE_STRING)  return *(char**)v;
 | 
			
		||||
 | 
			
		||||
    if (STRINGIFY_BUFFER_POS > 15)
 | 
			
		||||
        STRINGIFY_BUFFER_POS = 0;
 | 
			
		||||
    if (LIBCDSB_BUILTIN_COUNTER > 15)
 | 
			
		||||
        LIBCDSB_BUILTIN_COUNTER = 0;
 | 
			
		||||
 | 
			
		||||
    switch (t) {
 | 
			
		||||
        case    VTYPE_INT8: stringify(*(  s8_t*)v); break;
 | 
			
		||||
@ -83,25 +80,25 @@ const char* libcdsb_vtype_stringify(const void* v, vtype t) {
 | 
			
		||||
        case  VTYPE_UINT32: stringify(*( u32_t*)v); break;
 | 
			
		||||
        case  VTYPE_UINT64: stringify(*( u64_t*)v); break;
 | 
			
		||||
        case   VTYPE_FLOAT: if (abs(*(fl_t*)v) <= FLT_EPSILON) {
 | 
			
		||||
                                STRINGIFY_BUFFER[STRINGIFY_BUFFER_POS][0] = 0x30;
 | 
			
		||||
                                STRINGIFY_BUFFER[STRINGIFY_BUFFER_POS][1] = 0x00;
 | 
			
		||||
                                LIBCDSB_BUILTIN_BUFFER[LIBCDSB_BUILTIN_COUNTER][0] = 0x30;
 | 
			
		||||
                                LIBCDSB_BUILTIN_BUFFER[LIBCDSB_BUILTIN_COUNTER][1] = 0x00;
 | 
			
		||||
                            } else stringify(*(fl_t*)v);
 | 
			
		||||
                     break;
 | 
			
		||||
        case  VTYPE_DOUBLE: if (abs(*(dbl_t*)v) <= DBL_EPSILON) {
 | 
			
		||||
                                STRINGIFY_BUFFER[STRINGIFY_BUFFER_POS][0] = 0x30;
 | 
			
		||||
                                STRINGIFY_BUFFER[STRINGIFY_BUFFER_POS][1] = 0x00;
 | 
			
		||||
                                LIBCDSB_BUILTIN_BUFFER[LIBCDSB_BUILTIN_COUNTER][0] = 0x30;
 | 
			
		||||
                                LIBCDSB_BUILTIN_BUFFER[LIBCDSB_BUILTIN_COUNTER][1] = 0x00;
 | 
			
		||||
                            } else stringify(*(dbl_t*)v);
 | 
			
		||||
                     break;
 | 
			
		||||
        case VTYPE_LDOUBLE: if (abs(*(ldbl_t*)v) <= LDBL_EPSILON) {
 | 
			
		||||
                                STRINGIFY_BUFFER[STRINGIFY_BUFFER_POS][0] = 0x30;
 | 
			
		||||
                                STRINGIFY_BUFFER[STRINGIFY_BUFFER_POS][1] = 0x00;
 | 
			
		||||
                                LIBCDSB_BUILTIN_BUFFER[LIBCDSB_BUILTIN_COUNTER][0] = 0x30;
 | 
			
		||||
                                LIBCDSB_BUILTIN_BUFFER[LIBCDSB_BUILTIN_COUNTER][1] = 0x00;
 | 
			
		||||
                            } else stringify(*(ldbl_t*)v);
 | 
			
		||||
                     break;
 | 
			
		||||
        case VTYPE_POINTER: sprintf(STRINGIFY_BUFFER[STRINGIFY_BUFFER_POS], (sizeof(void*) == 8) ? "0x%016lx" : "0x%08x", (uintptr_t)*(void**)v); break;
 | 
			
		||||
        case VTYPE_POINTER: sprintf(LIBCDSB_BUILTIN_BUFFER[LIBCDSB_BUILTIN_COUNTER], (sizeof(void*) == 8) ? "0x%016lx" : "0x%08x", (uintptr_t)*(void**)v); break;
 | 
			
		||||
 | 
			
		||||
        default: sprintf(STRINGIFY_BUFFER[STRINGIFY_BUFFER_POS], "<%s>", libcdsb_vtype_name(t));
 | 
			
		||||
        default: sprintf(LIBCDSB_BUILTIN_BUFFER[LIBCDSB_BUILTIN_COUNTER], "<%s>", libcdsb_vtype_name(t));
 | 
			
		||||
          break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return STRINGIFY_BUFFER[STRINGIFY_BUFFER_POS++];
 | 
			
		||||
    return LIBCDSB_BUILTIN_BUFFER[LIBCDSB_BUILTIN_COUNTER++];
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								src/vnode.c
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								src/vnode.c
									
									
									
									
									
								
							@ -5,7 +5,7 @@
 | 
			
		||||
#include "__internal/vnode.h"
 | 
			
		||||
#include "../include/string.h"
 | 
			
		||||
 | 
			
		||||
static vtype internal_round(u64_t* x, ldbl_t v) {
 | 
			
		||||
static vtype libcdsb_builtin_round(u64_t* x, ldbl_t v) {
 | 
			
		||||
    if (v > 0) {
 | 
			
		||||
        *x = (u64_t)(v + 0.5);
 | 
			
		||||
        return VTYPE_UINT64;
 | 
			
		||||
@ -15,18 +15,16 @@ static vtype internal_round(u64_t* x, ldbl_t v) {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static vnode_t create_value(vtype xt, const void* v, vtype t) {
 | 
			
		||||
static vnode_t libcdsb_builtin_create_value(vtype xt, const void* v, vtype t) {
 | 
			
		||||
    var_t _;
 | 
			
		||||
 | 
			
		||||
    if (t == VTYPE_FLOAT)  {
 | 
			
		||||
        t = internal_round(&_.u64, *(fl_t*)v);
 | 
			
		||||
        t = libcdsb_builtin_round(&_.u64, *(fl_t*)v);
 | 
			
		||||
    } else if (t == VTYPE_DOUBLE) {
 | 
			
		||||
        t = internal_round(&_.u64, *(dbl_t*)v);
 | 
			
		||||
        t = libcdsb_builtin_round(&_.u64, *(dbl_t*)v);
 | 
			
		||||
    } else if (t == VTYPE_LDOUBLE) {
 | 
			
		||||
        t = internal_round(&_.u64, *(ldbl_t*)v);
 | 
			
		||||
        t = libcdsb_builtin_round(&_.u64, *(ldbl_t*)v);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (sizeof(void*) == 8) {
 | 
			
		||||
@ -85,7 +83,7 @@ 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 libcdsb_builtin_create_float(vtype xt, const void* v, vtype t) {
 | 
			
		||||
    var_t _;
 | 
			
		||||
 | 
			
		||||
    if        (t == VTYPE_UINT8 || t == VTYPE_BOOLEAN ) {
 | 
			
		||||
@ -131,11 +129,9 @@ static vnode_t create_float(vtype xt, const void* v, vtype t) {
 | 
			
		||||
    return _.ptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
vnode_t libcdsb_vnode_create(const void* v, vtype t) {
 | 
			
		||||
vnode_t libcdsb_builtin_vnode_create(const void* v, vtype t) {
 | 
			
		||||
    var_t _ = { .ptr = 0 };
 | 
			
		||||
 | 
			
		||||
    switch (t) { default: abort();
 | 
			
		||||
@ -198,10 +194,7 @@ vnode_t libcdsb_vnode_create(const void* v, vtype t) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void* libcdsb_vnode_peek(const vnode_t* x, vtype t) {
 | 
			
		||||
void* libcdsb_builtin_vnode_peek(const vnode_t* x, vtype t) {
 | 
			
		||||
    switch (t) { default: abort();
 | 
			
		||||
 | 
			
		||||
        case   VTYPE_FLOAT: if (is_permissible(fl_t))   goto vt_; else goto pt_;
 | 
			
		||||
@ -232,7 +225,7 @@ void* libcdsb_vnode_peek(const vnode_t* x, vtype t) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void libcdsb_vnode_free(vnode_t* x, vtype t) {
 | 
			
		||||
void libcdsb_builtin_vnode_free(vnode_t* x, vtype t) {
 | 
			
		||||
 | 
			
		||||
    switch (t) { default: abort();
 | 
			
		||||
 | 
			
		||||
@ -271,18 +264,15 @@ 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_builtin_vnode_create_target(vtype xt, const void* v, vtype t) {
 | 
			
		||||
    var_t _ = { .ptr = 0 };
 | 
			
		||||
 | 
			
		||||
    if (xt <= VTYPE_LDOUBLE) {
 | 
			
		||||
        if (t >= VTYPE_STRING) t = VTYPE_POINTER;
 | 
			
		||||
 | 
			
		||||
        if (xt <= VTYPE_INT64)
 | 
			
		||||
            return create_value(xt, v, t);
 | 
			
		||||
        return create_float(xt, v, t);
 | 
			
		||||
            return libcdsb_builtin_create_value(xt, v, t);
 | 
			
		||||
        return libcdsb_builtin_create_float(xt, v, t);
 | 
			
		||||
    } else if (t == VTYPE_POINTER && (t = xt) > VTYPE_STRING) {
 | 
			
		||||
        v = *(void**)v;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										22
									
								
								src/vtype.c
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								src/vtype.c
									
									
									
									
									
								
							@ -6,7 +6,7 @@
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
static ldbl_t normalize_value(const void* v, vtype t) {
 | 
			
		||||
static ldbl_t libcdsb_builtin_normalize(const void* v, vtype t) {
 | 
			
		||||
    if (t == VTYPE_BOOLEAN || t == VTYPE_UINT8) {
 | 
			
		||||
        return *(u8_t*)v;
 | 
			
		||||
    } else if (t == VTYPE_UINT16) {
 | 
			
		||||
@ -30,7 +30,7 @@ static ldbl_t normalize_value(const void* v, vtype t) {
 | 
			
		||||
    } else return abs(*(ldbl_t*)v) <= LDBL_EPSILON ? 0 : *(ldbl_t*)v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static hash_t ldouble_hash(ldbl_t s) {
 | 
			
		||||
static hash_t libcdsb_builtin_hash_float(ldbl_t s) {
 | 
			
		||||
    hash_t hash;
 | 
			
		||||
 | 
			
		||||
    if (sizeof(hash_t) == sizeof(u64_t)) {
 | 
			
		||||
@ -61,14 +61,14 @@ static hash_t ldouble_hash(ldbl_t s) {
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
int libcdsb_vtype_compare_values(const void* s0, vtype t0, const void* s1, vtype t1) {
 | 
			
		||||
    if (t0 == t1) return libcdsb_vtype_compare_values_eq(s0, s1, t0);
 | 
			
		||||
int libcdsb_builtin_vtype_compare_values(const void* s0, vtype t0, const void* s1, vtype t1) {
 | 
			
		||||
    if (t0 == t1) return libcdsb_builtin_vtype_compare_values_eq(s0, s1, t0);
 | 
			
		||||
 | 
			
		||||
    if (t0 <= VTYPE_LDOUBLE && t1 <= VTYPE_LDOUBLE) {
 | 
			
		||||
        ldbl_t d0, d1;
 | 
			
		||||
 | 
			
		||||
        d0 = normalize_value(s0, t0);
 | 
			
		||||
        d1 = normalize_value(s1, t1);
 | 
			
		||||
        d0 = libcdsb_builtin_normalize(s0, t0);
 | 
			
		||||
        d1 = libcdsb_builtin_normalize(s1, t1);
 | 
			
		||||
 | 
			
		||||
        return (abs(d0 - d1) <= LDBL_EPSILON) ? 0 : (d0 < d1 ? -1 : 1);
 | 
			
		||||
    }
 | 
			
		||||
@ -77,7 +77,7 @@ int libcdsb_vtype_compare_values(const void* s0, vtype t0, const void* s1, vtype
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int libcdsb_vtype_compare_values_eq(const void* s0, const void* s1, vtype t) {
 | 
			
		||||
int libcdsb_builtin_vtype_compare_values_eq(const void* s0, const void* s1, vtype t) {
 | 
			
		||||
 | 
			
		||||
    #define compare(T, s0, s1) *(T*)s0 == *(T*)s1 ? 0 : (*(T*)s0 < *(T*)s1 ? -1 : 1)
 | 
			
		||||
 | 
			
		||||
@ -117,7 +117,7 @@ int libcdsb_vtype_compare_values_eq(const void* s0, const void* s1, vtype t) {
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
hash_t libcdsb_vtype_hash(const void* v, vtype t) {
 | 
			
		||||
hash_t libcdsb_builtin_vtype_hash(const void* v, vtype t) {
 | 
			
		||||
 | 
			
		||||
    switch (t) { default: abort();
 | 
			
		||||
 | 
			
		||||
@ -147,8 +147,8 @@ hash_t libcdsb_vtype_hash(const void* v, vtype t) {
 | 
			
		||||
        case     VTYPE_SET: return vset_hash(v);
 | 
			
		||||
        case    VTYPE_DICT: return dict_hash(v);
 | 
			
		||||
 | 
			
		||||
        case   VTYPE_FLOAT: return ldouble_hash(*(fl_t*)v);
 | 
			
		||||
        case  VTYPE_DOUBLE: return ldouble_hash(*(dbl_t*)v);
 | 
			
		||||
        case VTYPE_LDOUBLE: return ldouble_hash(*(ldbl_t*)v);
 | 
			
		||||
        case   VTYPE_FLOAT: return libcdsb_builtin_hash_float(*(fl_t*)v);
 | 
			
		||||
        case  VTYPE_DOUBLE: return libcdsb_builtin_hash_float(*(dbl_t*)v);
 | 
			
		||||
        case VTYPE_LDOUBLE: return libcdsb_builtin_hash_float(*(ldbl_t*)v);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -51,6 +51,8 @@ tests: $(addprefix $(BUILD_PATH)/global-,$(notdir $(basename $(wildcard ./src/gl
 | 
			
		||||
 | 
			
		||||
########################################################################################################################
 | 
			
		||||
 | 
			
		||||
CFLAGS:=$(CFLAGS) ../modules/libunic/bin/libunic.a
 | 
			
		||||
 | 
			
		||||
$(BUILD_PATH)/obj/%.o: ./src/%.c | $(BUILD_PATH)/obj/
 | 
			
		||||
	$(CC) $^ -o $@ $(CFLAGS)
 | 
			
		||||
 | 
			
		||||
@ -72,7 +74,7 @@ $(BUILD_PATH)/obj/global-%.o: ./src/global/src/%.c | $(BUILD_PATH)/obj/
 | 
			
		||||
$(BUILD_PATH)/array-%:  ./src/array/%.c  $(OBJECTS_ARRAY)  | $(BUILD_PATH)/
 | 
			
		||||
	$(CC) $^ -o $@ $(CFLAGS) -g3 -Wall
 | 
			
		||||
$(BUILD_PATH)/string-%: ./src/string/%.c $(OBJECTS_STRING) | $(BUILD_PATH)/
 | 
			
		||||
	$(CC) $^ -o $@ ../modules/libunic/bin/libunic.a $(CFLAGS) -g3 -Wall
 | 
			
		||||
	$(CC) $^ -o $@ $(CFLAGS) -g3 -Wall
 | 
			
		||||
$(BUILD_PATH)/list-%:   ./src/list/%.c   $(OBJECTS_LIST)   | $(BUILD_PATH)/
 | 
			
		||||
	$(CC) $^ -o $@ $(CFLAGS) -g3 -Wall
 | 
			
		||||
$(BUILD_PATH)/map-%:    ./src/map/%.c    $(OBJECTS_MAP)    | $(BUILD_PATH)/
 | 
			
		||||
@ -82,7 +84,7 @@ $(BUILD_PATH)/set-%:    ./src/set/%.c    $(OBJECTS_SET)    | $(BUILD_PATH)/
 | 
			
		||||
$(BUILD_PATH)/dict-%:   ./src/dict/%.c   $(OBJECTS_DICT)   | $(BUILD_PATH)/
 | 
			
		||||
	$(CC) $^ -o $@ $(CFLAGS) -g3 -Wall
 | 
			
		||||
$(BUILD_PATH)/global-%: ./src/global/%.c $(OBJECTS_GLOBAL) | $(BUILD_PATH)/
 | 
			
		||||
	$(CC) $^ ../bin/debug/libcdsb.a ../modules/libunic/bin/libunic.a -o $@ $(CFLAGS) -g3 -Wall
 | 
			
		||||
	$(CC) $^ ../bin/debug/libcdsb.a -o $@ $(CFLAGS) -g3 -Wall
 | 
			
		||||
 | 
			
		||||
########################################################################################################################
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@
 | 
			
		||||
/*                                Copyright © 2022 Gregory Lirent */
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "../../../include/extra/vtype.h"
 | 
			
		||||
#include "../../../include/vtype.h"
 | 
			
		||||
#include "../../../include/array.h"
 | 
			
		||||
 | 
			
		||||
#include "../../include/random.h"
 | 
			
		||||
 | 
			
		||||
@ -2,16 +2,14 @@
 | 
			
		||||
/*                                Copyright © 2022 Gregory Lirent */
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "../../../../include/extra/vtype.h"
 | 
			
		||||
#include "../../../../include/vtype.h"
 | 
			
		||||
#include "../../../include/random.h"
 | 
			
		||||
 | 
			
		||||
vtype_string* string_duplicate(const vtype_string* x) { return 0; }
 | 
			
		||||
vtype_list*   list_duplicate  (const vtype_list*   x) { return 0; }
 | 
			
		||||
vtype_map*    map_duplicate   (const vtype_map*    x) { return 0; }
 | 
			
		||||
vtype_set*    vset_duplicate  (const vtype_set*    x) { return 0; }
 | 
			
		||||
vtype_dict*   dict_duplicate  (const vtype_dict*   x) { return 0; }
 | 
			
		||||
 | 
			
		||||
void string_free(vtype_string* x) {}
 | 
			
		||||
void list_free  (vtype_list*   x) {}
 | 
			
		||||
void map_free   (vtype_map*    x) {}
 | 
			
		||||
void vset_free  (vtype_set*    x) {}
 | 
			
		||||
@ -29,7 +27,6 @@ hash_t map_hash   (const vtype_map*    s) { return 0; }
 | 
			
		||||
hash_t vset_hash  (const vtype_set*    s) { return 0; }
 | 
			
		||||
hash_t dict_hash  (const vtype_dict*   s) { return 0; }
 | 
			
		||||
 | 
			
		||||
void string_copy_init(vtype_string* x, const vtype_string* s) { memset(x, 0, sizeof(*x)); }
 | 
			
		||||
void list_copy_init  (vtype_list*   x, const vtype_list*   s) { memset(x, 0, sizeof(*x)); }
 | 
			
		||||
void map_copy_init   (vtype_map*    x, const vtype_map*    s) { memset(x, 0, sizeof(*x)); }
 | 
			
		||||
void vset_copy_init  (vtype_set*    x, const vtype_set*    s) { memset(x, 0, sizeof(*x)); }
 | 
			
		||||
 | 
			
		||||
@ -31,7 +31,7 @@ void array_push_random(arr_t* x, _Bool silent, unsigned int hpos) {
 | 
			
		||||
            printf("\e[%dG\e[36mTry to push value to back of the array:\e[m\n", hpos+1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        r = libcdsb_array_push(x, _.v.value, _.v.type) >= 0;
 | 
			
		||||
        r = libcdsb_array_insert(x, _.v.value, _.v.type) >= 0;
 | 
			
		||||
    } else {
 | 
			
		||||
        ssize_t i = array_size(x);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -4,13 +4,11 @@
 | 
			
		||||
#include "../../../../src/__internal/include.h"
 | 
			
		||||
#include "../../../include/random.h"
 | 
			
		||||
 | 
			
		||||
vtype_string* string_duplicate(const vtype_string* x) { return 0; }
 | 
			
		||||
vtype_array*  array_duplicate (const vtype_array*  x) { return 0; }
 | 
			
		||||
vtype_list*   list_duplicate  (const vtype_list*   x) { return 0; }
 | 
			
		||||
vtype_map*    map_duplicate   (const vtype_map*    x) { return 0; }
 | 
			
		||||
vtype_set*    vset_duplicate  (const vtype_set*    x) { return 0; }
 | 
			
		||||
 | 
			
		||||
void string_free(vtype_string* x) {}
 | 
			
		||||
void array_free (vtype_array*  x) {}
 | 
			
		||||
void list_free  (vtype_list*   x) {}
 | 
			
		||||
void map_free   (vtype_map*    x) {}
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
/* This software is licensed by the MIT License, see LICENSE file */
 | 
			
		||||
/*                                Copyright © 2022 Gregory Lirent */
 | 
			
		||||
 | 
			
		||||
#include "../../../include/extra/string.h"
 | 
			
		||||
#include "../../../include/string.h"
 | 
			
		||||
#include "../../../include/array.h"
 | 
			
		||||
#include "../../../include/list.h"
 | 
			
		||||
#include "../../../include/set.h"
 | 
			
		||||
 | 
			
		||||
@ -80,30 +80,34 @@ static arr_t random_array(bool embd) {
 | 
			
		||||
    size_t  n = random_uint16()%((!embd)?MAX_ELEMENTS:100);
 | 
			
		||||
    value_t v = (!embd) ? random_value2() : real_random_value(1);
 | 
			
		||||
 | 
			
		||||
    void (*callback)(void*);
 | 
			
		||||
 | 
			
		||||
    switch (v.type) {
 | 
			
		||||
        default: callback = nullptr; break;
 | 
			
		||||
        case VTYPE_STRING: callback = (void*)string_free; break;
 | 
			
		||||
        case  VTYPE_ARRAY: callback = (void*)array_free;  break;
 | 
			
		||||
        case   VTYPE_LIST: callback = (void*)list_free;   break;
 | 
			
		||||
        case    VTYPE_MAP: callback = (void*)map_free;    break;
 | 
			
		||||
        case    VTYPE_SET: callback = (void*)vset_free;   break;
 | 
			
		||||
        case   VTYPE_DICT: callback = (void*)dict_free;   break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    array_init(&x, v.type);
 | 
			
		||||
 | 
			
		||||
    while(n--) {
 | 
			
		||||
 | 
			
		||||
        libcdsb_array_push(&x, v.value, v.type);
 | 
			
		||||
        libcdsb_array_insert(&x, v.value, v.type);
 | 
			
		||||
 | 
			
		||||
        if (callback) callback(v.value);
 | 
			
		||||
        switch (v.type) {
 | 
			
		||||
            default: break;
 | 
			
		||||
            case VTYPE_STRING: string_free((void*)v.value); break;
 | 
			
		||||
            case  VTYPE_ARRAY: array_free((void*)v.value);  break;
 | 
			
		||||
            case   VTYPE_LIST: list_free((void*)v.value);   break;
 | 
			
		||||
            case    VTYPE_MAP: map_free((void*)v.value);    break;
 | 
			
		||||
            case    VTYPE_SET: vset_free((void*)v.value);   break;
 | 
			
		||||
            case   VTYPE_DICT: dict_free((void*)v.value);   break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        v = random_value_by_type(v.type, 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (callback) callback(v.value);
 | 
			
		||||
    switch (v.type) {
 | 
			
		||||
        default: break;
 | 
			
		||||
        case VTYPE_STRING: string_free((void*)v.value); break;
 | 
			
		||||
        case  VTYPE_ARRAY: array_free((void*)v.value);  break;
 | 
			
		||||
        case   VTYPE_LIST: list_free((void*)v.value);   break;
 | 
			
		||||
        case    VTYPE_MAP: map_free((void*)v.value);    break;
 | 
			
		||||
        case    VTYPE_SET: vset_free((void*)v.value);   break;
 | 
			
		||||
        case   VTYPE_DICT: dict_free((void*)v.value);   break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return x;
 | 
			
		||||
}
 | 
			
		||||
@ -113,30 +117,35 @@ static set_t random_set(bool embd) {
 | 
			
		||||
    size_t  n = random_uint16()%((!embd)?MAX_ELEMENTS:100);
 | 
			
		||||
    value_t v = (!embd) ? random_value2() : real_random_value(1);
 | 
			
		||||
 | 
			
		||||
    void (*callback)(void*);
 | 
			
		||||
 | 
			
		||||
    switch (v.type) {
 | 
			
		||||
        default: callback = nullptr; break;
 | 
			
		||||
        case VTYPE_STRING: callback = (void*)string_free; break;
 | 
			
		||||
        case  VTYPE_ARRAY: callback = (void*)array_free;  break;
 | 
			
		||||
        case   VTYPE_LIST: callback = (void*)list_free;   break;
 | 
			
		||||
        case    VTYPE_MAP: callback = (void*)map_free;    break;
 | 
			
		||||
        case    VTYPE_SET: callback = (void*)vset_free;   break;
 | 
			
		||||
        case   VTYPE_DICT: callback = (void*)dict_free;   break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vset_init(&x, v.type);
 | 
			
		||||
 | 
			
		||||
    while(n--) {
 | 
			
		||||
 | 
			
		||||
        libcdsb_vset_insert(&x, v.value, v.type);
 | 
			
		||||
 | 
			
		||||
        if (callback) callback(v.value);
 | 
			
		||||
        switch (v.type) {
 | 
			
		||||
            default: break;
 | 
			
		||||
            case VTYPE_STRING: string_free((void*)v.value); break;
 | 
			
		||||
            case  VTYPE_ARRAY: array_free((void*)v.value);  break;
 | 
			
		||||
            case   VTYPE_LIST: list_free((void*)v.value);   break;
 | 
			
		||||
            case    VTYPE_MAP: map_free((void*)v.value);    break;
 | 
			
		||||
            case    VTYPE_SET: vset_free((void*)v.value);   break;
 | 
			
		||||
            case   VTYPE_DICT: dict_free((void*)v.value);   break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        v = random_value_by_type(v.type, 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (callback) callback(v.value);
 | 
			
		||||
    switch (v.type) {
 | 
			
		||||
        default: break;
 | 
			
		||||
        case VTYPE_STRING: string_free((void*)v.value); break;
 | 
			
		||||
        case  VTYPE_ARRAY: array_free((void*)v.value);  break;
 | 
			
		||||
        case   VTYPE_LIST: list_free((void*)v.value);   break;
 | 
			
		||||
        case    VTYPE_MAP: map_free((void*)v.value);    break;
 | 
			
		||||
        case    VTYPE_SET: vset_free((void*)v.value);   break;
 | 
			
		||||
        case   VTYPE_DICT: dict_free((void*)v.value);   break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -149,7 +158,7 @@ static list_t random_list(bool embd) {
 | 
			
		||||
 | 
			
		||||
    while(n--) {
 | 
			
		||||
        v = (!embd) ? random_value2() : real_random_value(1);
 | 
			
		||||
        libcdsb_list_update(&x, -1, v.value, v.type, 1);
 | 
			
		||||
        libcdsb_list_insert(&x, -1, v.value, v.type, 1);
 | 
			
		||||
 | 
			
		||||
        switch (v.type) {
 | 
			
		||||
            default: break;
 | 
			
		||||
@ -170,18 +179,6 @@ static map_t random_map(bool embd) {
 | 
			
		||||
    size_t  n = random_uint16()%((!embd)?MAX_ELEMENTS:100);
 | 
			
		||||
    value_t k = (!embd) ? random_value2() : real_random_value(1);
 | 
			
		||||
 | 
			
		||||
    void (*callback)(void*);
 | 
			
		||||
 | 
			
		||||
    switch (k.type) {
 | 
			
		||||
        default: callback = nullptr; break;
 | 
			
		||||
        case VTYPE_STRING: callback = (void*)string_free; break;
 | 
			
		||||
        case  VTYPE_ARRAY: callback = (void*)array_free;  break;
 | 
			
		||||
        case   VTYPE_LIST: callback = (void*)list_free;   break;
 | 
			
		||||
        case    VTYPE_MAP: callback = (void*)map_free;    break;
 | 
			
		||||
        case    VTYPE_SET: callback = (void*)vset_free;   break;
 | 
			
		||||
        case   VTYPE_DICT: callback = (void*)dict_free;   break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    map_init(&x, k.type);
 | 
			
		||||
 | 
			
		||||
    while(n--) {
 | 
			
		||||
@ -189,7 +186,15 @@ static map_t random_map(bool embd) {
 | 
			
		||||
 | 
			
		||||
        libcdsb_map_update(&x, k.value, k.type, v.value, v.type);
 | 
			
		||||
 | 
			
		||||
        if (callback) callback(k.value);
 | 
			
		||||
        switch (k.type) {
 | 
			
		||||
            default: break;
 | 
			
		||||
            case VTYPE_STRING: string_free((void*)k.value); break;
 | 
			
		||||
            case  VTYPE_ARRAY: array_free((void*)k.value);  break;
 | 
			
		||||
            case   VTYPE_LIST: list_free((void*)k.value);   break;
 | 
			
		||||
            case    VTYPE_MAP: map_free((void*)k.value);    break;
 | 
			
		||||
            case    VTYPE_SET: vset_free((void*)k.value);   break;
 | 
			
		||||
            case   VTYPE_DICT: dict_free((void*)k.value);   break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        switch (v.type) {
 | 
			
		||||
            default: break;
 | 
			
		||||
@ -204,7 +209,16 @@ static map_t random_map(bool embd) {
 | 
			
		||||
        k = random_value_by_type(k.type, 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (callback) callback(k.value);
 | 
			
		||||
    switch (k.type) {
 | 
			
		||||
        default: break;
 | 
			
		||||
        case VTYPE_STRING: string_free((void*)k.value); break;
 | 
			
		||||
        case  VTYPE_ARRAY: array_free((void*)k.value);  break;
 | 
			
		||||
        case   VTYPE_LIST: list_free((void*)k.value);   break;
 | 
			
		||||
        case    VTYPE_MAP: map_free((void*)k.value);    break;
 | 
			
		||||
        case    VTYPE_SET: vset_free((void*)k.value);   break;
 | 
			
		||||
        case   VTYPE_DICT: dict_free((void*)k.value);   break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return x;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -4,13 +4,11 @@
 | 
			
		||||
#include "../../../../src/__internal/include.h"
 | 
			
		||||
#include "../../../include/random.h"
 | 
			
		||||
 | 
			
		||||
vtype_string* string_duplicate(const vtype_string* x) { return 0; }
 | 
			
		||||
vtype_array*  array_duplicate (const vtype_array*  x) { return 0; }
 | 
			
		||||
vtype_map*    map_duplicate   (const vtype_map*    x) { return 0; }
 | 
			
		||||
vtype_set*    vset_duplicate  (const vtype_set*    x) { return 0; }
 | 
			
		||||
vtype_dict*   dict_duplicate  (const vtype_dict*   x) { return 0; }
 | 
			
		||||
 | 
			
		||||
void string_free(vtype_string* x) {}
 | 
			
		||||
void array_free (vtype_array*  x) {}
 | 
			
		||||
void map_free   (vtype_map*    x) {}
 | 
			
		||||
void vset_free  (vtype_set*    x) {}
 | 
			
		||||
 | 
			
		||||
@ -26,12 +26,12 @@ void list_push_random(list_t* x, _Bool silent, unsigned int hpos) {
 | 
			
		||||
        if (!silent) {
 | 
			
		||||
            printf("\e[%dG\e[36mTry to push value to back of the list:\e[m\n", hpos+1);
 | 
			
		||||
        }
 | 
			
		||||
        r = libcdsb_list_update(x, -1, v.value, v.type,  1);
 | 
			
		||||
        r = libcdsb_list_insert(x, -1, v.value, v.type,  1);
 | 
			
		||||
    } else if (random_boolean()) {
 | 
			
		||||
        if (!silent) {
 | 
			
		||||
            printf("\e[%dG\e[36mTry to push value to front of the list:\e[m\n", hpos+1);
 | 
			
		||||
        }
 | 
			
		||||
        r = libcdsb_list_update(x, -1, v.value, v.type,  1);
 | 
			
		||||
        r = libcdsb_list_insert(x, -1, v.value, v.type,  1);
 | 
			
		||||
    } else {
 | 
			
		||||
        ssize_t i = list_size(x);
 | 
			
		||||
        i = random_uint64()% (i ? i : 1);
 | 
			
		||||
@ -41,7 +41,7 @@ void list_push_random(list_t* x, _Bool silent, unsigned int hpos) {
 | 
			
		||||
            printf("\e[%dG\e[36mTry to change value with index \e[32;1m%ld\e[36m in the list:\e[m\n", hpos+1, i);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        r = libcdsb_list_update(x, i, v.value, v.type, 0);
 | 
			
		||||
        r = libcdsb_list_insert(x, i, v.value, v.type, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!silent) {
 | 
			
		||||
 | 
			
		||||
@ -4,13 +4,11 @@
 | 
			
		||||
#include "../../../../src/__internal/include.h"
 | 
			
		||||
#include "../../../include/random.h"
 | 
			
		||||
 | 
			
		||||
vtype_string* string_duplicate(const vtype_string* x) { return 0; }
 | 
			
		||||
vtype_array*  array_duplicate (const vtype_array*  x) { return 0; }
 | 
			
		||||
vtype_list*   list_duplicate  (const vtype_list*   x) { return 0; }
 | 
			
		||||
vtype_set*    vset_duplicate  (const vtype_set*    x) { return 0; }
 | 
			
		||||
vtype_dict*   dict_duplicate  (const vtype_dict*   x) { return 0; }
 | 
			
		||||
 | 
			
		||||
void string_free(vtype_string* x) {}
 | 
			
		||||
void array_free (vtype_array*  x) {}
 | 
			
		||||
void list_free  (vtype_list*   x) {}
 | 
			
		||||
void vset_free  (vtype_set*    x) {}
 | 
			
		||||
 | 
			
		||||
@ -4,13 +4,11 @@
 | 
			
		||||
#include "../../../../src/__internal/include.h"
 | 
			
		||||
#include "../../../include/random.h"
 | 
			
		||||
 | 
			
		||||
vtype_string* string_duplicate(const vtype_string* x) { return 0; }
 | 
			
		||||
vtype_array*  array_duplicate (const vtype_array*  x) { return 0; }
 | 
			
		||||
vtype_list*   list_duplicate  (const vtype_list*   x) { return 0; }
 | 
			
		||||
vtype_map*    map_duplicate   (const vtype_map*    x) { return 0; }
 | 
			
		||||
vtype_dict*   dict_duplicate  (const vtype_dict*   x) { return 0; }
 | 
			
		||||
 | 
			
		||||
void string_free(vtype_string* x) {}
 | 
			
		||||
void array_free (vtype_array*  x) {}
 | 
			
		||||
void list_free  (vtype_list*   x) {}
 | 
			
		||||
void map_free   (vtype_map*    x) {}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user