diff --git a/tests/include/tst_cmc_bitset.h b/tests/include/tst_cmc_bitset.h index 9e1998c..0c693e0 100644 --- a/tests/include/tst_cmc_bitset.h +++ b/tests/include/tst_cmc_bitset.h @@ -1,11 +1,44 @@ - #ifndef CMC_CMC_BITSET_TEST_H - #define CMC_CMC_BITSET_TEST_H +#ifndef CMC_CMC_BITSET_TEST_H +#define CMC_CMC_BITSET_TEST_H - #include "macro_collections.h" - - struct bitset { cmc_bitset_word *buffer; size_t capacity; size_t count; int flag; struct cmc_alloc_node *alloc; struct cmc_callbacks *callbacks; }; struct bitset_iter { struct bitset *target; size_t cursor; _Bool start; _Bool end; }; struct bitset *bs_new(size_t n_bits); struct bitset *bs_new_custom(size_t n_bits, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); struct bitset bs_init(size_t n_bits); struct bitset bs_init_custom(size_t n_bits, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); void bs_free(struct bitset * _bitset_); void bs_release(struct bitset _bitset_); void bs_customize(struct bitset * _bitset_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); _Bool bs_set(struct bitset * _bitset_, size_t bit_index); _Bool bs_set_range(struct bitset * _bitset_, size_t from, size_t to); _Bool bs_clear(struct bitset * _bitset_, size_t bit_index); _Bool bs_clear_range(struct bitset * _bitset_, size_t from, size_t to); _Bool bs_flip(struct bitset * _bitset_, size_t bit_index); _Bool bs_flip_range(struct bitset * _bitset_, size_t from, size_t to); _Bool bs_put(struct bitset * _bitset_, size_t bit_index, _Bool state); _Bool bs_put_range(struct bitset * _bitset_, size_t from, size_t to, _Bool state); _Bool bs_set_all(struct bitset * _bitset_); _Bool bs_clear_all(struct bitset * _bitset_); _Bool bs_flip_all(struct bitset * _bitset_); _Bool bs_get(struct bitset * _bitset_, size_t bit_index); _Bool bs_resize(struct bitset * _bitset_, size_t n_bits); - +#include "macro_collections.h" - #endif /* CMC_CMC_BITSET_TEST_H */ - \ No newline at end of file +struct bitset +{ + cmc_bitset_word *buffer; + size_t capacity; + size_t count; + int flag; + struct cmc_alloc_node *alloc; + struct cmc_callbacks *callbacks; +}; +struct bitset_iter +{ + struct bitset *target; + size_t cursor; + _Bool start; + _Bool end; +}; +struct bitset *bs_new(size_t n_bits); +struct bitset *bs_new_custom(size_t n_bits, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks); +struct bitset bs_init(size_t n_bits); +struct bitset bs_init_custom(size_t n_bits, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks); +void bs_free(struct bitset *_bitset_); +void bs_release(struct bitset _bitset_); +void bs_customize(struct bitset *_bitset_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks); +_Bool bs_set(struct bitset *_bitset_, size_t bit_index); +_Bool bs_set_range(struct bitset *_bitset_, size_t from, size_t to); +_Bool bs_clear(struct bitset *_bitset_, size_t bit_index); +_Bool bs_clear_range(struct bitset *_bitset_, size_t from, size_t to); +_Bool bs_flip(struct bitset *_bitset_, size_t bit_index); +_Bool bs_flip_range(struct bitset *_bitset_, size_t from, size_t to); +_Bool bs_put(struct bitset *_bitset_, size_t bit_index, _Bool state); +_Bool bs_put_range(struct bitset *_bitset_, size_t from, size_t to, _Bool state); +_Bool bs_set_all(struct bitset *_bitset_); +_Bool bs_clear_all(struct bitset *_bitset_); +_Bool bs_flip_all(struct bitset *_bitset_); +_Bool bs_get(struct bitset *_bitset_, size_t bit_index); +_Bool bs_resize(struct bitset *_bitset_, size_t n_bits); + +#endif /* CMC_CMC_BITSET_TEST_H */ diff --git a/tests/include/tst_cmc_deque.h b/tests/include/tst_cmc_deque.h index 70e222f..b664e2a 100644 --- a/tests/include/tst_cmc_deque.h +++ b/tests/include/tst_cmc_deque.h @@ -1,11 +1,78 @@ - #ifndef CMC_CMC_DEQUE_TEST_H - #define CMC_CMC_DEQUE_TEST_H +#ifndef CMC_CMC_DEQUE_TEST_H +#define CMC_CMC_DEQUE_TEST_H - #include "macro_collections.h" - - struct deque { size_t *buffer; size_t capacity; size_t count; size_t front; size_t back; int flag; struct deque_fval * f_val; struct cmc_alloc_node *alloc; struct cmc_callbacks *callbacks; }; struct deque_fval { int (*cmp)(size_t, size_t); size_t (*cpy)(size_t); _Bool (*str)(FILE *, size_t); void (*free)(size_t); size_t (*hash)(size_t); int (*pri)(size_t, size_t); }; struct deque *d_new(size_t capacity, struct deque_fval * f_val); struct deque *d_new_custom(size_t capacity, struct deque_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); void d_clear(struct deque * _deque_); void d_free(struct deque * _deque_); void d_customize(struct deque * _deque_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); _Bool d_push_front(struct deque * _deque_, size_t value); _Bool d_push_back(struct deque * _deque_, size_t value); _Bool d_pop_front(struct deque * _deque_); _Bool d_pop_back(struct deque * _deque_); size_t d_front(struct deque * _deque_); size_t d_back(struct deque * _deque_); _Bool d_contains(struct deque * _deque_, size_t value); _Bool d_empty(struct deque * _deque_); _Bool d_full(struct deque * _deque_); size_t d_count(struct deque * _deque_); size_t d_capacity(struct deque * _deque_); int d_flag(struct deque * _deque_); _Bool d_resize(struct deque * _deque_, size_t capacity); struct deque *d_copy_of(struct deque * _deque_); _Bool d_equals(struct deque * _deque1_, struct deque * _deque2_); struct deque d_init(size_t capacity, struct deque_fval * f_val); struct deque d_init_custom(size_t capacity, struct deque_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); void d_release(struct deque _deque_); struct deque_iter { struct deque *target; size_t cursor; size_t index; _Bool start; _Bool end; }; struct deque_iter d_iter_start(struct deque * target); struct deque_iter d_iter_end(struct deque * target); _Bool d_iter_at_start(struct deque_iter * iter); _Bool d_iter_at_end(struct deque_iter * iter); _Bool d_iter_to_start(struct deque_iter * iter); _Bool d_iter_to_end(struct deque_iter * iter); _Bool d_iter_next(struct deque_iter * iter); _Bool d_iter_prev(struct deque_iter * iter); _Bool d_iter_advance(struct deque_iter * iter, size_t steps); _Bool d_iter_rewind(struct deque_iter * iter, size_t steps); _Bool d_iter_go_to(struct deque_iter * iter, size_t index); size_t d_iter_value(struct deque_iter * iter); size_t *d_iter_rvalue(struct deque_iter * iter); size_t d_iter_index(struct deque_iter * iter); _Bool d_to_string(struct deque * _deque_, FILE * fptr); _Bool d_print(struct deque * _deque_, FILE * fptr, const char *start, const char *separator, const char *end); - +#include "macro_collections.h" - #endif /* CMC_CMC_DEQUE_TEST_H */ - \ No newline at end of file +struct deque +{ + size_t *buffer; + size_t capacity; + size_t count; + size_t front; + size_t back; + int flag; + struct deque_fval *f_val; + struct cmc_alloc_node *alloc; + struct cmc_callbacks *callbacks; +}; +struct deque_fval +{ + int (*cmp)(size_t, size_t); + size_t (*cpy)(size_t); + _Bool (*str)(FILE *, size_t); + void (*free)(size_t); + size_t (*hash)(size_t); + int (*pri)(size_t, size_t); +}; +struct deque *d_new(size_t capacity, struct deque_fval *f_val); +struct deque *d_new_custom(size_t capacity, struct deque_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks); +void d_clear(struct deque *_deque_); +void d_free(struct deque *_deque_); +void d_customize(struct deque *_deque_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks); +_Bool d_push_front(struct deque *_deque_, size_t value); +_Bool d_push_back(struct deque *_deque_, size_t value); +_Bool d_pop_front(struct deque *_deque_); +_Bool d_pop_back(struct deque *_deque_); +size_t d_front(struct deque *_deque_); +size_t d_back(struct deque *_deque_); +_Bool d_contains(struct deque *_deque_, size_t value); +_Bool d_empty(struct deque *_deque_); +_Bool d_full(struct deque *_deque_); +size_t d_count(struct deque *_deque_); +size_t d_capacity(struct deque *_deque_); +int d_flag(struct deque *_deque_); +_Bool d_resize(struct deque *_deque_, size_t capacity); +struct deque *d_copy_of(struct deque *_deque_); +_Bool d_equals(struct deque *_deque1_, struct deque *_deque2_); +struct deque d_init(size_t capacity, struct deque_fval *f_val); +struct deque d_init_custom(size_t capacity, struct deque_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks); +void d_release(struct deque _deque_); +struct deque_iter +{ + struct deque *target; + size_t cursor; + size_t index; + _Bool start; + _Bool end; +}; +struct deque_iter d_iter_start(struct deque *target); +struct deque_iter d_iter_end(struct deque *target); +_Bool d_iter_at_start(struct deque_iter *iter); +_Bool d_iter_at_end(struct deque_iter *iter); +_Bool d_iter_to_start(struct deque_iter *iter); +_Bool d_iter_to_end(struct deque_iter *iter); +_Bool d_iter_next(struct deque_iter *iter); +_Bool d_iter_prev(struct deque_iter *iter); +_Bool d_iter_advance(struct deque_iter *iter, size_t steps); +_Bool d_iter_rewind(struct deque_iter *iter, size_t steps); +_Bool d_iter_go_to(struct deque_iter *iter, size_t index); +size_t d_iter_value(struct deque_iter *iter); +size_t *d_iter_rvalue(struct deque_iter *iter); +size_t d_iter_index(struct deque_iter *iter); +_Bool d_to_string(struct deque *_deque_, FILE *fptr); +_Bool d_print(struct deque *_deque_, FILE *fptr, const char *start, const char *separator, const char *end); + +#endif /* CMC_CMC_DEQUE_TEST_H */ diff --git a/tests/include/tst_cmc_hashbidimap.h b/tests/include/tst_cmc_hashbidimap.h index a9a6387..c574437 100644 --- a/tests/include/tst_cmc_hashbidimap.h +++ b/tests/include/tst_cmc_hashbidimap.h @@ -1,11 +1,101 @@ - #ifndef CMC_CMC_HASHBIDIMAP_TEST_H - #define CMC_CMC_HASHBIDIMAP_TEST_H +#ifndef CMC_CMC_HASHBIDIMAP_TEST_H +#define CMC_CMC_HASHBIDIMAP_TEST_H - #include "macro_collections.h" - - struct hashbidimap { struct hashbidimap_entry * (*buffer)[2]; size_t capacity; size_t count; double load; int flag; struct hashbidimap_fkey * f_key; struct hashbidimap_fval * f_val; struct cmc_alloc_node *alloc; struct cmc_callbacks *callbacks; struct hashbidimap_iter (*it_start)(struct hashbidimap *); struct hashbidimap_iter (*it_end)(struct hashbidimap *); }; struct hashbidimap_entry { size_t key; size_t value; size_t dist[2]; struct hashbidimap_entry * *ref[2]; }; struct hashbidimap_fkey { int (*cmp)(size_t, size_t); size_t (*cpy)(size_t); _Bool (*str)(FILE *, size_t); void (*free)(size_t); size_t (*hash)(size_t); int (*pri)(size_t, size_t); }; struct hashbidimap_fval { int (*cmp)(size_t, size_t); size_t (*cpy)(size_t); _Bool (*str)(FILE *, size_t); void (*free)(size_t); size_t (*hash)(size_t); int (*pri)(size_t, size_t); }; struct hashbidimap_iter { struct hashbidimap *target; size_t cursor; size_t index; size_t first; size_t last; _Bool start; _Bool end; }; struct hashbidimap *hbm_new(size_t capacity, double load, struct hashbidimap_fkey * f_key, struct hashbidimap_fval * f_val); struct hashbidimap *hbm_new_custom(size_t capacity, double load, struct hashbidimap_fkey * f_key, struct hashbidimap_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); void hbm_clear(struct hashbidimap * _map_); void hbm_free(struct hashbidimap * _map_); void hbm_customize(struct hashbidimap * _map_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); _Bool hbm_insert(struct hashbidimap * _map_, size_t key, size_t value); _Bool hbm_update_key(struct hashbidimap * _map_, size_t val, size_t new_key); _Bool hbm_update_val(struct hashbidimap * _map_, size_t key, size_t new_val); _Bool hbm_remove_by_key(struct hashbidimap * _map_, size_t key, size_t * out_key, size_t * out_val); _Bool hbm_remove_by_val(struct hashbidimap * _map_, size_t val, size_t * out_key, size_t * out_val); size_t hbm_get_key(struct hashbidimap * _map_, size_t val); size_t hbm_get_val(struct hashbidimap * _map_, size_t key); _Bool hbm_contains_key(struct hashbidimap * _map_, size_t key); _Bool hbm_contains_val(struct hashbidimap * _map_, size_t val); _Bool hbm_empty(struct hashbidimap * _map_); _Bool hbm_full(struct hashbidimap * _map_); size_t hbm_count(struct hashbidimap * _map_); size_t hbm_capacity(struct hashbidimap * _map_); double hbm_load(struct hashbidimap * _map_); int hbm_flag(struct hashbidimap * _map_); _Bool hbm_resize(struct hashbidimap * _map_, size_t capacity); struct hashbidimap *hbm_copy_of(struct hashbidimap * _map_); _Bool hbm_equals(struct hashbidimap * _map1_, struct hashbidimap * _map2_); struct hashbidimap_iter * hbm_iter_new(struct hashbidimap * target); void hbm_iter_free(struct hashbidimap_iter * iter); void hbm_iter_init(struct hashbidimap_iter * iter, struct hashbidimap * target); _Bool hbm_iter_start(struct hashbidimap_iter * iter); _Bool hbm_iter_end(struct hashbidimap_iter * iter); void hbm_iter_to_start(struct hashbidimap_iter * iter); void hbm_iter_to_end(struct hashbidimap_iter * iter); _Bool hbm_iter_next(struct hashbidimap_iter * iter); _Bool hbm_iter_prev(struct hashbidimap_iter * iter); _Bool hbm_iter_advance(struct hashbidimap_iter * iter, size_t steps); _Bool hbm_iter_rewind(struct hashbidimap_iter * iter, size_t steps); _Bool hbm_iter_go_to(struct hashbidimap_iter * iter, size_t index); size_t hbm_iter_key(struct hashbidimap_iter * iter); size_t hbm_iter_value(struct hashbidimap_iter * iter); size_t hbm_iter_index(struct hashbidimap_iter * iter); _Bool hbm_to_string(struct hashbidimap * _map_, FILE * fptr); _Bool hbm_print(struct hashbidimap * _map_, FILE * fptr, const char *start, const char *separator, const char *end, const char *key_val_sep); - +#include "macro_collections.h" - #endif /* CMC_CMC_HASHBIDIMAP_TEST_H */ - \ No newline at end of file +struct hashbidimap +{ + struct hashbidimap_entry *(*buffer)[2]; + size_t capacity; + size_t count; + double load; + int flag; + struct hashbidimap_fkey *f_key; + struct hashbidimap_fval *f_val; + struct cmc_alloc_node *alloc; + struct cmc_callbacks *callbacks; + struct hashbidimap_iter (*it_start)(struct hashbidimap *); + struct hashbidimap_iter (*it_end)(struct hashbidimap *); +}; +struct hashbidimap_entry +{ + size_t key; + size_t value; + size_t dist[2]; + struct hashbidimap_entry **ref[2]; +}; +struct hashbidimap_fkey +{ + int (*cmp)(size_t, size_t); + size_t (*cpy)(size_t); + _Bool (*str)(FILE *, size_t); + void (*free)(size_t); + size_t (*hash)(size_t); + int (*pri)(size_t, size_t); +}; +struct hashbidimap_fval +{ + int (*cmp)(size_t, size_t); + size_t (*cpy)(size_t); + _Bool (*str)(FILE *, size_t); + void (*free)(size_t); + size_t (*hash)(size_t); + int (*pri)(size_t, size_t); +}; +struct hashbidimap_iter +{ + struct hashbidimap *target; + size_t cursor; + size_t index; + size_t first; + size_t last; + _Bool start; + _Bool end; +}; +struct hashbidimap *hbm_new(size_t capacity, double load, struct hashbidimap_fkey *f_key, + struct hashbidimap_fval *f_val); +struct hashbidimap *hbm_new_custom(size_t capacity, double load, struct hashbidimap_fkey *f_key, + struct hashbidimap_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks); +void hbm_clear(struct hashbidimap *_map_); +void hbm_free(struct hashbidimap *_map_); +void hbm_customize(struct hashbidimap *_map_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks); +_Bool hbm_insert(struct hashbidimap *_map_, size_t key, size_t value); +_Bool hbm_update_key(struct hashbidimap *_map_, size_t val, size_t new_key); +_Bool hbm_update_val(struct hashbidimap *_map_, size_t key, size_t new_val); +_Bool hbm_remove_by_key(struct hashbidimap *_map_, size_t key, size_t *out_key, size_t *out_val); +_Bool hbm_remove_by_val(struct hashbidimap *_map_, size_t val, size_t *out_key, size_t *out_val); +size_t hbm_get_key(struct hashbidimap *_map_, size_t val); +size_t hbm_get_val(struct hashbidimap *_map_, size_t key); +_Bool hbm_contains_key(struct hashbidimap *_map_, size_t key); +_Bool hbm_contains_val(struct hashbidimap *_map_, size_t val); +_Bool hbm_empty(struct hashbidimap *_map_); +_Bool hbm_full(struct hashbidimap *_map_); +size_t hbm_count(struct hashbidimap *_map_); +size_t hbm_capacity(struct hashbidimap *_map_); +double hbm_load(struct hashbidimap *_map_); +int hbm_flag(struct hashbidimap *_map_); +_Bool hbm_resize(struct hashbidimap *_map_, size_t capacity); +struct hashbidimap *hbm_copy_of(struct hashbidimap *_map_); +_Bool hbm_equals(struct hashbidimap *_map1_, struct hashbidimap *_map2_); +struct hashbidimap_iter *hbm_iter_new(struct hashbidimap *target); +void hbm_iter_free(struct hashbidimap_iter *iter); +void hbm_iter_init(struct hashbidimap_iter *iter, struct hashbidimap *target); +_Bool hbm_iter_start(struct hashbidimap_iter *iter); +_Bool hbm_iter_end(struct hashbidimap_iter *iter); +void hbm_iter_to_start(struct hashbidimap_iter *iter); +void hbm_iter_to_end(struct hashbidimap_iter *iter); +_Bool hbm_iter_next(struct hashbidimap_iter *iter); +_Bool hbm_iter_prev(struct hashbidimap_iter *iter); +_Bool hbm_iter_advance(struct hashbidimap_iter *iter, size_t steps); +_Bool hbm_iter_rewind(struct hashbidimap_iter *iter, size_t steps); +_Bool hbm_iter_go_to(struct hashbidimap_iter *iter, size_t index); +size_t hbm_iter_key(struct hashbidimap_iter *iter); +size_t hbm_iter_value(struct hashbidimap_iter *iter); +size_t hbm_iter_index(struct hashbidimap_iter *iter); +_Bool hbm_to_string(struct hashbidimap *_map_, FILE *fptr); +_Bool hbm_print(struct hashbidimap *_map_, FILE *fptr, const char *start, const char *separator, const char *end, + const char *key_val_sep); + +#endif /* CMC_CMC_HASHBIDIMAP_TEST_H */ diff --git a/tests/include/tst_cmc_hashmap.h b/tests/include/tst_cmc_hashmap.h index 490bae1..5bb61eb 100644 --- a/tests/include/tst_cmc_hashmap.h +++ b/tests/include/tst_cmc_hashmap.h @@ -1,11 +1,100 @@ - #ifndef CMC_CMC_HASHMAP_TEST_H - #define CMC_CMC_HASHMAP_TEST_H +#ifndef CMC_CMC_HASHMAP_TEST_H +#define CMC_CMC_HASHMAP_TEST_H - #include "macro_collections.h" - - struct hashmap { struct hashmap_entry * buffer; size_t capacity; size_t count; double load; int flag; struct hashmap_fkey * f_key; struct hashmap_fval * f_val; struct cmc_alloc_node *alloc; struct cmc_callbacks *callbacks; }; struct hashmap_entry { size_t key; size_t value; size_t dist; enum cmc_entry_state state; }; struct hashmap_fkey { int (*cmp)(size_t, size_t); size_t (*cpy)(size_t); _Bool (*str)(FILE *, size_t); void (*free)(size_t); size_t (*hash)(size_t); int (*pri)(size_t, size_t); }; struct hashmap_fval { int (*cmp)(size_t, size_t); size_t (*cpy)(size_t); _Bool (*str)(FILE *, size_t); void (*free)(size_t); size_t (*hash)(size_t); int (*pri)(size_t, size_t); }; struct hashmap *hm_new(size_t capacity, double load, struct hashmap_fkey * f_key, struct hashmap_fval * f_val); struct hashmap *hm_new_custom(size_t capacity, double load, struct hashmap_fkey * f_key, struct hashmap_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); void hm_clear(struct hashmap * _map_); void hm_free(struct hashmap * _map_); void hm_customize(struct hashmap * _map_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); _Bool hm_insert(struct hashmap * _map_, size_t key, size_t value); _Bool hm_update(struct hashmap * _map_, size_t key, size_t new_value, size_t * old_value); _Bool hm_remove(struct hashmap * _map_, size_t key, size_t * out_value); _Bool hm_max(struct hashmap * _map_, size_t * key, size_t * value); _Bool hm_min(struct hashmap * _map_, size_t * key, size_t * value); size_t hm_get(struct hashmap * _map_, size_t key); size_t *hm_get_ref(struct hashmap * _map_, size_t key); _Bool hm_contains(struct hashmap * _map_, size_t key); _Bool hm_empty(struct hashmap * _map_); _Bool hm_full(struct hashmap * _map_); size_t hm_count(struct hashmap * _map_); size_t hm_capacity(struct hashmap * _map_); double hm_load(struct hashmap * _map_); int hm_flag(struct hashmap * _map_); _Bool hm_resize(struct hashmap * _map_, size_t capacity); struct hashmap *hm_copy_of(struct hashmap * _map_); _Bool hm_equals(struct hashmap * _map1_, struct hashmap * _map2_); struct hashmap hm_init(size_t capacity, double load, struct hashmap_fkey * f_key, struct hashmap_fval * f_val); struct hashmap hm_init_custom(size_t capacity, double load, struct hashmap_fkey * f_key, struct hashmap_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); void hm_release(struct hashmap _map_); struct hashmap_iter { struct hashmap *target; size_t cursor; size_t index; size_t first; size_t last; _Bool start; _Bool end; }; struct hashmap_iter hm_iter_start(struct hashmap * target); struct hashmap_iter hm_iter_end(struct hashmap * target); _Bool hm_iter_at_start(struct hashmap_iter * iter); _Bool hm_iter_at_end(struct hashmap_iter * iter); _Bool hm_iter_to_start(struct hashmap_iter * iter); _Bool hm_iter_to_end(struct hashmap_iter * iter); _Bool hm_iter_next(struct hashmap_iter * iter); _Bool hm_iter_prev(struct hashmap_iter * iter); _Bool hm_iter_advance(struct hashmap_iter * iter, size_t steps); _Bool hm_iter_rewind(struct hashmap_iter * iter, size_t steps); _Bool hm_iter_go_to(struct hashmap_iter * iter, size_t index); size_t hm_iter_key(struct hashmap_iter * iter); size_t hm_iter_value(struct hashmap_iter * iter); size_t *hm_iter_rvalue(struct hashmap_iter * iter); size_t hm_iter_index(struct hashmap_iter * iter); _Bool hm_to_string(struct hashmap * _map_, FILE * fptr); _Bool hm_print(struct hashmap * _map_, FILE * fptr, const char *start, const char *separator, const char *end, const char *key_val_sep); - +#include "macro_collections.h" - #endif /* CMC_CMC_HASHMAP_TEST_H */ - \ No newline at end of file +struct hashmap +{ + struct hashmap_entry *buffer; + size_t capacity; + size_t count; + double load; + int flag; + struct hashmap_fkey *f_key; + struct hashmap_fval *f_val; + struct cmc_alloc_node *alloc; + struct cmc_callbacks *callbacks; +}; +struct hashmap_entry +{ + size_t key; + size_t value; + size_t dist; + enum cmc_entry_state state; +}; +struct hashmap_fkey +{ + int (*cmp)(size_t, size_t); + size_t (*cpy)(size_t); + _Bool (*str)(FILE *, size_t); + void (*free)(size_t); + size_t (*hash)(size_t); + int (*pri)(size_t, size_t); +}; +struct hashmap_fval +{ + int (*cmp)(size_t, size_t); + size_t (*cpy)(size_t); + _Bool (*str)(FILE *, size_t); + void (*free)(size_t); + size_t (*hash)(size_t); + int (*pri)(size_t, size_t); +}; +struct hashmap *hm_new(size_t capacity, double load, struct hashmap_fkey *f_key, struct hashmap_fval *f_val); +struct hashmap *hm_new_custom(size_t capacity, double load, struct hashmap_fkey *f_key, struct hashmap_fval *f_val, + struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks); +void hm_clear(struct hashmap *_map_); +void hm_free(struct hashmap *_map_); +void hm_customize(struct hashmap *_map_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks); +_Bool hm_insert(struct hashmap *_map_, size_t key, size_t value); +_Bool hm_update(struct hashmap *_map_, size_t key, size_t new_value, size_t *old_value); +_Bool hm_remove(struct hashmap *_map_, size_t key, size_t *out_value); +_Bool hm_max(struct hashmap *_map_, size_t *key, size_t *value); +_Bool hm_min(struct hashmap *_map_, size_t *key, size_t *value); +size_t hm_get(struct hashmap *_map_, size_t key); +size_t *hm_get_ref(struct hashmap *_map_, size_t key); +_Bool hm_contains(struct hashmap *_map_, size_t key); +_Bool hm_empty(struct hashmap *_map_); +_Bool hm_full(struct hashmap *_map_); +size_t hm_count(struct hashmap *_map_); +size_t hm_capacity(struct hashmap *_map_); +double hm_load(struct hashmap *_map_); +int hm_flag(struct hashmap *_map_); +_Bool hm_resize(struct hashmap *_map_, size_t capacity); +struct hashmap *hm_copy_of(struct hashmap *_map_); +_Bool hm_equals(struct hashmap *_map1_, struct hashmap *_map2_); +struct hashmap hm_init(size_t capacity, double load, struct hashmap_fkey *f_key, struct hashmap_fval *f_val); +struct hashmap hm_init_custom(size_t capacity, double load, struct hashmap_fkey *f_key, struct hashmap_fval *f_val, + struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks); +void hm_release(struct hashmap _map_); +struct hashmap_iter +{ + struct hashmap *target; + size_t cursor; + size_t index; + size_t first; + size_t last; + _Bool start; + _Bool end; +}; +struct hashmap_iter hm_iter_start(struct hashmap *target); +struct hashmap_iter hm_iter_end(struct hashmap *target); +_Bool hm_iter_at_start(struct hashmap_iter *iter); +_Bool hm_iter_at_end(struct hashmap_iter *iter); +_Bool hm_iter_to_start(struct hashmap_iter *iter); +_Bool hm_iter_to_end(struct hashmap_iter *iter); +_Bool hm_iter_next(struct hashmap_iter *iter); +_Bool hm_iter_prev(struct hashmap_iter *iter); +_Bool hm_iter_advance(struct hashmap_iter *iter, size_t steps); +_Bool hm_iter_rewind(struct hashmap_iter *iter, size_t steps); +_Bool hm_iter_go_to(struct hashmap_iter *iter, size_t index); +size_t hm_iter_key(struct hashmap_iter *iter); +size_t hm_iter_value(struct hashmap_iter *iter); +size_t *hm_iter_rvalue(struct hashmap_iter *iter); +size_t hm_iter_index(struct hashmap_iter *iter); +_Bool hm_to_string(struct hashmap *_map_, FILE *fptr); +_Bool hm_print(struct hashmap *_map_, FILE *fptr, const char *start, const char *separator, const char *end, + const char *key_val_sep); + +#endif /* CMC_CMC_HASHMAP_TEST_H */ diff --git a/tests/include/tst_cmc_hashmultimap.h b/tests/include/tst_cmc_hashmultimap.h index 883ad18..7b44266 100644 --- a/tests/include/tst_cmc_hashmultimap.h +++ b/tests/include/tst_cmc_hashmultimap.h @@ -1,11 +1,102 @@ - #ifndef CMC_CMC_HASHMULTIMAP_TEST_H - #define CMC_CMC_HASHMULTIMAP_TEST_H +#ifndef CMC_CMC_HASHMULTIMAP_TEST_H +#define CMC_CMC_HASHMULTIMAP_TEST_H - #include "macro_collections.h" - - struct hashmultimap { struct hashmultimap_entry * (*buffer)[2]; size_t capacity; size_t count; double load; int flag; struct hashmultimap_fkey * f_key; struct hashmultimap_fval * f_val; struct cmc_alloc_node *alloc; struct cmc_callbacks *callbacks; }; struct hashmultimap_entry { size_t key; size_t value; struct hashmultimap_entry * next; struct hashmultimap_entry * prev; }; struct hashmultimap_fkey { int (*cmp)(size_t, size_t); size_t (*cpy)(size_t); _Bool (*str)(FILE *, size_t); void (*free)(size_t); size_t (*hash)(size_t); int (*pri)(size_t, size_t); }; struct hashmultimap_fval { int (*cmp)(size_t, size_t); size_t (*cpy)(size_t); _Bool (*str)(FILE *, size_t); void (*free)(size_t); size_t (*hash)(size_t); int (*pri)(size_t, size_t); }; struct hashmultimap *hmm_new(size_t capacity, double load, struct hashmultimap_fkey * f_key, struct hashmultimap_fval * f_val); struct hashmultimap *hmm_new_custom(size_t capacity, double load, struct hashmultimap_fkey * f_key, struct hashmultimap_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); void hmm_clear(struct hashmultimap * _map_); void hmm_free(struct hashmultimap * _map_); void hmm_customize(struct hashmultimap * _map_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); _Bool hmm_insert(struct hashmultimap * _map_, size_t key, size_t value); _Bool hmm_update(struct hashmultimap * _map_, size_t key, size_t new_value, size_t * old_value); size_t hmm_update_all(struct hashmultimap * _map_, size_t key, size_t new_value, size_t * *old_values); _Bool hmm_remove(struct hashmultimap * _map_, size_t key, size_t * out_value); size_t hmm_remove_all(struct hashmultimap * _map_, size_t key, size_t * *out_values); _Bool hmm_max(struct hashmultimap * _map_, size_t * key, size_t * value); _Bool hmm_min(struct hashmultimap * _map_, size_t * key, size_t * value); size_t hmm_get(struct hashmultimap * _map_, size_t key); size_t *hmm_get_ref(struct hashmultimap * _map_, size_t key); _Bool hmm_contains(struct hashmultimap * _map_, size_t key); _Bool hmm_empty(struct hashmultimap * _map_); _Bool hmm_full(struct hashmultimap * _map_); size_t hmm_count(struct hashmultimap * _map_); size_t hmm_key_count(struct hashmultimap * _map_, size_t key); size_t hmm_capacity(struct hashmultimap * _map_); double hmm_load(struct hashmultimap * _map_); int hmm_flag(struct hashmultimap * _map_); _Bool hmm_resize(struct hashmultimap * _map_, size_t capacity); struct hashmultimap *hmm_copy_of(struct hashmultimap * _map_); _Bool hmm_equals(struct hashmultimap * _map1_, struct hashmultimap * _map2_); struct hashmultimap_iter { struct hashmultimap *target; struct hashmultimap_entry * curr_entry; size_t cursor; size_t index; size_t first; size_t last; _Bool start; _Bool end; }; struct hashmultimap_iter hmm_iter_start(struct hashmultimap * target); struct hashmultimap_iter hmm_iter_end(struct hashmultimap * target); _Bool hmm_iter_at_start(struct hashmultimap_iter * iter); _Bool hmm_iter_at_end(struct hashmultimap_iter * iter); _Bool hmm_iter_to_start(struct hashmultimap_iter * iter); _Bool hmm_iter_to_end(struct hashmultimap_iter * iter); _Bool hmm_iter_next(struct hashmultimap_iter * iter); _Bool hmm_iter_prev(struct hashmultimap_iter * iter); _Bool hmm_iter_advance(struct hashmultimap_iter * iter, size_t steps); _Bool hmm_iter_rewind(struct hashmultimap_iter * iter, size_t steps); _Bool hmm_iter_go_to(struct hashmultimap_iter * iter, size_t index); size_t hmm_iter_key(struct hashmultimap_iter * iter); size_t hmm_iter_value(struct hashmultimap_iter * iter); size_t *hmm_iter_rvalue(struct hashmultimap_iter * iter); size_t hmm_iter_index(struct hashmultimap_iter * iter); _Bool hmm_to_string(struct hashmultimap * _map_, FILE * fptr); _Bool hmm_print(struct hashmultimap * _map_, FILE * fptr, const char *start, const char *separator, const char *end, const char *key_val_sep); - +#include "macro_collections.h" - #endif /* CMC_CMC_HASHMULTIMAP_TEST_H */ - \ No newline at end of file +struct hashmultimap +{ + struct hashmultimap_entry *(*buffer)[2]; + size_t capacity; + size_t count; + double load; + int flag; + struct hashmultimap_fkey *f_key; + struct hashmultimap_fval *f_val; + struct cmc_alloc_node *alloc; + struct cmc_callbacks *callbacks; +}; +struct hashmultimap_entry +{ + size_t key; + size_t value; + struct hashmultimap_entry *next; + struct hashmultimap_entry *prev; +}; +struct hashmultimap_fkey +{ + int (*cmp)(size_t, size_t); + size_t (*cpy)(size_t); + _Bool (*str)(FILE *, size_t); + void (*free)(size_t); + size_t (*hash)(size_t); + int (*pri)(size_t, size_t); +}; +struct hashmultimap_fval +{ + int (*cmp)(size_t, size_t); + size_t (*cpy)(size_t); + _Bool (*str)(FILE *, size_t); + void (*free)(size_t); + size_t (*hash)(size_t); + int (*pri)(size_t, size_t); +}; +struct hashmultimap *hmm_new(size_t capacity, double load, struct hashmultimap_fkey *f_key, + struct hashmultimap_fval *f_val); +struct hashmultimap *hmm_new_custom(size_t capacity, double load, struct hashmultimap_fkey *f_key, + struct hashmultimap_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks); +void hmm_clear(struct hashmultimap *_map_); +void hmm_free(struct hashmultimap *_map_); +void hmm_customize(struct hashmultimap *_map_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks); +_Bool hmm_insert(struct hashmultimap *_map_, size_t key, size_t value); +_Bool hmm_update(struct hashmultimap *_map_, size_t key, size_t new_value, size_t *old_value); +size_t hmm_update_all(struct hashmultimap *_map_, size_t key, size_t new_value, size_t **old_values); +_Bool hmm_remove(struct hashmultimap *_map_, size_t key, size_t *out_value); +size_t hmm_remove_all(struct hashmultimap *_map_, size_t key, size_t **out_values); +_Bool hmm_max(struct hashmultimap *_map_, size_t *key, size_t *value); +_Bool hmm_min(struct hashmultimap *_map_, size_t *key, size_t *value); +size_t hmm_get(struct hashmultimap *_map_, size_t key); +size_t *hmm_get_ref(struct hashmultimap *_map_, size_t key); +_Bool hmm_contains(struct hashmultimap *_map_, size_t key); +_Bool hmm_empty(struct hashmultimap *_map_); +_Bool hmm_full(struct hashmultimap *_map_); +size_t hmm_count(struct hashmultimap *_map_); +size_t hmm_key_count(struct hashmultimap *_map_, size_t key); +size_t hmm_capacity(struct hashmultimap *_map_); +double hmm_load(struct hashmultimap *_map_); +int hmm_flag(struct hashmultimap *_map_); +_Bool hmm_resize(struct hashmultimap *_map_, size_t capacity); +struct hashmultimap *hmm_copy_of(struct hashmultimap *_map_); +_Bool hmm_equals(struct hashmultimap *_map1_, struct hashmultimap *_map2_); +struct hashmultimap_iter +{ + struct hashmultimap *target; + struct hashmultimap_entry *curr_entry; + size_t cursor; + size_t index; + size_t first; + size_t last; + _Bool start; + _Bool end; +}; +struct hashmultimap_iter hmm_iter_start(struct hashmultimap *target); +struct hashmultimap_iter hmm_iter_end(struct hashmultimap *target); +_Bool hmm_iter_at_start(struct hashmultimap_iter *iter); +_Bool hmm_iter_at_end(struct hashmultimap_iter *iter); +_Bool hmm_iter_to_start(struct hashmultimap_iter *iter); +_Bool hmm_iter_to_end(struct hashmultimap_iter *iter); +_Bool hmm_iter_next(struct hashmultimap_iter *iter); +_Bool hmm_iter_prev(struct hashmultimap_iter *iter); +_Bool hmm_iter_advance(struct hashmultimap_iter *iter, size_t steps); +_Bool hmm_iter_rewind(struct hashmultimap_iter *iter, size_t steps); +_Bool hmm_iter_go_to(struct hashmultimap_iter *iter, size_t index); +size_t hmm_iter_key(struct hashmultimap_iter *iter); +size_t hmm_iter_value(struct hashmultimap_iter *iter); +size_t *hmm_iter_rvalue(struct hashmultimap_iter *iter); +size_t hmm_iter_index(struct hashmultimap_iter *iter); +_Bool hmm_to_string(struct hashmultimap *_map_, FILE *fptr); +_Bool hmm_print(struct hashmultimap *_map_, FILE *fptr, const char *start, const char *separator, const char *end, + const char *key_val_sep); + +#endif /* CMC_CMC_HASHMULTIMAP_TEST_H */ diff --git a/tests/include/tst_cmc_hashmultiset.h b/tests/include/tst_cmc_hashmultiset.h index 8fc3e80..6ab4627 100644 --- a/tests/include/tst_cmc_hashmultiset.h +++ b/tests/include/tst_cmc_hashmultiset.h @@ -1,11 +1,98 @@ - #ifndef CMC_CMC_HASHMULTISET_TEST_H - #define CMC_CMC_HASHMULTISET_TEST_H +#ifndef CMC_CMC_HASHMULTISET_TEST_H +#define CMC_CMC_HASHMULTISET_TEST_H - #include "macro_collections.h" - - struct hashmultiset { struct hashmultiset_entry * buffer; size_t capacity; size_t count; size_t cardinality; double load; int flag; struct hashmultiset_fval * f_val; struct cmc_alloc_node *alloc; struct cmc_callbacks *callbacks; }; struct hashmultiset_entry { size_t value; size_t multiplicity; size_t dist; enum cmc_entry_state state; }; struct hashmultiset_fval { int (*cmp)(size_t, size_t); size_t (*cpy)(size_t); _Bool (*str)(FILE *, size_t); void (*free)(size_t); size_t (*hash)(size_t); int (*pri)(size_t, size_t); }; struct hashmultiset *hms_new(size_t capacity, double load, struct hashmultiset_fval * f_val); struct hashmultiset *hms_new_custom(size_t capacity, double load, struct hashmultiset_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); void hms_clear(struct hashmultiset * _set_); void hms_free(struct hashmultiset * _set_); void hms_customize(struct hashmultiset * _set_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); _Bool hms_insert(struct hashmultiset * _set_, size_t value); _Bool hms_insert_many(struct hashmultiset * _set_, size_t value, size_t count); _Bool hms_update(struct hashmultiset * _set_, size_t value, size_t multiplicity); _Bool hms_remove(struct hashmultiset * _set_, size_t value); size_t hms_remove_all(struct hashmultiset * _set_, size_t value); _Bool hms_max(struct hashmultiset * _set_, size_t * value); _Bool hms_min(struct hashmultiset * _set_, size_t * value); size_t hms_multiplicity_of(struct hashmultiset * _set_, size_t value); _Bool hms_contains(struct hashmultiset * _set_, size_t value); _Bool hms_empty(struct hashmultiset * _set_); _Bool hms_full(struct hashmultiset * _set_); size_t hms_count(struct hashmultiset * _set_); size_t hms_cardinality(struct hashmultiset * _set_); size_t hms_capacity(struct hashmultiset * _set_); double hms_load(struct hashmultiset * _set_); int hms_flag(struct hashmultiset * _set_); _Bool hms_resize(struct hashmultiset * _set_, size_t capacity); struct hashmultiset *hms_copy_of(struct hashmultiset * _set_); _Bool hms_equals(struct hashmultiset * _set1_, struct hashmultiset * _set2_); struct hashmultiset_iter { struct hashmultiset *target; size_t cursor; size_t index; size_t first; size_t last; _Bool start; _Bool end; }; struct hashmultiset_iter hms_iter_start(struct hashmultiset * target); struct hashmultiset_iter hms_iter_end(struct hashmultiset * target); _Bool hms_iter_at_start(struct hashmultiset_iter * iter); _Bool hms_iter_at_end(struct hashmultiset_iter * iter); _Bool hms_iter_to_start(struct hashmultiset_iter * iter); _Bool hms_iter_to_end(struct hashmultiset_iter * iter); _Bool hms_iter_next(struct hashmultiset_iter * iter); _Bool hms_iter_prev(struct hashmultiset_iter * iter); _Bool hms_iter_advance(struct hashmultiset_iter * iter, size_t steps); _Bool hms_iter_rewind(struct hashmultiset_iter * iter, size_t steps); _Bool hms_iter_go_to(struct hashmultiset_iter * iter, size_t index); size_t hms_iter_value(struct hashmultiset_iter * iter); size_t hms_iter_multiplicity(struct hashmultiset_iter * iter); size_t hms_iter_index(struct hashmultiset_iter * iter); struct hashmultiset *hms_union(struct hashmultiset * _set1_, struct hashmultiset * _set2_); struct hashmultiset *hms_intersection(struct hashmultiset * _set1_, struct hashmultiset * _set2_); struct hashmultiset *hms_difference(struct hashmultiset * _set1_, struct hashmultiset * _set2_); struct hashmultiset *hms_summation(struct hashmultiset * _set1_, struct hashmultiset * _set2_); struct hashmultiset *hms_symmetric_difference(struct hashmultiset * _set1_, struct hashmultiset * _set2_); _Bool hms_is_subset(struct hashmultiset * _set1_, struct hashmultiset * _set2_); _Bool hms_is_superset(struct hashmultiset * _set1_, struct hashmultiset * _set2_); _Bool hms_is_proper_subset(struct hashmultiset * _set1_, struct hashmultiset * _set2_); _Bool hms_is_proper_superset(struct hashmultiset * _set1_, struct hashmultiset * _set2_); _Bool hms_is_disjointset(struct hashmultiset * _set1_, struct hashmultiset * _set2_); _Bool hms_to_string(struct hashmultiset * _set_, FILE * fptr); _Bool hms_print(struct hashmultiset * _set_, FILE * fptr, const char *start, const char *separator, const char *end, const char *key_val_sep); - +#include "macro_collections.h" - #endif /* CMC_CMC_HASHMULTISET_TEST_H */ - \ No newline at end of file +struct hashmultiset +{ + struct hashmultiset_entry *buffer; + size_t capacity; + size_t count; + size_t cardinality; + double load; + int flag; + struct hashmultiset_fval *f_val; + struct cmc_alloc_node *alloc; + struct cmc_callbacks *callbacks; +}; +struct hashmultiset_entry +{ + size_t value; + size_t multiplicity; + size_t dist; + enum cmc_entry_state state; +}; +struct hashmultiset_fval +{ + int (*cmp)(size_t, size_t); + size_t (*cpy)(size_t); + _Bool (*str)(FILE *, size_t); + void (*free)(size_t); + size_t (*hash)(size_t); + int (*pri)(size_t, size_t); +}; +struct hashmultiset *hms_new(size_t capacity, double load, struct hashmultiset_fval *f_val); +struct hashmultiset *hms_new_custom(size_t capacity, double load, struct hashmultiset_fval *f_val, + struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks); +void hms_clear(struct hashmultiset *_set_); +void hms_free(struct hashmultiset *_set_); +void hms_customize(struct hashmultiset *_set_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks); +_Bool hms_insert(struct hashmultiset *_set_, size_t value); +_Bool hms_insert_many(struct hashmultiset *_set_, size_t value, size_t count); +_Bool hms_update(struct hashmultiset *_set_, size_t value, size_t multiplicity); +_Bool hms_remove(struct hashmultiset *_set_, size_t value); +size_t hms_remove_all(struct hashmultiset *_set_, size_t value); +_Bool hms_max(struct hashmultiset *_set_, size_t *value); +_Bool hms_min(struct hashmultiset *_set_, size_t *value); +size_t hms_multiplicity_of(struct hashmultiset *_set_, size_t value); +_Bool hms_contains(struct hashmultiset *_set_, size_t value); +_Bool hms_empty(struct hashmultiset *_set_); +_Bool hms_full(struct hashmultiset *_set_); +size_t hms_count(struct hashmultiset *_set_); +size_t hms_cardinality(struct hashmultiset *_set_); +size_t hms_capacity(struct hashmultiset *_set_); +double hms_load(struct hashmultiset *_set_); +int hms_flag(struct hashmultiset *_set_); +_Bool hms_resize(struct hashmultiset *_set_, size_t capacity); +struct hashmultiset *hms_copy_of(struct hashmultiset *_set_); +_Bool hms_equals(struct hashmultiset *_set1_, struct hashmultiset *_set2_); +struct hashmultiset_iter +{ + struct hashmultiset *target; + size_t cursor; + size_t index; + size_t first; + size_t last; + _Bool start; + _Bool end; +}; +struct hashmultiset_iter hms_iter_start(struct hashmultiset *target); +struct hashmultiset_iter hms_iter_end(struct hashmultiset *target); +_Bool hms_iter_at_start(struct hashmultiset_iter *iter); +_Bool hms_iter_at_end(struct hashmultiset_iter *iter); +_Bool hms_iter_to_start(struct hashmultiset_iter *iter); +_Bool hms_iter_to_end(struct hashmultiset_iter *iter); +_Bool hms_iter_next(struct hashmultiset_iter *iter); +_Bool hms_iter_prev(struct hashmultiset_iter *iter); +_Bool hms_iter_advance(struct hashmultiset_iter *iter, size_t steps); +_Bool hms_iter_rewind(struct hashmultiset_iter *iter, size_t steps); +_Bool hms_iter_go_to(struct hashmultiset_iter *iter, size_t index); +size_t hms_iter_value(struct hashmultiset_iter *iter); +size_t hms_iter_multiplicity(struct hashmultiset_iter *iter); +size_t hms_iter_index(struct hashmultiset_iter *iter); +struct hashmultiset *hms_union(struct hashmultiset *_set1_, struct hashmultiset *_set2_); +struct hashmultiset *hms_intersection(struct hashmultiset *_set1_, struct hashmultiset *_set2_); +struct hashmultiset *hms_difference(struct hashmultiset *_set1_, struct hashmultiset *_set2_); +struct hashmultiset *hms_summation(struct hashmultiset *_set1_, struct hashmultiset *_set2_); +struct hashmultiset *hms_symmetric_difference(struct hashmultiset *_set1_, struct hashmultiset *_set2_); +_Bool hms_is_subset(struct hashmultiset *_set1_, struct hashmultiset *_set2_); +_Bool hms_is_superset(struct hashmultiset *_set1_, struct hashmultiset *_set2_); +_Bool hms_is_proper_subset(struct hashmultiset *_set1_, struct hashmultiset *_set2_); +_Bool hms_is_proper_superset(struct hashmultiset *_set1_, struct hashmultiset *_set2_); +_Bool hms_is_disjointset(struct hashmultiset *_set1_, struct hashmultiset *_set2_); +_Bool hms_to_string(struct hashmultiset *_set_, FILE *fptr); +_Bool hms_print(struct hashmultiset *_set_, FILE *fptr, const char *start, const char *separator, const char *end, + const char *key_val_sep); + +#endif /* CMC_CMC_HASHMULTISET_TEST_H */ diff --git a/tests/include/tst_cmc_hashset.h b/tests/include/tst_cmc_hashset.h index bf1b031..a9ab75c 100644 --- a/tests/include/tst_cmc_hashset.h +++ b/tests/include/tst_cmc_hashset.h @@ -1,11 +1,88 @@ - #ifndef CMC_CMC_HASHSET_TEST_H - #define CMC_CMC_HASHSET_TEST_H +#ifndef CMC_CMC_HASHSET_TEST_H +#define CMC_CMC_HASHSET_TEST_H - #include "macro_collections.h" - - struct hashset { struct hashset_entry * buffer; size_t capacity; size_t count; double load; int flag; struct hashset_fval * f_val; struct cmc_alloc_node *alloc; struct cmc_callbacks *callbacks; }; struct hashset_entry { size_t value; size_t dist; enum cmc_entry_state state; }; struct hashset_fval { int (*cmp)(size_t, size_t); size_t (*cpy)(size_t); _Bool (*str)(FILE *, size_t); void (*free)(size_t); size_t (*hash)(size_t); int (*pri)(size_t, size_t); }; struct hashset *hs_new(size_t capacity, double load, struct hashset_fval * f_val); struct hashset *hs_new_custom(size_t capacity, double load, struct hashset_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); void hs_clear(struct hashset * _set_); void hs_free(struct hashset * _set_); void hs_customize(struct hashset * _set_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); _Bool hs_insert(struct hashset * _set_, size_t value); _Bool hs_remove(struct hashset * _set_, size_t value); _Bool hs_max(struct hashset * _set_, size_t * value); _Bool hs_min(struct hashset * _set_, size_t * value); _Bool hs_contains(struct hashset * _set_, size_t value); _Bool hs_empty(struct hashset * _set_); _Bool hs_full(struct hashset * _set_); size_t hs_count(struct hashset * _set_); size_t hs_capacity(struct hashset * _set_); double hs_load(struct hashset * _set_); int hs_flag(struct hashset * _set_); _Bool hs_resize(struct hashset * _set_, size_t capacity); struct hashset *hs_copy_of(struct hashset * _set_); _Bool hs_equals(struct hashset * _set1_, struct hashset * _set2_); struct hashset_iter { struct hashset *target; size_t cursor; size_t index; size_t first; size_t last; _Bool start; _Bool end; }; struct hashset_iter hs_iter_start(struct hashset * target); struct hashset_iter hs_iter_end(struct hashset * target); _Bool hs_iter_at_start(struct hashset_iter * iter); _Bool hs_iter_at_end(struct hashset_iter * iter); _Bool hs_iter_to_start(struct hashset_iter * iter); _Bool hs_iter_to_end(struct hashset_iter * iter); _Bool hs_iter_next(struct hashset_iter * iter); _Bool hs_iter_prev(struct hashset_iter * iter); _Bool hs_iter_advance(struct hashset_iter * iter, size_t steps); _Bool hs_iter_rewind(struct hashset_iter * iter, size_t steps); _Bool hs_iter_go_to(struct hashset_iter * iter, size_t index); size_t hs_iter_value(struct hashset_iter * iter); size_t hs_iter_index(struct hashset_iter * iter); struct hashset *hs_union(struct hashset * _set1_, struct hashset * _set2_); struct hashset *hs_intersection(struct hashset * _set1_, struct hashset * _set2_); struct hashset *hs_difference(struct hashset * _set1_, struct hashset * _set2_); struct hashset *hs_symmetric_difference(struct hashset * _set1_, struct hashset * _set2_); _Bool hs_is_subset(struct hashset * _set1_, struct hashset * _set2_); _Bool hs_is_superset(struct hashset * _set1_, struct hashset * _set2_); _Bool hs_is_proper_subset(struct hashset * _set1_, struct hashset * _set2_); _Bool hs_is_proper_superset(struct hashset * _set1_, struct hashset * _set2_); _Bool hs_is_disjointset(struct hashset * _set1_, struct hashset * _set2_); _Bool hs_to_string(struct hashset * _set_, FILE * fptr); _Bool hs_print(struct hashset * _set_, FILE * fptr, const char *start, const char *separator, const char *end); - +#include "macro_collections.h" - #endif /* CMC_CMC_HASHSET_TEST_H */ - \ No newline at end of file +struct hashset +{ + struct hashset_entry *buffer; + size_t capacity; + size_t count; + double load; + int flag; + struct hashset_fval *f_val; + struct cmc_alloc_node *alloc; + struct cmc_callbacks *callbacks; +}; +struct hashset_entry +{ + size_t value; + size_t dist; + enum cmc_entry_state state; +}; +struct hashset_fval +{ + int (*cmp)(size_t, size_t); + size_t (*cpy)(size_t); + _Bool (*str)(FILE *, size_t); + void (*free)(size_t); + size_t (*hash)(size_t); + int (*pri)(size_t, size_t); +}; +struct hashset *hs_new(size_t capacity, double load, struct hashset_fval *f_val); +struct hashset *hs_new_custom(size_t capacity, double load, struct hashset_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks); +void hs_clear(struct hashset *_set_); +void hs_free(struct hashset *_set_); +void hs_customize(struct hashset *_set_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks); +_Bool hs_insert(struct hashset *_set_, size_t value); +_Bool hs_remove(struct hashset *_set_, size_t value); +_Bool hs_max(struct hashset *_set_, size_t *value); +_Bool hs_min(struct hashset *_set_, size_t *value); +_Bool hs_contains(struct hashset *_set_, size_t value); +_Bool hs_empty(struct hashset *_set_); +_Bool hs_full(struct hashset *_set_); +size_t hs_count(struct hashset *_set_); +size_t hs_capacity(struct hashset *_set_); +double hs_load(struct hashset *_set_); +int hs_flag(struct hashset *_set_); +_Bool hs_resize(struct hashset *_set_, size_t capacity); +struct hashset *hs_copy_of(struct hashset *_set_); +_Bool hs_equals(struct hashset *_set1_, struct hashset *_set2_); +struct hashset_iter +{ + struct hashset *target; + size_t cursor; + size_t index; + size_t first; + size_t last; + _Bool start; + _Bool end; +}; +struct hashset_iter hs_iter_start(struct hashset *target); +struct hashset_iter hs_iter_end(struct hashset *target); +_Bool hs_iter_at_start(struct hashset_iter *iter); +_Bool hs_iter_at_end(struct hashset_iter *iter); +_Bool hs_iter_to_start(struct hashset_iter *iter); +_Bool hs_iter_to_end(struct hashset_iter *iter); +_Bool hs_iter_next(struct hashset_iter *iter); +_Bool hs_iter_prev(struct hashset_iter *iter); +_Bool hs_iter_advance(struct hashset_iter *iter, size_t steps); +_Bool hs_iter_rewind(struct hashset_iter *iter, size_t steps); +_Bool hs_iter_go_to(struct hashset_iter *iter, size_t index); +size_t hs_iter_value(struct hashset_iter *iter); +size_t hs_iter_index(struct hashset_iter *iter); +struct hashset *hs_union(struct hashset *_set1_, struct hashset *_set2_); +struct hashset *hs_intersection(struct hashset *_set1_, struct hashset *_set2_); +struct hashset *hs_difference(struct hashset *_set1_, struct hashset *_set2_); +struct hashset *hs_symmetric_difference(struct hashset *_set1_, struct hashset *_set2_); +_Bool hs_is_subset(struct hashset *_set1_, struct hashset *_set2_); +_Bool hs_is_superset(struct hashset *_set1_, struct hashset *_set2_); +_Bool hs_is_proper_subset(struct hashset *_set1_, struct hashset *_set2_); +_Bool hs_is_proper_superset(struct hashset *_set1_, struct hashset *_set2_); +_Bool hs_is_disjointset(struct hashset *_set1_, struct hashset *_set2_); +_Bool hs_to_string(struct hashset *_set_, FILE *fptr); +_Bool hs_print(struct hashset *_set_, FILE *fptr, const char *start, const char *separator, const char *end); + +#endif /* CMC_CMC_HASHSET_TEST_H */ diff --git a/tests/include/tst_cmc_heap.h b/tests/include/tst_cmc_heap.h index 73aa0c6..8b062f1 100644 --- a/tests/include/tst_cmc_heap.h +++ b/tests/include/tst_cmc_heap.h @@ -1,11 +1,68 @@ - #ifndef CMC_CMC_HEAP_TEST_H - #define CMC_CMC_HEAP_TEST_H +#ifndef CMC_CMC_HEAP_TEST_H +#define CMC_CMC_HEAP_TEST_H - #include "macro_collections.h" - - struct heap { size_t *buffer; size_t capacity; size_t count; enum cmc_heap_order HO; int flag; struct heap_fval * f_val; struct cmc_alloc_node *alloc; struct cmc_callbacks *callbacks; }; struct heap_fval { int (*cmp)(size_t, size_t); size_t (*cpy)(size_t); _Bool (*str)(FILE *, size_t); void (*free)(size_t); size_t (*hash)(size_t); int (*pri)(size_t, size_t); }; struct heap *h_new(size_t capacity, enum cmc_heap_order HO, struct heap_fval * f_val); struct heap *h_new_custom(size_t capacity, enum cmc_heap_order HO, struct heap_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); void h_clear(struct heap * _heap_); void h_free(struct heap * _heap_); void h_customize(struct heap * _heap_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); _Bool h_insert(struct heap * _heap_, size_t value); _Bool h_remove(struct heap * _heap_); size_t h_peek(struct heap * _heap_); _Bool h_contains(struct heap * _heap_, size_t value); _Bool h_empty(struct heap * _heap_); _Bool h_full(struct heap * _heap_); size_t h_count(struct heap * _heap_); size_t h_capacity(struct heap * _heap_); int h_flag(struct heap * _heap_); _Bool h_resize(struct heap * _heap_, size_t capacity); struct heap *h_copy_of(struct heap * _heap_); _Bool h_equals(struct heap * _heap1_, struct heap * _heap2_); struct heap_iter { struct heap *target; size_t cursor; _Bool start; _Bool end; }; struct heap_iter h_iter_start(struct heap * target); struct heap_iter h_iter_end(struct heap * target); _Bool h_iter_at_start(struct heap_iter * iter); _Bool h_iter_at_end(struct heap_iter * iter); _Bool h_iter_to_start(struct heap_iter * iter); _Bool h_iter_to_end(struct heap_iter * iter); _Bool h_iter_next(struct heap_iter * iter); _Bool h_iter_prev(struct heap_iter * iter); _Bool h_iter_advance(struct heap_iter * iter, size_t steps); _Bool h_iter_rewind(struct heap_iter * iter, size_t steps); _Bool h_iter_go_to(struct heap_iter * iter, size_t index); size_t h_iter_value(struct heap_iter * iter); size_t h_iter_index(struct heap_iter * iter); _Bool h_to_string(struct heap * _heap_, FILE * fptr); _Bool h_print(struct heap * _heap_, FILE * fptr, const char *start, const char *separator, const char *end); - +#include "macro_collections.h" - #endif /* CMC_CMC_HEAP_TEST_H */ - \ No newline at end of file +struct heap +{ + size_t *buffer; + size_t capacity; + size_t count; + enum cmc_heap_order HO; + int flag; + struct heap_fval *f_val; + struct cmc_alloc_node *alloc; + struct cmc_callbacks *callbacks; +}; +struct heap_fval +{ + int (*cmp)(size_t, size_t); + size_t (*cpy)(size_t); + _Bool (*str)(FILE *, size_t); + void (*free)(size_t); + size_t (*hash)(size_t); + int (*pri)(size_t, size_t); +}; +struct heap *h_new(size_t capacity, enum cmc_heap_order HO, struct heap_fval *f_val); +struct heap *h_new_custom(size_t capacity, enum cmc_heap_order HO, struct heap_fval *f_val, + struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks); +void h_clear(struct heap *_heap_); +void h_free(struct heap *_heap_); +void h_customize(struct heap *_heap_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks); +_Bool h_insert(struct heap *_heap_, size_t value); +_Bool h_remove(struct heap *_heap_); +size_t h_peek(struct heap *_heap_); +_Bool h_contains(struct heap *_heap_, size_t value); +_Bool h_empty(struct heap *_heap_); +_Bool h_full(struct heap *_heap_); +size_t h_count(struct heap *_heap_); +size_t h_capacity(struct heap *_heap_); +int h_flag(struct heap *_heap_); +_Bool h_resize(struct heap *_heap_, size_t capacity); +struct heap *h_copy_of(struct heap *_heap_); +_Bool h_equals(struct heap *_heap1_, struct heap *_heap2_); +struct heap_iter +{ + struct heap *target; + size_t cursor; + _Bool start; + _Bool end; +}; +struct heap_iter h_iter_start(struct heap *target); +struct heap_iter h_iter_end(struct heap *target); +_Bool h_iter_at_start(struct heap_iter *iter); +_Bool h_iter_at_end(struct heap_iter *iter); +_Bool h_iter_to_start(struct heap_iter *iter); +_Bool h_iter_to_end(struct heap_iter *iter); +_Bool h_iter_next(struct heap_iter *iter); +_Bool h_iter_prev(struct heap_iter *iter); +_Bool h_iter_advance(struct heap_iter *iter, size_t steps); +_Bool h_iter_rewind(struct heap_iter *iter, size_t steps); +_Bool h_iter_go_to(struct heap_iter *iter, size_t index); +size_t h_iter_value(struct heap_iter *iter); +size_t h_iter_index(struct heap_iter *iter); +_Bool h_to_string(struct heap *_heap_, FILE *fptr); +_Bool h_print(struct heap *_heap_, FILE *fptr, const char *start, const char *separator, const char *end); + +#endif /* CMC_CMC_HEAP_TEST_H */ diff --git a/tests/include/tst_cmc_intervalheap.h b/tests/include/tst_cmc_intervalheap.h index 28b3010..5bc4fb2 100644 --- a/tests/include/tst_cmc_intervalheap.h +++ b/tests/include/tst_cmc_intervalheap.h @@ -1,11 +1,72 @@ - #ifndef CMC_CMC_INTERVALHEAP_TEST_H - #define CMC_CMC_INTERVALHEAP_TEST_H +#ifndef CMC_CMC_INTERVALHEAP_TEST_H +#define CMC_CMC_INTERVALHEAP_TEST_H - #include "macro_collections.h" - - struct intervalheap { size_t (*buffer)[2]; size_t capacity; size_t size; size_t count; int flag; struct intervalheap_fval * f_val; struct cmc_alloc_node *alloc; struct cmc_callbacks *callbacks; }; struct intervalheap_fval { int (*cmp)(size_t, size_t); size_t (*cpy)(size_t); _Bool (*str)(FILE *, size_t); void (*free)(size_t); size_t (*hash)(size_t); int (*pri)(size_t, size_t); }; struct intervalheap *ih_new(size_t capacity, struct intervalheap_fval * f_val); struct intervalheap *ih_new_custom(size_t capacity, struct intervalheap_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); void ih_clear(struct intervalheap * _heap_); void ih_free(struct intervalheap * _heap_); void ih_customize(struct intervalheap * _heap_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); _Bool ih_insert(struct intervalheap * _heap_, size_t value); _Bool ih_remove_max(struct intervalheap * _heap_); _Bool ih_remove_min(struct intervalheap * _heap_); _Bool ih_update_max(struct intervalheap * _heap_, size_t value); _Bool ih_update_min(struct intervalheap * _heap_, size_t value); size_t ih_max(struct intervalheap * _heap_); size_t ih_min(struct intervalheap * _heap_); _Bool ih_contains(struct intervalheap * _heap_, size_t value); _Bool ih_empty(struct intervalheap * _heap_); _Bool ih_full(struct intervalheap * _heap_); size_t ih_count(struct intervalheap * _heap_); size_t ih_capacity(struct intervalheap * _heap_); int ih_flag(struct intervalheap * _heap_); _Bool ih_resize(struct intervalheap * _heap_, size_t capacity); struct intervalheap *ih_copy_of(struct intervalheap * _heap_); _Bool ih_equals(struct intervalheap * _heap1_, struct intervalheap * _heap2_); struct intervalheap_iter { struct intervalheap *target; size_t cursor; _Bool start; _Bool end; }; struct intervalheap_iter ih_iter_start(struct intervalheap * target); struct intervalheap_iter ih_iter_end(struct intervalheap * target); _Bool ih_iter_at_start(struct intervalheap_iter * iter); _Bool ih_iter_at_end(struct intervalheap_iter * iter); _Bool ih_iter_to_start(struct intervalheap_iter * iter); _Bool ih_iter_to_end(struct intervalheap_iter * iter); _Bool ih_iter_next(struct intervalheap_iter * iter); _Bool ih_iter_prev(struct intervalheap_iter * iter); _Bool ih_iter_advance(struct intervalheap_iter * iter, size_t steps); _Bool ih_iter_rewind(struct intervalheap_iter * iter, size_t steps); _Bool ih_iter_go_to(struct intervalheap_iter * iter, size_t index); size_t ih_iter_value(struct intervalheap_iter * iter); size_t ih_iter_index(struct intervalheap_iter * iter); _Bool ih_to_string(struct intervalheap * _heap_, FILE * fptr); _Bool ih_print(struct intervalheap * _heap_, FILE * fptr, const char *start, const char *separator, const char *end); - +#include "macro_collections.h" - #endif /* CMC_CMC_INTERVALHEAP_TEST_H */ - \ No newline at end of file +struct intervalheap +{ + size_t (*buffer)[2]; + size_t capacity; + size_t size; + size_t count; + int flag; + struct intervalheap_fval *f_val; + struct cmc_alloc_node *alloc; + struct cmc_callbacks *callbacks; +}; +struct intervalheap_fval +{ + int (*cmp)(size_t, size_t); + size_t (*cpy)(size_t); + _Bool (*str)(FILE *, size_t); + void (*free)(size_t); + size_t (*hash)(size_t); + int (*pri)(size_t, size_t); +}; +struct intervalheap *ih_new(size_t capacity, struct intervalheap_fval *f_val); +struct intervalheap *ih_new_custom(size_t capacity, struct intervalheap_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks); +void ih_clear(struct intervalheap *_heap_); +void ih_free(struct intervalheap *_heap_); +void ih_customize(struct intervalheap *_heap_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks); +_Bool ih_insert(struct intervalheap *_heap_, size_t value); +_Bool ih_remove_max(struct intervalheap *_heap_); +_Bool ih_remove_min(struct intervalheap *_heap_); +_Bool ih_update_max(struct intervalheap *_heap_, size_t value); +_Bool ih_update_min(struct intervalheap *_heap_, size_t value); +size_t ih_max(struct intervalheap *_heap_); +size_t ih_min(struct intervalheap *_heap_); +_Bool ih_contains(struct intervalheap *_heap_, size_t value); +_Bool ih_empty(struct intervalheap *_heap_); +_Bool ih_full(struct intervalheap *_heap_); +size_t ih_count(struct intervalheap *_heap_); +size_t ih_capacity(struct intervalheap *_heap_); +int ih_flag(struct intervalheap *_heap_); +_Bool ih_resize(struct intervalheap *_heap_, size_t capacity); +struct intervalheap *ih_copy_of(struct intervalheap *_heap_); +_Bool ih_equals(struct intervalheap *_heap1_, struct intervalheap *_heap2_); +struct intervalheap_iter +{ + struct intervalheap *target; + size_t cursor; + _Bool start; + _Bool end; +}; +struct intervalheap_iter ih_iter_start(struct intervalheap *target); +struct intervalheap_iter ih_iter_end(struct intervalheap *target); +_Bool ih_iter_at_start(struct intervalheap_iter *iter); +_Bool ih_iter_at_end(struct intervalheap_iter *iter); +_Bool ih_iter_to_start(struct intervalheap_iter *iter); +_Bool ih_iter_to_end(struct intervalheap_iter *iter); +_Bool ih_iter_next(struct intervalheap_iter *iter); +_Bool ih_iter_prev(struct intervalheap_iter *iter); +_Bool ih_iter_advance(struct intervalheap_iter *iter, size_t steps); +_Bool ih_iter_rewind(struct intervalheap_iter *iter, size_t steps); +_Bool ih_iter_go_to(struct intervalheap_iter *iter, size_t index); +size_t ih_iter_value(struct intervalheap_iter *iter); +size_t ih_iter_index(struct intervalheap_iter *iter); +_Bool ih_to_string(struct intervalheap *_heap_, FILE *fptr); +_Bool ih_print(struct intervalheap *_heap_, FILE *fptr, const char *start, const char *separator, const char *end); + +#endif /* CMC_CMC_INTERVALHEAP_TEST_H */ diff --git a/tests/include/tst_cmc_linkedlist.h b/tests/include/tst_cmc_linkedlist.h index e682e9e..c06925d 100644 --- a/tests/include/tst_cmc_linkedlist.h +++ b/tests/include/tst_cmc_linkedlist.h @@ -1,11 +1,92 @@ - #ifndef CMC_CMC_LINKEDLIST_TEST_H - #define CMC_CMC_LINKEDLIST_TEST_H +#ifndef CMC_CMC_LINKEDLIST_TEST_H +#define CMC_CMC_LINKEDLIST_TEST_H - #include "macro_collections.h" - - struct linkedlist { struct linkedlist_node * head; struct linkedlist_node * tail; size_t count; int flag; struct linkedlist_fval * f_val; struct cmc_alloc_node *alloc; struct cmc_callbacks *callbacks; }; struct linkedlist_node { size_t value; struct linkedlist_node * next; struct linkedlist_node * prev; }; struct linkedlist_fval { int (*cmp)(size_t, size_t); size_t (*cpy)(size_t); _Bool (*str)(FILE *, size_t); void (*free)(size_t); size_t (*hash)(size_t); int (*pri)(size_t, size_t); }; struct linkedlist *ll_new(struct linkedlist_fval * f_val); struct linkedlist *ll_new_custom(struct linkedlist_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); void ll_clear(struct linkedlist * _list_); void ll_free(struct linkedlist * _list_); void ll_customize(struct linkedlist * _list_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); _Bool ll_push_front(struct linkedlist * _list_, size_t value); _Bool ll_push_at(struct linkedlist * _list_, size_t value, size_t index); _Bool ll_push_back(struct linkedlist * _list_, size_t value); _Bool ll_pop_front(struct linkedlist * _list_); _Bool ll_pop_at(struct linkedlist * _list_, size_t index); _Bool ll_pop_back(struct linkedlist * _list_); size_t ll_front(struct linkedlist * _list_); size_t ll_get(struct linkedlist * _list_, size_t index); size_t *ll_get_ref(struct linkedlist * _list_, size_t index); size_t ll_back(struct linkedlist * _list_); _Bool ll_contains(struct linkedlist * _list_, size_t value); _Bool ll_empty(struct linkedlist * _list_); size_t ll_count(struct linkedlist * _list_); int ll_flag(struct linkedlist * _list_); struct linkedlist *ll_copy_of(struct linkedlist * _list_); _Bool ll_equals(struct linkedlist * _list1_, struct linkedlist * _list2_); struct linkedlist_iter { struct linkedlist *target; struct linkedlist_node * cursor; size_t index; _Bool start; _Bool end; }; struct linkedlist_iter ll_iter_start(struct linkedlist * target); struct linkedlist_iter ll_iter_end(struct linkedlist * target); _Bool ll_iter_at_start(struct linkedlist_iter * iter); _Bool ll_iter_at_end(struct linkedlist_iter * iter); _Bool ll_iter_to_start(struct linkedlist_iter * iter); _Bool ll_iter_to_end(struct linkedlist_iter * iter); _Bool ll_iter_next(struct linkedlist_iter * iter); _Bool ll_iter_prev(struct linkedlist_iter * iter); _Bool ll_iter_advance(struct linkedlist_iter * iter, size_t steps); _Bool ll_iter_rewind(struct linkedlist_iter * iter, size_t steps); _Bool ll_iter_go_to(struct linkedlist_iter * iter, size_t index); size_t ll_iter_value(struct linkedlist_iter * iter); size_t *ll_iter_rvalue(struct linkedlist_iter * iter); size_t ll_iter_index(struct linkedlist_iter * iter); struct linkedlist_node * ll_iter_node(struct linkedlist_iter * iter); struct linkedlist_node * ll_new_node(struct linkedlist * _list_, size_t value); void ll_free_node(struct linkedlist * _list_, struct linkedlist_node * _node_); struct linkedlist_node * ll_head(struct linkedlist * _list_); struct linkedlist_node * ll_get_node(struct linkedlist * _list_, size_t index); struct linkedlist_node * ll_tail(struct linkedlist * _list_); _Bool ll_add_next(struct linkedlist * _owner_, struct linkedlist_node * _node_, size_t value); _Bool ll_add_prev(struct linkedlist * _owner_, struct linkedlist_node * _node_, size_t value); _Bool ll_del_next(struct linkedlist * _owner_, struct linkedlist_node * _node_); _Bool ll_del_curr(struct linkedlist * _owner_, struct linkedlist_node * _node_); _Bool ll_del_prev(struct linkedlist * _owner_, struct linkedlist_node * _node_); struct linkedlist_node * ll_next_node(struct linkedlist_node * _node_); struct linkedlist_node * ll_prev_node(struct linkedlist_node * _node_); _Bool ll_to_string(struct linkedlist * _list_, FILE * fptr); _Bool ll_print(struct linkedlist * _list_, FILE * fptr, const char *start, const char *separator, const char *end); - +#include "macro_collections.h" - #endif /* CMC_CMC_LINKEDLIST_TEST_H */ - \ No newline at end of file +struct linkedlist +{ + struct linkedlist_node *head; + struct linkedlist_node *tail; + size_t count; + int flag; + struct linkedlist_fval *f_val; + struct cmc_alloc_node *alloc; + struct cmc_callbacks *callbacks; +}; +struct linkedlist_node +{ + size_t value; + struct linkedlist_node *next; + struct linkedlist_node *prev; +}; +struct linkedlist_fval +{ + int (*cmp)(size_t, size_t); + size_t (*cpy)(size_t); + _Bool (*str)(FILE *, size_t); + void (*free)(size_t); + size_t (*hash)(size_t); + int (*pri)(size_t, size_t); +}; +struct linkedlist *ll_new(struct linkedlist_fval *f_val); +struct linkedlist *ll_new_custom(struct linkedlist_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks); +void ll_clear(struct linkedlist *_list_); +void ll_free(struct linkedlist *_list_); +void ll_customize(struct linkedlist *_list_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks); +_Bool ll_push_front(struct linkedlist *_list_, size_t value); +_Bool ll_push_at(struct linkedlist *_list_, size_t value, size_t index); +_Bool ll_push_back(struct linkedlist *_list_, size_t value); +_Bool ll_pop_front(struct linkedlist *_list_); +_Bool ll_pop_at(struct linkedlist *_list_, size_t index); +_Bool ll_pop_back(struct linkedlist *_list_); +size_t ll_front(struct linkedlist *_list_); +size_t ll_get(struct linkedlist *_list_, size_t index); +size_t *ll_get_ref(struct linkedlist *_list_, size_t index); +size_t ll_back(struct linkedlist *_list_); +_Bool ll_contains(struct linkedlist *_list_, size_t value); +_Bool ll_empty(struct linkedlist *_list_); +size_t ll_count(struct linkedlist *_list_); +int ll_flag(struct linkedlist *_list_); +struct linkedlist *ll_copy_of(struct linkedlist *_list_); +_Bool ll_equals(struct linkedlist *_list1_, struct linkedlist *_list2_); +struct linkedlist_iter +{ + struct linkedlist *target; + struct linkedlist_node *cursor; + size_t index; + _Bool start; + _Bool end; +}; +struct linkedlist_iter ll_iter_start(struct linkedlist *target); +struct linkedlist_iter ll_iter_end(struct linkedlist *target); +_Bool ll_iter_at_start(struct linkedlist_iter *iter); +_Bool ll_iter_at_end(struct linkedlist_iter *iter); +_Bool ll_iter_to_start(struct linkedlist_iter *iter); +_Bool ll_iter_to_end(struct linkedlist_iter *iter); +_Bool ll_iter_next(struct linkedlist_iter *iter); +_Bool ll_iter_prev(struct linkedlist_iter *iter); +_Bool ll_iter_advance(struct linkedlist_iter *iter, size_t steps); +_Bool ll_iter_rewind(struct linkedlist_iter *iter, size_t steps); +_Bool ll_iter_go_to(struct linkedlist_iter *iter, size_t index); +size_t ll_iter_value(struct linkedlist_iter *iter); +size_t *ll_iter_rvalue(struct linkedlist_iter *iter); +size_t ll_iter_index(struct linkedlist_iter *iter); +struct linkedlist_node *ll_iter_node(struct linkedlist_iter *iter); +struct linkedlist_node *ll_new_node(struct linkedlist *_list_, size_t value); +void ll_free_node(struct linkedlist *_list_, struct linkedlist_node *_node_); +struct linkedlist_node *ll_head(struct linkedlist *_list_); +struct linkedlist_node *ll_get_node(struct linkedlist *_list_, size_t index); +struct linkedlist_node *ll_tail(struct linkedlist *_list_); +_Bool ll_add_next(struct linkedlist *_owner_, struct linkedlist_node *_node_, size_t value); +_Bool ll_add_prev(struct linkedlist *_owner_, struct linkedlist_node *_node_, size_t value); +_Bool ll_del_next(struct linkedlist *_owner_, struct linkedlist_node *_node_); +_Bool ll_del_curr(struct linkedlist *_owner_, struct linkedlist_node *_node_); +_Bool ll_del_prev(struct linkedlist *_owner_, struct linkedlist_node *_node_); +struct linkedlist_node *ll_next_node(struct linkedlist_node *_node_); +struct linkedlist_node *ll_prev_node(struct linkedlist_node *_node_); +_Bool ll_to_string(struct linkedlist *_list_, FILE *fptr); +_Bool ll_print(struct linkedlist *_list_, FILE *fptr, const char *start, const char *separator, const char *end); + +#endif /* CMC_CMC_LINKEDLIST_TEST_H */ diff --git a/tests/include/tst_cmc_list.h b/tests/include/tst_cmc_list.h index f7def9b..3a1043d 100644 --- a/tests/include/tst_cmc_list.h +++ b/tests/include/tst_cmc_list.h @@ -1,11 +1,82 @@ - #ifndef CMC_CMC_LIST_TEST_H - #define CMC_CMC_LIST_TEST_H +#ifndef CMC_CMC_LIST_TEST_H +#define CMC_CMC_LIST_TEST_H - #include "macro_collections.h" - - struct list { size_t *buffer; size_t capacity; size_t count; int flag; struct list_fval * f_val; struct cmc_alloc_node *alloc; struct cmc_callbacks *callbacks; }; struct list_fval { int (*cmp)(size_t, size_t); size_t (*cpy)(size_t); _Bool (*str)(FILE *, size_t); void (*free)(size_t); size_t (*hash)(size_t); int (*pri)(size_t, size_t); }; struct list *l_new(size_t capacity, struct list_fval * f_val); struct list *l_new_custom(size_t capacity, struct list_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); void l_clear(struct list * _list_); void l_free(struct list * _list_); void l_customize(struct list * _list_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); _Bool l_push_front(struct list * _list_, size_t value); _Bool l_push_at(struct list * _list_, size_t value, size_t index); _Bool l_push_back(struct list * _list_, size_t value); _Bool l_pop_front(struct list * _list_); _Bool l_pop_at(struct list * _list_, size_t index); _Bool l_pop_back(struct list * _list_); size_t l_front(struct list * _list_); size_t l_get(struct list * _list_, size_t index); size_t *l_get_ref(struct list * _list_, size_t index); size_t l_back(struct list * _list_); size_t l_index_of(struct list * _list_, size_t value, _Bool from_start); _Bool l_contains(struct list * _list_, size_t value); _Bool l_empty(struct list * _list_); _Bool l_full(struct list * _list_); size_t l_count(struct list * _list_); _Bool l_fits(struct list * _list_, size_t size); size_t l_capacity(struct list * _list_); int l_flag(struct list * _list_); _Bool l_resize(struct list * _list_, size_t capacity); struct list *l_copy_of(struct list * _list_); _Bool l_equals(struct list * _list1_, struct list * _list2_); struct list_iter { struct list *target; size_t cursor; _Bool start; _Bool end; }; struct list_iter l_iter_start(struct list * target); struct list_iter l_iter_end(struct list * target); _Bool l_iter_at_start(struct list_iter * iter); _Bool l_iter_at_end(struct list_iter * iter); _Bool l_iter_to_start(struct list_iter * iter); _Bool l_iter_to_end(struct list_iter * iter); _Bool l_iter_next(struct list_iter * iter); _Bool l_iter_prev(struct list_iter * iter); _Bool l_iter_advance(struct list_iter * iter, size_t steps); _Bool l_iter_rewind(struct list_iter * iter, size_t steps); _Bool l_iter_go_to(struct list_iter * iter, size_t index); size_t l_iter_value(struct list_iter * iter); size_t *l_iter_rvalue(struct list_iter * iter); size_t l_iter_index(struct list_iter * iter); _Bool l_seq_push_front(struct list * _list_, size_t * values, size_t size); _Bool l_seq_push_at(struct list * _list_, size_t * values, size_t size, size_t index); _Bool l_seq_push_back(struct list * _list_, size_t * values, size_t size); _Bool l_seq_pop_at(struct list * _list_, size_t from, size_t to); struct list *l_seq_sublist(struct list * _list_, size_t from, size_t to); _Bool l_to_string(struct list * _list_, FILE * fptr); _Bool l_print(struct list * _list_, FILE * fptr, const char *start, const char *separator, const char *end); - +#include "macro_collections.h" - #endif /* CMC_CMC_LIST_TEST_H */ - \ No newline at end of file +struct list +{ + size_t *buffer; + size_t capacity; + size_t count; + int flag; + struct list_fval *f_val; + struct cmc_alloc_node *alloc; + struct cmc_callbacks *callbacks; +}; +struct list_fval +{ + int (*cmp)(size_t, size_t); + size_t (*cpy)(size_t); + _Bool (*str)(FILE *, size_t); + void (*free)(size_t); + size_t (*hash)(size_t); + int (*pri)(size_t, size_t); +}; +struct list *l_new(size_t capacity, struct list_fval *f_val); +struct list *l_new_custom(size_t capacity, struct list_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks); +void l_clear(struct list *_list_); +void l_free(struct list *_list_); +void l_customize(struct list *_list_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks); +_Bool l_push_front(struct list *_list_, size_t value); +_Bool l_push_at(struct list *_list_, size_t value, size_t index); +_Bool l_push_back(struct list *_list_, size_t value); +_Bool l_pop_front(struct list *_list_); +_Bool l_pop_at(struct list *_list_, size_t index); +_Bool l_pop_back(struct list *_list_); +size_t l_front(struct list *_list_); +size_t l_get(struct list *_list_, size_t index); +size_t *l_get_ref(struct list *_list_, size_t index); +size_t l_back(struct list *_list_); +size_t l_index_of(struct list *_list_, size_t value, _Bool from_start); +_Bool l_contains(struct list *_list_, size_t value); +_Bool l_empty(struct list *_list_); +_Bool l_full(struct list *_list_); +size_t l_count(struct list *_list_); +_Bool l_fits(struct list *_list_, size_t size); +size_t l_capacity(struct list *_list_); +int l_flag(struct list *_list_); +_Bool l_resize(struct list *_list_, size_t capacity); +struct list *l_copy_of(struct list *_list_); +_Bool l_equals(struct list *_list1_, struct list *_list2_); +struct list_iter +{ + struct list *target; + size_t cursor; + _Bool start; + _Bool end; +}; +struct list_iter l_iter_start(struct list *target); +struct list_iter l_iter_end(struct list *target); +_Bool l_iter_at_start(struct list_iter *iter); +_Bool l_iter_at_end(struct list_iter *iter); +_Bool l_iter_to_start(struct list_iter *iter); +_Bool l_iter_to_end(struct list_iter *iter); +_Bool l_iter_next(struct list_iter *iter); +_Bool l_iter_prev(struct list_iter *iter); +_Bool l_iter_advance(struct list_iter *iter, size_t steps); +_Bool l_iter_rewind(struct list_iter *iter, size_t steps); +_Bool l_iter_go_to(struct list_iter *iter, size_t index); +size_t l_iter_value(struct list_iter *iter); +size_t *l_iter_rvalue(struct list_iter *iter); +size_t l_iter_index(struct list_iter *iter); +_Bool l_seq_push_front(struct list *_list_, size_t *values, size_t size); +_Bool l_seq_push_at(struct list *_list_, size_t *values, size_t size, size_t index); +_Bool l_seq_push_back(struct list *_list_, size_t *values, size_t size); +_Bool l_seq_pop_at(struct list *_list_, size_t from, size_t to); +struct list *l_seq_sublist(struct list *_list_, size_t from, size_t to); +_Bool l_to_string(struct list *_list_, FILE *fptr); +_Bool l_print(struct list *_list_, FILE *fptr, const char *start, const char *separator, const char *end); + +#endif /* CMC_CMC_LIST_TEST_H */ diff --git a/tests/include/tst_cmc_queue.h b/tests/include/tst_cmc_queue.h index 6cdcdc0..1fcd7b1 100644 --- a/tests/include/tst_cmc_queue.h +++ b/tests/include/tst_cmc_queue.h @@ -1,11 +1,71 @@ - #ifndef CMC_CMC_QUEUE_TEST_H - #define CMC_CMC_QUEUE_TEST_H +#ifndef CMC_CMC_QUEUE_TEST_H +#define CMC_CMC_QUEUE_TEST_H - #include "macro_collections.h" - - struct queue { size_t *buffer; size_t capacity; size_t count; size_t front; size_t back; int flag; struct queue_fval * f_val; struct cmc_alloc_node *alloc; struct cmc_callbacks *callbacks; }; struct queue_fval { int (*cmp)(size_t, size_t); size_t (*cpy)(size_t); _Bool (*str)(FILE *, size_t); void (*free)(size_t); size_t (*hash)(size_t); int (*pri)(size_t, size_t); }; struct queue *q_new(size_t capacity, struct queue_fval * f_val); struct queue *q_new_custom(size_t capacity, struct queue_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); void q_clear(struct queue * _queue_); void q_free(struct queue * _queue_); void q_customize(struct queue * _queue_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); _Bool q_enqueue(struct queue * _queue_, size_t value); _Bool q_dequeue(struct queue * _queue_); size_t q_peek(struct queue * _queue_); _Bool q_contains(struct queue * _queue_, size_t value); _Bool q_empty(struct queue * _queue_); _Bool q_full(struct queue * _queue_); size_t q_count(struct queue * _queue_); size_t q_capacity(struct queue * _queue_); int q_flag(struct queue * _queue_); _Bool q_resize(struct queue * _queue_, size_t capacity); struct queue *q_copy_of(struct queue * _queue_); _Bool q_equals(struct queue * _queue1_, struct queue * _queue2_); struct queue_iter { struct queue *target; size_t cursor; size_t index; _Bool start; _Bool end; }; struct queue_iter q_iter_start(struct queue * target); struct queue_iter q_iter_end(struct queue * target); _Bool q_iter_at_start(struct queue_iter * iter); _Bool q_iter_at_end(struct queue_iter * iter); _Bool q_iter_to_start(struct queue_iter * iter); _Bool q_iter_to_end(struct queue_iter * iter); _Bool q_iter_next(struct queue_iter * iter); _Bool q_iter_prev(struct queue_iter * iter); _Bool q_iter_advance(struct queue_iter * iter, size_t steps); _Bool q_iter_rewind(struct queue_iter * iter, size_t steps); _Bool q_iter_go_to(struct queue_iter * iter, size_t index); size_t q_iter_value(struct queue_iter * iter); size_t *q_iter_rvalue(struct queue_iter * iter); size_t q_iter_index(struct queue_iter * iter); _Bool q_to_string(struct queue * _queue_, FILE * fptr); _Bool q_print(struct queue * _queue_, FILE * fptr, const char *start, const char *separator, const char *end); - +#include "macro_collections.h" - #endif /* CMC_CMC_QUEUE_TEST_H */ - \ No newline at end of file +struct queue +{ + size_t *buffer; + size_t capacity; + size_t count; + size_t front; + size_t back; + int flag; + struct queue_fval *f_val; + struct cmc_alloc_node *alloc; + struct cmc_callbacks *callbacks; +}; +struct queue_fval +{ + int (*cmp)(size_t, size_t); + size_t (*cpy)(size_t); + _Bool (*str)(FILE *, size_t); + void (*free)(size_t); + size_t (*hash)(size_t); + int (*pri)(size_t, size_t); +}; +struct queue *q_new(size_t capacity, struct queue_fval *f_val); +struct queue *q_new_custom(size_t capacity, struct queue_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks); +void q_clear(struct queue *_queue_); +void q_free(struct queue *_queue_); +void q_customize(struct queue *_queue_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks); +_Bool q_enqueue(struct queue *_queue_, size_t value); +_Bool q_dequeue(struct queue *_queue_); +size_t q_peek(struct queue *_queue_); +_Bool q_contains(struct queue *_queue_, size_t value); +_Bool q_empty(struct queue *_queue_); +_Bool q_full(struct queue *_queue_); +size_t q_count(struct queue *_queue_); +size_t q_capacity(struct queue *_queue_); +int q_flag(struct queue *_queue_); +_Bool q_resize(struct queue *_queue_, size_t capacity); +struct queue *q_copy_of(struct queue *_queue_); +_Bool q_equals(struct queue *_queue1_, struct queue *_queue2_); +struct queue_iter +{ + struct queue *target; + size_t cursor; + size_t index; + _Bool start; + _Bool end; +}; +struct queue_iter q_iter_start(struct queue *target); +struct queue_iter q_iter_end(struct queue *target); +_Bool q_iter_at_start(struct queue_iter *iter); +_Bool q_iter_at_end(struct queue_iter *iter); +_Bool q_iter_to_start(struct queue_iter *iter); +_Bool q_iter_to_end(struct queue_iter *iter); +_Bool q_iter_next(struct queue_iter *iter); +_Bool q_iter_prev(struct queue_iter *iter); +_Bool q_iter_advance(struct queue_iter *iter, size_t steps); +_Bool q_iter_rewind(struct queue_iter *iter, size_t steps); +_Bool q_iter_go_to(struct queue_iter *iter, size_t index); +size_t q_iter_value(struct queue_iter *iter); +size_t *q_iter_rvalue(struct queue_iter *iter); +size_t q_iter_index(struct queue_iter *iter); +_Bool q_to_string(struct queue *_queue_, FILE *fptr); +_Bool q_print(struct queue *_queue_, FILE *fptr, const char *start, const char *separator, const char *end); + +#endif /* CMC_CMC_QUEUE_TEST_H */ diff --git a/tests/include/tst_cmc_sortedlist.h b/tests/include/tst_cmc_sortedlist.h index 2b4e0bf..a34b155 100644 --- a/tests/include/tst_cmc_sortedlist.h +++ b/tests/include/tst_cmc_sortedlist.h @@ -1,11 +1,72 @@ - #ifndef CMC_CMC_SORTEDLIST_TEST_H - #define CMC_CMC_SORTEDLIST_TEST_H +#ifndef CMC_CMC_SORTEDLIST_TEST_H +#define CMC_CMC_SORTEDLIST_TEST_H - #include "macro_collections.h" - - struct sortedlist { size_t *buffer; size_t capacity; size_t count; _Bool is_sorted; int flag; struct sortedlist_fval * f_val; struct cmc_alloc_node *alloc; struct cmc_callbacks *callbacks; }; struct sortedlist_fval { int (*cmp)(size_t, size_t); size_t (*cpy)(size_t); _Bool (*str)(FILE *, size_t); void (*free)(size_t); size_t (*hash)(size_t); int (*pri)(size_t, size_t); }; struct sortedlist *sl_new(size_t capacity, struct sortedlist_fval * f_val); struct sortedlist *sl_new_custom(size_t capacity, struct sortedlist_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); void sl_clear(struct sortedlist * _list_); void sl_free(struct sortedlist * _list_); void sl_customize(struct sortedlist * _list_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); _Bool sl_insert(struct sortedlist * _list_, size_t value); _Bool sl_remove(struct sortedlist * _list_, size_t index); size_t sl_max(struct sortedlist * _list_); size_t sl_min(struct sortedlist * _list_); size_t sl_get(struct sortedlist * _list_, size_t index); size_t sl_index_of(struct sortedlist * _list_, size_t value, _Bool from_start); _Bool sl_contains(struct sortedlist * _list_, size_t value); _Bool sl_empty(struct sortedlist * _list_); _Bool sl_full(struct sortedlist * _list_); size_t sl_count(struct sortedlist * _list_); size_t sl_capacity(struct sortedlist * _list_); int sl_flag(struct sortedlist * _list_); _Bool sl_resize(struct sortedlist * _list_, size_t capacity); void sl_sort(struct sortedlist * _list_); struct sortedlist *sl_copy_of(struct sortedlist * _list_); _Bool sl_equals(struct sortedlist * _list1_, struct sortedlist * _list2_); struct sortedlist_iter { struct sortedlist *target; size_t cursor; _Bool start; _Bool end; }; struct sortedlist_iter sl_iter_start(struct sortedlist * target); struct sortedlist_iter sl_iter_end(struct sortedlist * target); _Bool sl_iter_at_start(struct sortedlist_iter * iter); _Bool sl_iter_at_end(struct sortedlist_iter * iter); _Bool sl_iter_to_start(struct sortedlist_iter * iter); _Bool sl_iter_to_end(struct sortedlist_iter * iter); _Bool sl_iter_next(struct sortedlist_iter * iter); _Bool sl_iter_prev(struct sortedlist_iter * iter); _Bool sl_iter_advance(struct sortedlist_iter * iter, size_t steps); _Bool sl_iter_rewind(struct sortedlist_iter * iter, size_t steps); _Bool sl_iter_go_to(struct sortedlist_iter * iter, size_t index); size_t sl_iter_value(struct sortedlist_iter * iter); size_t sl_iter_index(struct sortedlist_iter * iter); _Bool sl_to_string(struct sortedlist * _list_, FILE * fptr); _Bool sl_print(struct sortedlist * _list_, FILE * fptr, const char *start, const char *separator, const char *end); - +#include "macro_collections.h" - #endif /* CMC_CMC_SORTEDLIST_TEST_H */ - \ No newline at end of file +struct sortedlist +{ + size_t *buffer; + size_t capacity; + size_t count; + _Bool is_sorted; + int flag; + struct sortedlist_fval *f_val; + struct cmc_alloc_node *alloc; + struct cmc_callbacks *callbacks; +}; +struct sortedlist_fval +{ + int (*cmp)(size_t, size_t); + size_t (*cpy)(size_t); + _Bool (*str)(FILE *, size_t); + void (*free)(size_t); + size_t (*hash)(size_t); + int (*pri)(size_t, size_t); +}; +struct sortedlist *sl_new(size_t capacity, struct sortedlist_fval *f_val); +struct sortedlist *sl_new_custom(size_t capacity, struct sortedlist_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks); +void sl_clear(struct sortedlist *_list_); +void sl_free(struct sortedlist *_list_); +void sl_customize(struct sortedlist *_list_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks); +_Bool sl_insert(struct sortedlist *_list_, size_t value); +_Bool sl_remove(struct sortedlist *_list_, size_t index); +size_t sl_max(struct sortedlist *_list_); +size_t sl_min(struct sortedlist *_list_); +size_t sl_get(struct sortedlist *_list_, size_t index); +size_t sl_index_of(struct sortedlist *_list_, size_t value, _Bool from_start); +_Bool sl_contains(struct sortedlist *_list_, size_t value); +_Bool sl_empty(struct sortedlist *_list_); +_Bool sl_full(struct sortedlist *_list_); +size_t sl_count(struct sortedlist *_list_); +size_t sl_capacity(struct sortedlist *_list_); +int sl_flag(struct sortedlist *_list_); +_Bool sl_resize(struct sortedlist *_list_, size_t capacity); +void sl_sort(struct sortedlist *_list_); +struct sortedlist *sl_copy_of(struct sortedlist *_list_); +_Bool sl_equals(struct sortedlist *_list1_, struct sortedlist *_list2_); +struct sortedlist_iter +{ + struct sortedlist *target; + size_t cursor; + _Bool start; + _Bool end; +}; +struct sortedlist_iter sl_iter_start(struct sortedlist *target); +struct sortedlist_iter sl_iter_end(struct sortedlist *target); +_Bool sl_iter_at_start(struct sortedlist_iter *iter); +_Bool sl_iter_at_end(struct sortedlist_iter *iter); +_Bool sl_iter_to_start(struct sortedlist_iter *iter); +_Bool sl_iter_to_end(struct sortedlist_iter *iter); +_Bool sl_iter_next(struct sortedlist_iter *iter); +_Bool sl_iter_prev(struct sortedlist_iter *iter); +_Bool sl_iter_advance(struct sortedlist_iter *iter, size_t steps); +_Bool sl_iter_rewind(struct sortedlist_iter *iter, size_t steps); +_Bool sl_iter_go_to(struct sortedlist_iter *iter, size_t index); +size_t sl_iter_value(struct sortedlist_iter *iter); +size_t sl_iter_index(struct sortedlist_iter *iter); +_Bool sl_to_string(struct sortedlist *_list_, FILE *fptr); +_Bool sl_print(struct sortedlist *_list_, FILE *fptr, const char *start, const char *separator, const char *end); + +#endif /* CMC_CMC_SORTEDLIST_TEST_H */ diff --git a/tests/include/tst_cmc_stack.h b/tests/include/tst_cmc_stack.h index 0def578..6f510d0 100644 --- a/tests/include/tst_cmc_stack.h +++ b/tests/include/tst_cmc_stack.h @@ -1,11 +1,68 @@ - #ifndef CMC_CMC_STACK_TEST_H - #define CMC_CMC_STACK_TEST_H +#ifndef CMC_CMC_STACK_TEST_H +#define CMC_CMC_STACK_TEST_H - #include "macro_collections.h" - - struct stack { size_t *buffer; size_t capacity; size_t count; int flag; struct stack_fval * f_val; struct cmc_alloc_node *alloc; struct cmc_callbacks *callbacks; }; struct stack_fval { int (*cmp)(size_t, size_t); size_t (*cpy)(size_t); _Bool (*str)(FILE *, size_t); void (*free)(size_t); size_t (*hash)(size_t); int (*pri)(size_t, size_t); }; struct stack *s_new(size_t capacity, struct stack_fval * f_val); struct stack *s_new_custom(size_t capacity, struct stack_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); void s_clear(struct stack * _stack_); void s_free(struct stack * _stack_); void s_customize(struct stack * _stack_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); _Bool s_push(struct stack * _stack_, size_t value); _Bool s_pop(struct stack * _stack_); size_t s_top(struct stack * _stack_); _Bool s_contains(struct stack * _stack_, size_t value); _Bool s_empty(struct stack * _stack_); _Bool s_full(struct stack * _stack_); size_t s_count(struct stack * _stack_); size_t s_capacity(struct stack * _stack_); int s_flag(struct stack * _stack_); _Bool s_resize(struct stack * _stack_, size_t capacity); struct stack *s_copy_of(struct stack * _stack_); _Bool s_equals(struct stack * _stack1_, struct stack * _stack2_); struct stack_iter { struct stack *target; size_t cursor; _Bool start; _Bool end; }; struct stack_iter s_iter_start(struct stack * target); struct stack_iter s_iter_end(struct stack * target); _Bool s_iter_at_start(struct stack_iter * iter); _Bool s_iter_at_end(struct stack_iter * iter); _Bool s_iter_to_start(struct stack_iter * iter); _Bool s_iter_to_end(struct stack_iter * iter); _Bool s_iter_next(struct stack_iter * iter); _Bool s_iter_prev(struct stack_iter * iter); _Bool s_iter_advance(struct stack_iter * iter, size_t steps); _Bool s_iter_rewind(struct stack_iter * iter, size_t steps); _Bool s_iter_go_to(struct stack_iter * iter, size_t index); size_t s_iter_value(struct stack_iter * iter); size_t *s_iter_rvalue(struct stack_iter * iter); size_t s_iter_index(struct stack_iter * iter); _Bool s_to_string(struct stack * _stack_, FILE * fptr); _Bool s_print(struct stack * _stack_, FILE * fptr, const char *start, const char *separator, const char *end); - +#include "macro_collections.h" - #endif /* CMC_CMC_STACK_TEST_H */ - \ No newline at end of file +struct stack +{ + size_t *buffer; + size_t capacity; + size_t count; + int flag; + struct stack_fval *f_val; + struct cmc_alloc_node *alloc; + struct cmc_callbacks *callbacks; +}; +struct stack_fval +{ + int (*cmp)(size_t, size_t); + size_t (*cpy)(size_t); + _Bool (*str)(FILE *, size_t); + void (*free)(size_t); + size_t (*hash)(size_t); + int (*pri)(size_t, size_t); +}; +struct stack *s_new(size_t capacity, struct stack_fval *f_val); +struct stack *s_new_custom(size_t capacity, struct stack_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks); +void s_clear(struct stack *_stack_); +void s_free(struct stack *_stack_); +void s_customize(struct stack *_stack_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks); +_Bool s_push(struct stack *_stack_, size_t value); +_Bool s_pop(struct stack *_stack_); +size_t s_top(struct stack *_stack_); +_Bool s_contains(struct stack *_stack_, size_t value); +_Bool s_empty(struct stack *_stack_); +_Bool s_full(struct stack *_stack_); +size_t s_count(struct stack *_stack_); +size_t s_capacity(struct stack *_stack_); +int s_flag(struct stack *_stack_); +_Bool s_resize(struct stack *_stack_, size_t capacity); +struct stack *s_copy_of(struct stack *_stack_); +_Bool s_equals(struct stack *_stack1_, struct stack *_stack2_); +struct stack_iter +{ + struct stack *target; + size_t cursor; + _Bool start; + _Bool end; +}; +struct stack_iter s_iter_start(struct stack *target); +struct stack_iter s_iter_end(struct stack *target); +_Bool s_iter_at_start(struct stack_iter *iter); +_Bool s_iter_at_end(struct stack_iter *iter); +_Bool s_iter_to_start(struct stack_iter *iter); +_Bool s_iter_to_end(struct stack_iter *iter); +_Bool s_iter_next(struct stack_iter *iter); +_Bool s_iter_prev(struct stack_iter *iter); +_Bool s_iter_advance(struct stack_iter *iter, size_t steps); +_Bool s_iter_rewind(struct stack_iter *iter, size_t steps); +_Bool s_iter_go_to(struct stack_iter *iter, size_t index); +size_t s_iter_value(struct stack_iter *iter); +size_t *s_iter_rvalue(struct stack_iter *iter); +size_t s_iter_index(struct stack_iter *iter); +_Bool s_to_string(struct stack *_stack_, FILE *fptr); +_Bool s_print(struct stack *_stack_, FILE *fptr, const char *start, const char *separator, const char *end); + +#endif /* CMC_CMC_STACK_TEST_H */ diff --git a/tests/include/tst_cmc_treemap.h b/tests/include/tst_cmc_treemap.h index d13e622..005ad91 100644 --- a/tests/include/tst_cmc_treemap.h +++ b/tests/include/tst_cmc_treemap.h @@ -1,11 +1,92 @@ - #ifndef CMC_CMC_TREEMAP_TEST_H - #define CMC_CMC_TREEMAP_TEST_H +#ifndef CMC_CMC_TREEMAP_TEST_H +#define CMC_CMC_TREEMAP_TEST_H - #include "macro_collections.h" - - struct treemap { struct treemap_node * root; size_t count; int flag; struct treemap_fkey * f_key; struct treemap_fval * f_val; struct cmc_alloc_node *alloc; struct cmc_callbacks *callbacks; }; struct treemap_node { size_t key; size_t value; unsigned char height; struct treemap_node * right; struct treemap_node * left; struct treemap_node * parent; }; struct treemap_fkey { int (*cmp)(size_t, size_t); size_t (*cpy)(size_t); _Bool (*str)(FILE *, size_t); void (*free)(size_t); size_t (*hash)(size_t); int (*pri)(size_t, size_t); }; struct treemap_fval { int (*cmp)(size_t, size_t); size_t (*cpy)(size_t); _Bool (*str)(FILE *, size_t); void (*free)(size_t); size_t (*hash)(size_t); int (*pri)(size_t, size_t); }; struct treemap *tm_new(struct treemap_fkey * f_key, struct treemap_fval * f_val); struct treemap *tm_new_custom(struct treemap_fkey * f_key, struct treemap_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); void tm_clear(struct treemap * _map_); void tm_free(struct treemap * _map_); void tm_customize(struct treemap * _map_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); _Bool tm_insert(struct treemap * _map_, size_t key, size_t value); _Bool tm_update(struct treemap * _map_, size_t key, size_t new_value, size_t * old_value); _Bool tm_remove(struct treemap * _map_, size_t key, size_t * out_value); _Bool tm_max(struct treemap * _map_, size_t * key, size_t * value); _Bool tm_min(struct treemap * _map_, size_t * key, size_t * value); size_t tm_get(struct treemap * _map_, size_t key); size_t *tm_get_ref(struct treemap * _map_, size_t key); _Bool tm_contains(struct treemap * _map_, size_t key); _Bool tm_empty(struct treemap * _map_); size_t tm_count(struct treemap * _map_); int tm_flag(struct treemap * _map_); struct treemap *tm_copy_of(struct treemap * _map_); _Bool tm_equals(struct treemap * _map1_, struct treemap * _map2_); struct treemap_iter { struct treemap *target; struct treemap_node * cursor; struct treemap_node * first; struct treemap_node * last; size_t index; _Bool start; _Bool end; }; struct treemap_iter tm_iter_start(struct treemap * target); struct treemap_iter tm_iter_end(struct treemap * target); _Bool tm_iter_at_start(struct treemap_iter * iter); _Bool tm_iter_at_end(struct treemap_iter * iter); _Bool tm_iter_to_start(struct treemap_iter * iter); _Bool tm_iter_to_end(struct treemap_iter * iter); _Bool tm_iter_next(struct treemap_iter * iter); _Bool tm_iter_prev(struct treemap_iter * iter); _Bool tm_iter_advance(struct treemap_iter * iter, size_t steps); _Bool tm_iter_rewind(struct treemap_iter * iter, size_t steps); _Bool tm_iter_go_to(struct treemap_iter * iter, size_t index); size_t tm_iter_key(struct treemap_iter * iter); size_t tm_iter_value(struct treemap_iter * iter); size_t *tm_iter_rvalue(struct treemap_iter * iter); size_t tm_iter_index(struct treemap_iter * iter); _Bool tm_to_string(struct treemap * _map_, FILE * fptr); _Bool tm_print(struct treemap * _map_, FILE * fptr, const char *start, const char *separator, const char *end, const char *key_val_sep); - +#include "macro_collections.h" - #endif /* CMC_CMC_TREEMAP_TEST_H */ - \ No newline at end of file +struct treemap +{ + struct treemap_node *root; + size_t count; + int flag; + struct treemap_fkey *f_key; + struct treemap_fval *f_val; + struct cmc_alloc_node *alloc; + struct cmc_callbacks *callbacks; +}; +struct treemap_node +{ + size_t key; + size_t value; + unsigned char height; + struct treemap_node *right; + struct treemap_node *left; + struct treemap_node *parent; +}; +struct treemap_fkey +{ + int (*cmp)(size_t, size_t); + size_t (*cpy)(size_t); + _Bool (*str)(FILE *, size_t); + void (*free)(size_t); + size_t (*hash)(size_t); + int (*pri)(size_t, size_t); +}; +struct treemap_fval +{ + int (*cmp)(size_t, size_t); + size_t (*cpy)(size_t); + _Bool (*str)(FILE *, size_t); + void (*free)(size_t); + size_t (*hash)(size_t); + int (*pri)(size_t, size_t); +}; +struct treemap *tm_new(struct treemap_fkey *f_key, struct treemap_fval *f_val); +struct treemap *tm_new_custom(struct treemap_fkey *f_key, struct treemap_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks); +void tm_clear(struct treemap *_map_); +void tm_free(struct treemap *_map_); +void tm_customize(struct treemap *_map_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks); +_Bool tm_insert(struct treemap *_map_, size_t key, size_t value); +_Bool tm_update(struct treemap *_map_, size_t key, size_t new_value, size_t *old_value); +_Bool tm_remove(struct treemap *_map_, size_t key, size_t *out_value); +_Bool tm_max(struct treemap *_map_, size_t *key, size_t *value); +_Bool tm_min(struct treemap *_map_, size_t *key, size_t *value); +size_t tm_get(struct treemap *_map_, size_t key); +size_t *tm_get_ref(struct treemap *_map_, size_t key); +_Bool tm_contains(struct treemap *_map_, size_t key); +_Bool tm_empty(struct treemap *_map_); +size_t tm_count(struct treemap *_map_); +int tm_flag(struct treemap *_map_); +struct treemap *tm_copy_of(struct treemap *_map_); +_Bool tm_equals(struct treemap *_map1_, struct treemap *_map2_); +struct treemap_iter +{ + struct treemap *target; + struct treemap_node *cursor; + struct treemap_node *first; + struct treemap_node *last; + size_t index; + _Bool start; + _Bool end; +}; +struct treemap_iter tm_iter_start(struct treemap *target); +struct treemap_iter tm_iter_end(struct treemap *target); +_Bool tm_iter_at_start(struct treemap_iter *iter); +_Bool tm_iter_at_end(struct treemap_iter *iter); +_Bool tm_iter_to_start(struct treemap_iter *iter); +_Bool tm_iter_to_end(struct treemap_iter *iter); +_Bool tm_iter_next(struct treemap_iter *iter); +_Bool tm_iter_prev(struct treemap_iter *iter); +_Bool tm_iter_advance(struct treemap_iter *iter, size_t steps); +_Bool tm_iter_rewind(struct treemap_iter *iter, size_t steps); +_Bool tm_iter_go_to(struct treemap_iter *iter, size_t index); +size_t tm_iter_key(struct treemap_iter *iter); +size_t tm_iter_value(struct treemap_iter *iter); +size_t *tm_iter_rvalue(struct treemap_iter *iter); +size_t tm_iter_index(struct treemap_iter *iter); +_Bool tm_to_string(struct treemap *_map_, FILE *fptr); +_Bool tm_print(struct treemap *_map_, FILE *fptr, const char *start, const char *separator, const char *end, + const char *key_val_sep); + +#endif /* CMC_CMC_TREEMAP_TEST_H */ diff --git a/tests/include/tst_cmc_treeset.h b/tests/include/tst_cmc_treeset.h index 3623f97..9bca697 100644 --- a/tests/include/tst_cmc_treeset.h +++ b/tests/include/tst_cmc_treeset.h @@ -1,11 +1,84 @@ - #ifndef CMC_CMC_TREESET_TEST_H - #define CMC_CMC_TREESET_TEST_H +#ifndef CMC_CMC_TREESET_TEST_H +#define CMC_CMC_TREESET_TEST_H - #include "macro_collections.h" - - struct treeset { struct treeset_node * root; size_t count; int flag; struct treeset_fval * f_val; struct cmc_alloc_node *alloc; struct cmc_callbacks *callbacks; }; struct treeset_node { size_t value; unsigned char height; struct treeset_node * right; struct treeset_node * left; struct treeset_node * parent; }; struct treeset_fval { int (*cmp)(size_t, size_t); size_t (*cpy)(size_t); _Bool (*str)(FILE *, size_t); void (*free)(size_t); size_t (*hash)(size_t); int (*pri)(size_t, size_t); }; struct treeset *ts_new(struct treeset_fval * f_val); struct treeset *ts_new_custom(struct treeset_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); void ts_clear(struct treeset * _set_); void ts_free(struct treeset * _set_); void ts_customize(struct treeset * _set_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks); _Bool ts_insert(struct treeset * _set_, size_t value); _Bool ts_remove(struct treeset * _set_, size_t value); _Bool ts_max(struct treeset * _set_, size_t * value); _Bool ts_min(struct treeset * _set_, size_t * value); _Bool ts_contains(struct treeset * _set_, size_t value); _Bool ts_empty(struct treeset * _set_); size_t ts_count(struct treeset * _set_); int ts_flag(struct treeset * _set_); struct treeset *ts_copy_of(struct treeset * _set_); _Bool ts_equals(struct treeset * _set1_, struct treeset * _set2_); struct treeset_iter { struct treeset *target; struct treeset_node * cursor; struct treeset_node * first; struct treeset_node * last; size_t index; _Bool start; _Bool end; }; struct treeset_iter ts_iter_start(struct treeset * target); struct treeset_iter ts_iter_end(struct treeset * target); _Bool ts_iter_at_start(struct treeset_iter * iter); _Bool ts_iter_at_end(struct treeset_iter * iter); _Bool ts_iter_to_start(struct treeset_iter * iter); _Bool ts_iter_to_end(struct treeset_iter * iter); _Bool ts_iter_next(struct treeset_iter * iter); _Bool ts_iter_prev(struct treeset_iter * iter); _Bool ts_iter_advance(struct treeset_iter * iter, size_t steps); _Bool ts_iter_rewind(struct treeset_iter * iter, size_t steps); _Bool ts_iter_go_to(struct treeset_iter * iter, size_t index); size_t ts_iter_value(struct treeset_iter * iter); size_t ts_iter_index(struct treeset_iter * iter); struct treeset *ts_union(struct treeset * _set1_, struct treeset * _set2_); struct treeset *ts_intersection(struct treeset * _set1_, struct treeset * _set2_); struct treeset *ts_difference(struct treeset * _set1_, struct treeset * _set2_); struct treeset *ts_symmetric_difference(struct treeset * _set1_, struct treeset * _set2_); _Bool ts_is_subset(struct treeset * _set1_, struct treeset * _set2_); _Bool ts_is_superset(struct treeset * _set1_, struct treeset * _set2_); _Bool ts_is_proper_subset(struct treeset * _set1_, struct treeset * _set2_); _Bool ts_is_proper_superset(struct treeset * _set1_, struct treeset * _set2_); _Bool ts_is_disjointset(struct treeset * _set1_, struct treeset * _set2_); _Bool ts_to_string(struct treeset * _set_, FILE * fptr); _Bool ts_print(struct treeset * _set_, FILE * fptr, const char *start, const char *separator, const char *end); - +#include "macro_collections.h" - #endif /* CMC_CMC_TREESET_TEST_H */ - \ No newline at end of file +struct treeset +{ + struct treeset_node *root; + size_t count; + int flag; + struct treeset_fval *f_val; + struct cmc_alloc_node *alloc; + struct cmc_callbacks *callbacks; +}; +struct treeset_node +{ + size_t value; + unsigned char height; + struct treeset_node *right; + struct treeset_node *left; + struct treeset_node *parent; +}; +struct treeset_fval +{ + int (*cmp)(size_t, size_t); + size_t (*cpy)(size_t); + _Bool (*str)(FILE *, size_t); + void (*free)(size_t); + size_t (*hash)(size_t); + int (*pri)(size_t, size_t); +}; +struct treeset *ts_new(struct treeset_fval *f_val); +struct treeset *ts_new_custom(struct treeset_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks); +void ts_clear(struct treeset *_set_); +void ts_free(struct treeset *_set_); +void ts_customize(struct treeset *_set_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks); +_Bool ts_insert(struct treeset *_set_, size_t value); +_Bool ts_remove(struct treeset *_set_, size_t value); +_Bool ts_max(struct treeset *_set_, size_t *value); +_Bool ts_min(struct treeset *_set_, size_t *value); +_Bool ts_contains(struct treeset *_set_, size_t value); +_Bool ts_empty(struct treeset *_set_); +size_t ts_count(struct treeset *_set_); +int ts_flag(struct treeset *_set_); +struct treeset *ts_copy_of(struct treeset *_set_); +_Bool ts_equals(struct treeset *_set1_, struct treeset *_set2_); +struct treeset_iter +{ + struct treeset *target; + struct treeset_node *cursor; + struct treeset_node *first; + struct treeset_node *last; + size_t index; + _Bool start; + _Bool end; +}; +struct treeset_iter ts_iter_start(struct treeset *target); +struct treeset_iter ts_iter_end(struct treeset *target); +_Bool ts_iter_at_start(struct treeset_iter *iter); +_Bool ts_iter_at_end(struct treeset_iter *iter); +_Bool ts_iter_to_start(struct treeset_iter *iter); +_Bool ts_iter_to_end(struct treeset_iter *iter); +_Bool ts_iter_next(struct treeset_iter *iter); +_Bool ts_iter_prev(struct treeset_iter *iter); +_Bool ts_iter_advance(struct treeset_iter *iter, size_t steps); +_Bool ts_iter_rewind(struct treeset_iter *iter, size_t steps); +_Bool ts_iter_go_to(struct treeset_iter *iter, size_t index); +size_t ts_iter_value(struct treeset_iter *iter); +size_t ts_iter_index(struct treeset_iter *iter); +struct treeset *ts_union(struct treeset *_set1_, struct treeset *_set2_); +struct treeset *ts_intersection(struct treeset *_set1_, struct treeset *_set2_); +struct treeset *ts_difference(struct treeset *_set1_, struct treeset *_set2_); +struct treeset *ts_symmetric_difference(struct treeset *_set1_, struct treeset *_set2_); +_Bool ts_is_subset(struct treeset *_set1_, struct treeset *_set2_); +_Bool ts_is_superset(struct treeset *_set1_, struct treeset *_set2_); +_Bool ts_is_proper_subset(struct treeset *_set1_, struct treeset *_set2_); +_Bool ts_is_proper_superset(struct treeset *_set1_, struct treeset *_set2_); +_Bool ts_is_disjointset(struct treeset *_set1_, struct treeset *_set2_); +_Bool ts_to_string(struct treeset *_set_, FILE *fptr); +_Bool ts_print(struct treeset *_set_, FILE *fptr, const char *start, const char *separator, const char *end); + +#endif /* CMC_CMC_TREESET_TEST_H */ diff --git a/tests/src/tst_cmc_bitset.c b/tests/src/tst_cmc_bitset.c index b995c83..1ae7c75 100644 --- a/tests/src/tst_cmc_bitset.c +++ b/tests/src/tst_cmc_bitset.c @@ -1,7 +1,294 @@ - #include "tst_cmc_bitset.h" +#include "tst_cmc_bitset.h" - - _Bool bs_impl_resize(struct bitset * _bitset_, size_t n_bits, _Bool do_resize); struct bitset *bs_new(size_t n_bits) { return bs_new_custom(n_bits, ((void *)0), ((void *)0)); } struct bitset *bs_new_custom(size_t n_bits, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (n_bits < 1) return ((void *)0); if (!alloc) alloc = &cmc_alloc_node_default; size_t capacity = cmc_bidx_to_widx(n_bits - 1) + 1; struct bitset *_bitset_ = alloc->malloc(sizeof(struct bitset)); if (!_bitset_) return ((void *)0); _bitset_->buffer = alloc->calloc(capacity, sizeof(cmc_bitset_word)); if (!_bitset_->buffer) { alloc->free(_bitset_); return ((void *)0); } _bitset_->capacity = capacity; _bitset_->flag = CMC_FLAG_OK; _bitset_->alloc = alloc; (_bitset_)->callbacks = callbacks; return _bitset_; } struct bitset bs_init(size_t n_bits) { return bs_init_custom(n_bits, ((void *)0), ((void *)0)); } struct bitset bs_init_custom(size_t n_bits, struct cmc_alloc_node * alloc, struct cmc_callbacks * __attribute__((__unused__))(callbacks)) { ; struct bitset _bitset_ = { 0 }; if (n_bits < 1) return _bitset_; if (!alloc) alloc = &cmc_alloc_node_default; size_t capacity = cmc_bidx_to_widx(n_bits - 1) + 1; _bitset_.buffer = alloc->calloc(capacity, sizeof(cmc_bitset_word)); if (!_bitset_.buffer) return _bitset_; _bitset_.capacity = capacity; _bitset_.flag = CMC_FLAG_OK; _bitset_.alloc = alloc; (&_bitset_)->callbacks = callbacks; return _bitset_; } void bs_free(struct bitset * _bitset_) { free(_bitset_->buffer); free(_bitset_); } void bs_release(struct bitset _bitset_) { free(_bitset_.buffer); } void bs_customize(struct bitset * _bitset_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (!alloc) _bitset_->alloc = &cmc_alloc_node_default; else _bitset_->alloc = alloc; (_bitset_)->callbacks = callbacks; _bitset_->flag = CMC_FLAG_OK; } _Bool bs_set(struct bitset * _bitset_, size_t bit_index) { if (!bs_impl_resize(_bitset_, bit_index + 1, 0)) return 0; const cmc_bitset_word bits = sizeof(cmc_bitset_word) * 8; size_t i = cmc_bidx_to_widx(bit_index); _bitset_->buffer[i] |= ((cmc_bitset_word)1) << (bit_index % bits); _bitset_->flag = CMC_FLAG_OK; if ((_bitset_)->callbacks && (_bitset_)->callbacks->create) (_bitset_)->callbacks->create();; return 1; } _Bool bs_set_range(struct bitset * _bitset_, size_t from, size_t to) { if (to < from) { _bitset_->flag = CMC_FLAG_INVALID; return 0; } if (!bs_impl_resize(_bitset_, to + 1, 0)) return 0; size_t start_index = cmc_bidx_to_widx(from); size_t end_index = cmc_bidx_to_widx(to); const cmc_bitset_word bits = sizeof(cmc_bitset_word) * 8; const cmc_bitset_word ones = ~((cmc_bitset_word)0); cmc_bitset_word shift_start = from % bits; cmc_bitset_word shift_end = (cmc_bitset_word)(-(to + 1)) % bits; cmc_bitset_word start_mask = ones << shift_start; cmc_bitset_word end_mask = ones >> shift_end; if (start_index == end_index) { _bitset_->buffer[end_index] |= (start_mask & end_mask); } else { _bitset_->buffer[start_index] |= start_mask; for (size_t i = start_index + 1; i < end_index; i++) _bitset_->buffer[i] |= ~((cmc_bitset_word)0); _bitset_->buffer[end_index] |= end_mask; } _bitset_->flag = CMC_FLAG_OK; if ((_bitset_)->callbacks && (_bitset_)->callbacks->create) (_bitset_)->callbacks->create();; return 1; } _Bool bs_clear(struct bitset * _bitset_, size_t bit_index) { if (!bs_impl_resize(_bitset_, bit_index + 1, 0)) return 0; const cmc_bitset_word bits = sizeof(cmc_bitset_word) * 8; size_t i = cmc_bidx_to_widx(bit_index); _bitset_->buffer[i] &= ~(((cmc_bitset_word)1) << (bit_index % bits)); _bitset_->flag = CMC_FLAG_OK; if ((_bitset_)->callbacks && (_bitset_)->callbacks->delete) (_bitset_)->callbacks->delete();; return 1; } _Bool bs_clear_range(struct bitset * _bitset_, size_t from, size_t to) { if (to < from) { _bitset_->flag = CMC_FLAG_INVALID; return 0; } if (!bs_impl_resize(_bitset_, to + 1, 0)) return 0; size_t start_index = cmc_bidx_to_widx(from); size_t end_index = cmc_bidx_to_widx(to); const cmc_bitset_word bits = sizeof(cmc_bitset_word) * 8; const cmc_bitset_word ones = ~((cmc_bitset_word)0); cmc_bitset_word shift_start = from % bits; cmc_bitset_word shift_end = (cmc_bitset_word)(-(to + 1)) % bits; cmc_bitset_word start_mask = ones << shift_start; cmc_bitset_word end_mask = ones >> shift_end; if (start_index == end_index) { _bitset_->buffer[end_index] &= ~(start_mask & end_mask); } else { _bitset_->buffer[start_index] &= ~start_mask; for (size_t i = start_index + 1; i < end_index; i++) _bitset_->buffer[i] = 0; _bitset_->buffer[end_index] &= ~end_mask; } _bitset_->flag = CMC_FLAG_OK; if ((_bitset_)->callbacks && (_bitset_)->callbacks->delete) (_bitset_)->callbacks->delete();; return 1; } _Bool bs_flip(struct bitset * _bitset_, size_t bit_index) { if (!bs_impl_resize(_bitset_, bit_index + 1, 0)) return 0; const cmc_bitset_word bits = sizeof(cmc_bitset_word) * 8; size_t i = cmc_bidx_to_widx(bit_index); _bitset_->buffer[i] ^= ((cmc_bitset_word)1) << (bit_index % bits); _bitset_->flag = CMC_FLAG_OK; if ((_bitset_)->callbacks && (_bitset_)->callbacks->update) (_bitset_)->callbacks->update();; return 1; } _Bool bs_flip_range(struct bitset * _bitset_, size_t from, size_t to) { if (to < from) { _bitset_->flag = CMC_FLAG_INVALID; return 0; } if (!bs_impl_resize(_bitset_, to + 1, 0)) return 0; size_t start_index = cmc_bidx_to_widx(from); size_t end_index = cmc_bidx_to_widx(to); const cmc_bitset_word bits = sizeof(cmc_bitset_word) * 8; const cmc_bitset_word ones = ~((cmc_bitset_word)0); cmc_bitset_word shift_start = from % bits; cmc_bitset_word shift_end = (cmc_bitset_word)(-(to + 1)) % bits; cmc_bitset_word start_mask = ones << shift_start; cmc_bitset_word end_mask = ones >> shift_end; if (start_index == end_index) { _bitset_->buffer[end_index] ^= (start_mask & end_mask); } else { _bitset_->buffer[start_index] ^= start_mask; for (size_t i = start_index + 1; i < end_index; i++) _bitset_->buffer[i] ^= ones; _bitset_->buffer[end_index] ^= end_mask; } _bitset_->flag = CMC_FLAG_OK; if ((_bitset_)->callbacks && (_bitset_)->callbacks->update) (_bitset_)->callbacks->update();; return 1; } _Bool bs_put(struct bitset * _bitset_, size_t bit_index, _Bool state) { if (state) return bs_set(_bitset_, bit_index); else return bs_clear(_bitset_, bit_index); } _Bool bs_put_range(struct bitset * _bitset_, size_t from, size_t to, _Bool state) { if (state) return bs_set_range(_bitset_, from, to); else return bs_clear_range(_bitset_, from, to); } _Bool bs_set_all(struct bitset * _bitset_) { for (size_t i = 0; i < _bitset_->capacity; i++) _bitset_->buffer[i] = ~((cmc_bitset_word)0); _bitset_->flag = CMC_FLAG_OK; if ((_bitset_)->callbacks && (_bitset_)->callbacks->create) (_bitset_)->callbacks->create();; return 1; } _Bool bs_clear_all(struct bitset * _bitset_) { for (size_t i = 0; i < _bitset_->capacity; i++) _bitset_->buffer[i] = 0; _bitset_->flag = CMC_FLAG_OK; if ((_bitset_)->callbacks && (_bitset_)->callbacks->delete) (_bitset_)->callbacks->delete();; return 1; } _Bool bs_flip_all(struct bitset * _bitset_) { for (size_t i = 0; i < _bitset_->capacity; i++) _bitset_->buffer[i] ^= ~((cmc_bitset_word)0); _bitset_->flag = CMC_FLAG_OK; if ((_bitset_)->callbacks && (_bitset_)->callbacks->create) (_bitset_)->callbacks->create();; return 1; } _Bool bs_get(struct bitset * _bitset_, size_t bit_index) { const cmc_bitset_word bits = sizeof(cmc_bitset_word) * 8; cmc_bitset_word w = _bitset_->buffer[cmc_bidx_to_widx(bit_index)]; return w & ((cmc_bitset_word)1 << (bit_index % bits)); } _Bool bs_resize(struct bitset * _bitset_, size_t n_bits) { return bs_impl_resize(_bitset_, n_bits, 1); } _Bool bs_impl_resize(struct bitset * _bitset_, size_t n_bits, _Bool do_resize) { if (n_bits == 0) { _bitset_->flag = CMC_FLAG_INVALID; return 0; } size_t words = cmc_bidx_to_widx(n_bits - 1) + 1; if (!do_resize && words <= _bitset_->capacity) return 1; cmc_bitset_word *new_buffer = realloc(_bitset_->buffer, words * sizeof(cmc_bitset_word)); if (!new_buffer) { _bitset_->flag = CMC_FLAG_ALLOC; return 0; } _bitset_->buffer = new_buffer; if (_bitset_->capacity < words) memset(_bitset_->buffer + _bitset_->capacity, 0, (words - _bitset_->capacity) * sizeof(cmc_bitset_word)); _bitset_->capacity = words; if ((_bitset_)->callbacks && (_bitset_)->callbacks->resize) (_bitset_)->callbacks->resize();; _bitset_->flag = CMC_FLAG_OK; return 1; } - - \ No newline at end of file +_Bool bs_impl_resize(struct bitset *_bitset_, size_t n_bits, _Bool do_resize); +struct bitset *bs_new(size_t n_bits) +{ + return bs_new_custom(n_bits, ((void *)0), ((void *)0)); +} +struct bitset *bs_new_custom(size_t n_bits, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks) +{ + ; + if (n_bits < 1) + return ((void *)0); + if (!alloc) + alloc = &cmc_alloc_node_default; + size_t capacity = cmc_bidx_to_widx(n_bits - 1) + 1; + struct bitset *_bitset_ = alloc->malloc(sizeof(struct bitset)); + if (!_bitset_) + return ((void *)0); + _bitset_->buffer = alloc->calloc(capacity, sizeof(cmc_bitset_word)); + if (!_bitset_->buffer) + { + alloc->free(_bitset_); + return ((void *)0); + } + _bitset_->capacity = capacity; + _bitset_->flag = CMC_FLAG_OK; + _bitset_->alloc = alloc; + (_bitset_)->callbacks = callbacks; + return _bitset_; +} +struct bitset bs_init(size_t n_bits) +{ + return bs_init_custom(n_bits, ((void *)0), ((void *)0)); +} +struct bitset bs_init_custom(size_t n_bits, struct cmc_alloc_node *alloc, + struct cmc_callbacks *__attribute__((__unused__)) (callbacks)) +{ + ; + struct bitset _bitset_ = { 0 }; + if (n_bits < 1) + return _bitset_; + if (!alloc) + alloc = &cmc_alloc_node_default; + size_t capacity = cmc_bidx_to_widx(n_bits - 1) + 1; + _bitset_.buffer = alloc->calloc(capacity, sizeof(cmc_bitset_word)); + if (!_bitset_.buffer) + return _bitset_; + _bitset_.capacity = capacity; + _bitset_.flag = CMC_FLAG_OK; + _bitset_.alloc = alloc; + (&_bitset_)->callbacks = callbacks; + return _bitset_; +} +void bs_free(struct bitset *_bitset_) +{ + free(_bitset_->buffer); + free(_bitset_); +} +void bs_release(struct bitset _bitset_) +{ + free(_bitset_.buffer); +} +void bs_customize(struct bitset *_bitset_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks) +{ + ; + if (!alloc) + _bitset_->alloc = &cmc_alloc_node_default; + else + _bitset_->alloc = alloc; + (_bitset_)->callbacks = callbacks; + _bitset_->flag = CMC_FLAG_OK; +} +_Bool bs_set(struct bitset *_bitset_, size_t bit_index) +{ + if (!bs_impl_resize(_bitset_, bit_index + 1, 0)) + return 0; + const cmc_bitset_word bits = sizeof(cmc_bitset_word) * 8; + size_t i = cmc_bidx_to_widx(bit_index); + _bitset_->buffer[i] |= ((cmc_bitset_word)1) << (bit_index % bits); + _bitset_->flag = CMC_FLAG_OK; + if ((_bitset_)->callbacks && (_bitset_)->callbacks->create) + (_bitset_)->callbacks->create(); + ; + return 1; +} +_Bool bs_set_range(struct bitset *_bitset_, size_t from, size_t to) +{ + if (to < from) + { + _bitset_->flag = CMC_FLAG_INVALID; + return 0; + } + if (!bs_impl_resize(_bitset_, to + 1, 0)) + return 0; + size_t start_index = cmc_bidx_to_widx(from); + size_t end_index = cmc_bidx_to_widx(to); + const cmc_bitset_word bits = sizeof(cmc_bitset_word) * 8; + const cmc_bitset_word ones = ~((cmc_bitset_word)0); + cmc_bitset_word shift_start = from % bits; + cmc_bitset_word shift_end = (cmc_bitset_word)(-(to + 1)) % bits; + cmc_bitset_word start_mask = ones << shift_start; + cmc_bitset_word end_mask = ones >> shift_end; + if (start_index == end_index) + { + _bitset_->buffer[end_index] |= (start_mask & end_mask); + } + else + { + _bitset_->buffer[start_index] |= start_mask; + for (size_t i = start_index + 1; i < end_index; i++) + _bitset_->buffer[i] |= ~((cmc_bitset_word)0); + _bitset_->buffer[end_index] |= end_mask; + } + _bitset_->flag = CMC_FLAG_OK; + if ((_bitset_)->callbacks && (_bitset_)->callbacks->create) + (_bitset_)->callbacks->create(); + ; + return 1; +} +_Bool bs_clear(struct bitset *_bitset_, size_t bit_index) +{ + if (!bs_impl_resize(_bitset_, bit_index + 1, 0)) + return 0; + const cmc_bitset_word bits = sizeof(cmc_bitset_word) * 8; + size_t i = cmc_bidx_to_widx(bit_index); + _bitset_->buffer[i] &= ~(((cmc_bitset_word)1) << (bit_index % bits)); + _bitset_->flag = CMC_FLAG_OK; + if ((_bitset_)->callbacks && (_bitset_)->callbacks->delete) + (_bitset_)->callbacks->delete (); + ; + return 1; +} +_Bool bs_clear_range(struct bitset *_bitset_, size_t from, size_t to) +{ + if (to < from) + { + _bitset_->flag = CMC_FLAG_INVALID; + return 0; + } + if (!bs_impl_resize(_bitset_, to + 1, 0)) + return 0; + size_t start_index = cmc_bidx_to_widx(from); + size_t end_index = cmc_bidx_to_widx(to); + const cmc_bitset_word bits = sizeof(cmc_bitset_word) * 8; + const cmc_bitset_word ones = ~((cmc_bitset_word)0); + cmc_bitset_word shift_start = from % bits; + cmc_bitset_word shift_end = (cmc_bitset_word)(-(to + 1)) % bits; + cmc_bitset_word start_mask = ones << shift_start; + cmc_bitset_word end_mask = ones >> shift_end; + if (start_index == end_index) + { + _bitset_->buffer[end_index] &= ~(start_mask & end_mask); + } + else + { + _bitset_->buffer[start_index] &= ~start_mask; + for (size_t i = start_index + 1; i < end_index; i++) + _bitset_->buffer[i] = 0; + _bitset_->buffer[end_index] &= ~end_mask; + } + _bitset_->flag = CMC_FLAG_OK; + if ((_bitset_)->callbacks && (_bitset_)->callbacks->delete) + (_bitset_)->callbacks->delete (); + ; + return 1; +} +_Bool bs_flip(struct bitset *_bitset_, size_t bit_index) +{ + if (!bs_impl_resize(_bitset_, bit_index + 1, 0)) + return 0; + const cmc_bitset_word bits = sizeof(cmc_bitset_word) * 8; + size_t i = cmc_bidx_to_widx(bit_index); + _bitset_->buffer[i] ^= ((cmc_bitset_word)1) << (bit_index % bits); + _bitset_->flag = CMC_FLAG_OK; + if ((_bitset_)->callbacks && (_bitset_)->callbacks->update) + (_bitset_)->callbacks->update(); + ; + return 1; +} +_Bool bs_flip_range(struct bitset *_bitset_, size_t from, size_t to) +{ + if (to < from) + { + _bitset_->flag = CMC_FLAG_INVALID; + return 0; + } + if (!bs_impl_resize(_bitset_, to + 1, 0)) + return 0; + size_t start_index = cmc_bidx_to_widx(from); + size_t end_index = cmc_bidx_to_widx(to); + const cmc_bitset_word bits = sizeof(cmc_bitset_word) * 8; + const cmc_bitset_word ones = ~((cmc_bitset_word)0); + cmc_bitset_word shift_start = from % bits; + cmc_bitset_word shift_end = (cmc_bitset_word)(-(to + 1)) % bits; + cmc_bitset_word start_mask = ones << shift_start; + cmc_bitset_word end_mask = ones >> shift_end; + if (start_index == end_index) + { + _bitset_->buffer[end_index] ^= (start_mask & end_mask); + } + else + { + _bitset_->buffer[start_index] ^= start_mask; + for (size_t i = start_index + 1; i < end_index; i++) + _bitset_->buffer[i] ^= ones; + _bitset_->buffer[end_index] ^= end_mask; + } + _bitset_->flag = CMC_FLAG_OK; + if ((_bitset_)->callbacks && (_bitset_)->callbacks->update) + (_bitset_)->callbacks->update(); + ; + return 1; +} +_Bool bs_put(struct bitset *_bitset_, size_t bit_index, _Bool state) +{ + if (state) + return bs_set(_bitset_, bit_index); + else + return bs_clear(_bitset_, bit_index); +} +_Bool bs_put_range(struct bitset *_bitset_, size_t from, size_t to, _Bool state) +{ + if (state) + return bs_set_range(_bitset_, from, to); + else + return bs_clear_range(_bitset_, from, to); +} +_Bool bs_set_all(struct bitset *_bitset_) +{ + for (size_t i = 0; i < _bitset_->capacity; i++) + _bitset_->buffer[i] = ~((cmc_bitset_word)0); + _bitset_->flag = CMC_FLAG_OK; + if ((_bitset_)->callbacks && (_bitset_)->callbacks->create) + (_bitset_)->callbacks->create(); + ; + return 1; +} +_Bool bs_clear_all(struct bitset *_bitset_) +{ + for (size_t i = 0; i < _bitset_->capacity; i++) + _bitset_->buffer[i] = 0; + _bitset_->flag = CMC_FLAG_OK; + if ((_bitset_)->callbacks && (_bitset_)->callbacks->delete) + (_bitset_)->callbacks->delete (); + ; + return 1; +} +_Bool bs_flip_all(struct bitset *_bitset_) +{ + for (size_t i = 0; i < _bitset_->capacity; i++) + _bitset_->buffer[i] ^= ~((cmc_bitset_word)0); + _bitset_->flag = CMC_FLAG_OK; + if ((_bitset_)->callbacks && (_bitset_)->callbacks->create) + (_bitset_)->callbacks->create(); + ; + return 1; +} +_Bool bs_get(struct bitset *_bitset_, size_t bit_index) +{ + const cmc_bitset_word bits = sizeof(cmc_bitset_word) * 8; + cmc_bitset_word w = _bitset_->buffer[cmc_bidx_to_widx(bit_index)]; + return w & ((cmc_bitset_word)1 << (bit_index % bits)); +} +_Bool bs_resize(struct bitset *_bitset_, size_t n_bits) +{ + return bs_impl_resize(_bitset_, n_bits, 1); +} +_Bool bs_impl_resize(struct bitset *_bitset_, size_t n_bits, _Bool do_resize) +{ + if (n_bits == 0) + { + _bitset_->flag = CMC_FLAG_INVALID; + return 0; + } + size_t words = cmc_bidx_to_widx(n_bits - 1) + 1; + if (!do_resize && words <= _bitset_->capacity) + return 1; + cmc_bitset_word *new_buffer = realloc(_bitset_->buffer, words * sizeof(cmc_bitset_word)); + if (!new_buffer) + { + _bitset_->flag = CMC_FLAG_ALLOC; + return 0; + } + _bitset_->buffer = new_buffer; + if (_bitset_->capacity < words) + memset(_bitset_->buffer + _bitset_->capacity, 0, (words - _bitset_->capacity) * sizeof(cmc_bitset_word)); + _bitset_->capacity = words; + if ((_bitset_)->callbacks && (_bitset_)->callbacks->resize) + (_bitset_)->callbacks->resize(); + ; + _bitset_->flag = CMC_FLAG_OK; + return 1; +} diff --git a/tests/src/tst_cmc_deque.c b/tests/src/tst_cmc_deque.c index e67e9d7..a815278 100644 --- a/tests/src/tst_cmc_deque.c +++ b/tests/src/tst_cmc_deque.c @@ -1,7 +1,516 @@ - #include "tst_cmc_deque.h" +#include "tst_cmc_deque.h" - - struct deque *d_new(size_t capacity, struct deque_fval * f_val) { return d_new_custom(capacity, f_val, ((void *)0), ((void *)0)); } struct deque *d_new_custom(size_t capacity, struct deque_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (capacity < 1) return ((void *)0); if (!f_val) return ((void *)0); if (!alloc) alloc = &cmc_alloc_node_default; struct deque *_deque_ = alloc->malloc(sizeof(struct deque)); if (!_deque_) return ((void *)0); _deque_->buffer = alloc->calloc(capacity, sizeof(size_t)); if (!_deque_->buffer) { alloc->free(_deque_); return ((void *)0); } _deque_->capacity = capacity; _deque_->count = 0; _deque_->front = 0; _deque_->back = 0; _deque_->flag = CMC_FLAG_OK; _deque_->f_val = f_val; _deque_->alloc = alloc; (_deque_)->callbacks = callbacks; return _deque_; } void d_clear(struct deque * _deque_) { if (_deque_->f_val->free) { for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) { _deque_->f_val->free(_deque_->buffer[i]); i = (i + 1) % _deque_->capacity; } } memset(_deque_->buffer, 0, sizeof(size_t) * _deque_->capacity); _deque_->count = 0; _deque_->front = 0; _deque_->back = 0; _deque_->flag = CMC_FLAG_OK; } void d_free(struct deque * _deque_) { if (_deque_->f_val->free) { for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) { _deque_->f_val->free(_deque_->buffer[i]); i = (i + 1) % _deque_->capacity; } } _deque_->alloc->free(_deque_->buffer); _deque_->alloc->free(_deque_); } void d_customize(struct deque * _deque_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (!alloc) _deque_->alloc = &cmc_alloc_node_default; else _deque_->alloc = alloc; (_deque_)->callbacks = callbacks; _deque_->flag = CMC_FLAG_OK; } _Bool d_push_front(struct deque * _deque_, size_t value) { if (d_full(_deque_)) { if (!d_resize(_deque_, _deque_->capacity * 2)) return 0; } _deque_->front = (_deque_->front == 0) ? _deque_->capacity - 1 : _deque_->front - 1; _deque_->buffer[_deque_->front] = value; _deque_->count++; _deque_->flag = CMC_FLAG_OK; if ((_deque_)->callbacks && (_deque_)->callbacks->create) (_deque_)->callbacks->create();; return 1; } _Bool d_push_back(struct deque * _deque_, size_t value) { if (d_full(_deque_)) { if (!d_resize(_deque_, _deque_->capacity * 2)) return 0; } _deque_->buffer[_deque_->back] = value; _deque_->back = (_deque_->back == _deque_->capacity - 1) ? 0 : _deque_->back + 1; _deque_->count++; _deque_->flag = CMC_FLAG_OK; if ((_deque_)->callbacks && (_deque_)->callbacks->create) (_deque_)->callbacks->create();; return 1; } _Bool d_pop_front(struct deque * _deque_) { if (d_empty(_deque_)) { _deque_->flag = CMC_FLAG_EMPTY; return 0; } _deque_->buffer[_deque_->front] = (size_t){ 0 }; _deque_->front = (_deque_->front == _deque_->capacity - 1) ? 0 : _deque_->front + 1; _deque_->count--; _deque_->flag = CMC_FLAG_OK; if ((_deque_)->callbacks && (_deque_)->callbacks->delete) (_deque_)->callbacks->delete();; return 1; } _Bool d_pop_back(struct deque * _deque_) { if (d_empty(_deque_)) { _deque_->flag = CMC_FLAG_EMPTY; return 0; } _deque_->back = (_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1; _deque_->buffer[_deque_->back] = (size_t){ 0 }; _deque_->count--; _deque_->flag = CMC_FLAG_OK; if ((_deque_)->callbacks && (_deque_)->callbacks->delete) (_deque_)->callbacks->delete();; return 1; } size_t d_front(struct deque * _deque_) { if (d_empty(_deque_)) { _deque_->flag = CMC_FLAG_EMPTY; return (size_t){ 0 }; } _deque_->flag = CMC_FLAG_OK; if ((_deque_)->callbacks && (_deque_)->callbacks->read) (_deque_)->callbacks->read();; return _deque_->buffer[_deque_->front]; } size_t d_back(struct deque * _deque_) { if (d_empty(_deque_)) { _deque_->flag = CMC_FLAG_EMPTY; return (size_t){ 0 }; } _deque_->flag = CMC_FLAG_OK; if ((_deque_)->callbacks && (_deque_)->callbacks->read) (_deque_)->callbacks->read();; return _deque_->buffer[(_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1]; } _Bool d_contains(struct deque * _deque_, size_t value) { _deque_->flag = CMC_FLAG_OK; _Bool result = 0; for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) { if (_deque_->f_val->cmp(_deque_->buffer[i], value) == 0) { result = 1; break; } i = (i + 1) % _deque_->capacity; } if ((_deque_)->callbacks && (_deque_)->callbacks->read) (_deque_)->callbacks->read();; return result; } _Bool d_empty(struct deque * _deque_) { return _deque_->count == 0; } _Bool d_full(struct deque * _deque_) { return _deque_->count >= _deque_->capacity; } size_t d_count(struct deque * _deque_) { return _deque_->count; } size_t d_capacity(struct deque * _deque_) { return _deque_->capacity; } int d_flag(struct deque * _deque_) { return _deque_->flag; } _Bool d_resize(struct deque * _deque_, size_t capacity) { _deque_->flag = CMC_FLAG_OK; if (_deque_->capacity == capacity) goto success; if (capacity < _deque_->count) { _deque_->flag = CMC_FLAG_INVALID; return 0; } size_t *new_buffer = _deque_->alloc->malloc(sizeof(size_t) * capacity); if (!new_buffer) { _deque_->flag = CMC_FLAG_ALLOC; return 0; } for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) { new_buffer[j] = _deque_->buffer[i]; i = (i + 1) % _deque_->capacity; } _deque_->alloc->free(_deque_->buffer); _deque_->buffer = new_buffer; _deque_->capacity = capacity; _deque_->front = 0; _deque_->back = _deque_->count; success: if ((_deque_)->callbacks && (_deque_)->callbacks->resize) (_deque_)->callbacks->resize();; return 1; } struct deque *d_copy_of(struct deque * _deque_) { struct deque *result = d_new_custom(_deque_->capacity, _deque_->f_val, _deque_->alloc, ((void *)0)); if (!result) { _deque_->flag = CMC_FLAG_ERROR; return ((void *)0); } (result)->callbacks = _deque_->callbacks; if (_deque_->f_val->cpy) { for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) { result->buffer[j] = _deque_->f_val->cpy(_deque_->buffer[i]); i = (i + 1) % _deque_->capacity; } } else { for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) { result->buffer[j] = _deque_->buffer[i]; i = (i + 1) % _deque_->capacity; } } result->count = _deque_->count; result->front = 0; result->back = _deque_->count; _deque_->flag = CMC_FLAG_OK; return result; } _Bool d_equals(struct deque * _deque1_, struct deque * _deque2_) { _deque1_->flag = CMC_FLAG_OK; _deque2_->flag = CMC_FLAG_OK; if (_deque1_->count != _deque2_->count) return 0; size_t i, j, k; for (i = _deque1_->front, j = _deque2_->front, k = 0; k < _deque1_->count; k++) { if (_deque1_->f_val->cmp(_deque1_->buffer[i], _deque2_->buffer[j]) != 0) return 0; i = (i + 1) % _deque1_->capacity; j = (j + 1) % _deque2_->capacity; } return 1; } struct deque d_init(size_t capacity, struct deque_fval * f_val) { return d_init_custom(capacity, f_val, ((void *)0), ((void *)0)); } struct deque d_init_custom(size_t capacity, struct deque_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; struct deque _deque_ = { 0 }; if (capacity < 1) return _deque_; if (!f_val) return _deque_; if (!alloc) alloc = &cmc_alloc_node_default; _deque_.buffer = alloc->calloc(capacity, sizeof(size_t)); if (!_deque_.buffer) return _deque_; _deque_.capacity = capacity; _deque_.count = 0; _deque_.front = 0; _deque_.back = 0; _deque_.flag = CMC_FLAG_OK; _deque_.f_val = f_val; _deque_.alloc = alloc; (&_deque_)->callbacks = callbacks; return _deque_; } void d_release(struct deque _deque_) { if (_deque_.f_val->free) { for (size_t i = _deque_.front, j = 0; j < _deque_.count; j++) { _deque_.f_val->free(_deque_.buffer[i]); i = (i + 1) % _deque_.capacity; } } _deque_.alloc->free(_deque_.buffer); } struct deque_iter d_iter_start(struct deque * target) { struct deque_iter iter; iter.target = target; iter.cursor = target->front; iter.index = 0; iter.start = 1; iter.end = d_empty(target); return iter; } struct deque_iter d_iter_end(struct deque * target) { struct deque_iter iter; iter.target = target; if (!d_empty(target)) { if (iter.target->back == 0) iter.cursor = iter.target->capacity - 1; else iter.cursor = iter.target->back - 1; iter.index = iter.target->count - 1; } else { iter.cursor = 0; iter.index = 0; } iter.start = d_empty(target); iter.end = 1; return iter; } _Bool d_iter_at_start(struct deque_iter * iter) { return d_empty(iter->target) || iter->start; } _Bool d_iter_at_end(struct deque_iter * iter) { return d_empty(iter->target) || iter->end; } _Bool d_iter_to_start(struct deque_iter * iter) { if (!d_empty(iter->target)) { iter->cursor = iter->target->front; iter->index = 0; iter->start = 1; iter->end = 0; return 1; } return 0; } _Bool d_iter_to_end(struct deque_iter * iter) { if (!d_empty(iter->target)) { if (iter->target->back == 0) iter->cursor = iter->target->capacity - 1; else iter->cursor = iter->target->back - 1; iter->index = iter->target->count - 1; iter->start = 0; iter->end = 1; return 1; } return 0; } _Bool d_iter_next(struct deque_iter * iter) { if (iter->end) return 0; if (iter->index + 1 == iter->target->count) { iter->end = 1; return 0; } iter->start = d_empty(iter->target); iter->cursor = (iter->cursor + 1) % (iter->target->capacity); iter->index++; return 1; } _Bool d_iter_prev(struct deque_iter * iter) { if (iter->start) return 0; if (iter->index == 0) { iter->start = 1; return 0; } iter->end = d_empty(iter->target); iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; iter->index--; return 1; } _Bool d_iter_advance(struct deque_iter * iter, size_t steps) { if (iter->end) return 0; if (iter->index + 1 == iter->target->count) { iter->end = 1; return 0; } if (steps == 0 || iter->index + steps >= iter->target->count) return 0; iter->start = d_empty(iter->target); iter->index += steps; iter->cursor = (iter->cursor + steps) % iter->target->capacity; return 1; } _Bool d_iter_rewind(struct deque_iter * iter, size_t steps) { if (iter->start) return 0; if (iter->index == 0) { iter->start = 1; return 0; } if (steps == 0 || iter->index < steps) return 0; iter->end = d_empty(iter->target); iter->index -= steps; if (iter->cursor < steps) iter->cursor += iter->target->capacity; iter->cursor -= steps; return 1; } _Bool d_iter_go_to(struct deque_iter * iter, size_t index) { if (index >= iter->target->count) return 0; if (iter->index > index) return d_iter_rewind(iter, iter->index - index); else if (iter->index < index) return d_iter_advance(iter, index - iter->index); return 1; } size_t d_iter_value(struct deque_iter * iter) { if (d_empty(iter->target)) return (size_t){ 0 }; return iter->target->buffer[iter->cursor]; } size_t *d_iter_rvalue(struct deque_iter * iter) { if (d_empty(iter->target)) return ((void *)0); return &(iter->target->buffer[iter->cursor]); } size_t d_iter_index(struct deque_iter * iter) { return iter->index; } _Bool d_to_string(struct deque * _deque_, FILE * fptr) { struct deque *d_ = _deque_; return 0 <= fprintf(fptr, "struct %s<%s> " "at %p { " "buffer:%p, " "capacity:%" "I64u" ", " "count:%" "I64u" ", " "front:%" "I64u" ", " "back:%" "I64u" ", " "flag:%d, " "f_val:%p, " "alloc:%p, " "callbacks:%p }", "deque", "size_t", d_, d_->buffer, d_->capacity, d_->count, d_->front, d_->back, d_->flag, d_->f_val, d_->alloc, (d_)->callbacks); } _Bool d_print(struct deque * _deque_, FILE * fptr, const char *start, const char *separator, const char *end) { fprintf(fptr, "%s", start); for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) { if (!_deque_->f_val->str(fptr, _deque_->buffer[i])) return 0; i = (i + 1) % _deque_->capacity; if (j + 1 < _deque_->count) fprintf(fptr, "%s", separator); } fprintf(fptr, "%s", end); return 1; } - - \ No newline at end of file +struct deque *d_new(size_t capacity, struct deque_fval *f_val) +{ + return d_new_custom(capacity, f_val, ((void *)0), ((void *)0)); +} +struct deque *d_new_custom(size_t capacity, struct deque_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks) +{ + ; + if (capacity < 1) + return ((void *)0); + if (!f_val) + return ((void *)0); + if (!alloc) + alloc = &cmc_alloc_node_default; + struct deque *_deque_ = alloc->malloc(sizeof(struct deque)); + if (!_deque_) + return ((void *)0); + _deque_->buffer = alloc->calloc(capacity, sizeof(size_t)); + if (!_deque_->buffer) + { + alloc->free(_deque_); + return ((void *)0); + } + _deque_->capacity = capacity; + _deque_->count = 0; + _deque_->front = 0; + _deque_->back = 0; + _deque_->flag = CMC_FLAG_OK; + _deque_->f_val = f_val; + _deque_->alloc = alloc; + (_deque_)->callbacks = callbacks; + return _deque_; +} +void d_clear(struct deque *_deque_) +{ + if (_deque_->f_val->free) + { + for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) + { + _deque_->f_val->free(_deque_->buffer[i]); + i = (i + 1) % _deque_->capacity; + } + } + memset(_deque_->buffer, 0, sizeof(size_t) * _deque_->capacity); + _deque_->count = 0; + _deque_->front = 0; + _deque_->back = 0; + _deque_->flag = CMC_FLAG_OK; +} +void d_free(struct deque *_deque_) +{ + if (_deque_->f_val->free) + { + for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) + { + _deque_->f_val->free(_deque_->buffer[i]); + i = (i + 1) % _deque_->capacity; + } + } + _deque_->alloc->free(_deque_->buffer); + _deque_->alloc->free(_deque_); +} +void d_customize(struct deque *_deque_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks) +{ + ; + if (!alloc) + _deque_->alloc = &cmc_alloc_node_default; + else + _deque_->alloc = alloc; + (_deque_)->callbacks = callbacks; + _deque_->flag = CMC_FLAG_OK; +} +_Bool d_push_front(struct deque *_deque_, size_t value) +{ + if (d_full(_deque_)) + { + if (!d_resize(_deque_, _deque_->capacity * 2)) + return 0; + } + _deque_->front = (_deque_->front == 0) ? _deque_->capacity - 1 : _deque_->front - 1; + _deque_->buffer[_deque_->front] = value; + _deque_->count++; + _deque_->flag = CMC_FLAG_OK; + if ((_deque_)->callbacks && (_deque_)->callbacks->create) + (_deque_)->callbacks->create(); + ; + return 1; +} +_Bool d_push_back(struct deque *_deque_, size_t value) +{ + if (d_full(_deque_)) + { + if (!d_resize(_deque_, _deque_->capacity * 2)) + return 0; + } + _deque_->buffer[_deque_->back] = value; + _deque_->back = (_deque_->back == _deque_->capacity - 1) ? 0 : _deque_->back + 1; + _deque_->count++; + _deque_->flag = CMC_FLAG_OK; + if ((_deque_)->callbacks && (_deque_)->callbacks->create) + (_deque_)->callbacks->create(); + ; + return 1; +} +_Bool d_pop_front(struct deque *_deque_) +{ + if (d_empty(_deque_)) + { + _deque_->flag = CMC_FLAG_EMPTY; + return 0; + } + _deque_->buffer[_deque_->front] = (size_t){ 0 }; + _deque_->front = (_deque_->front == _deque_->capacity - 1) ? 0 : _deque_->front + 1; + _deque_->count--; + _deque_->flag = CMC_FLAG_OK; + if ((_deque_)->callbacks && (_deque_)->callbacks->delete) + (_deque_)->callbacks->delete (); + ; + return 1; +} +_Bool d_pop_back(struct deque *_deque_) +{ + if (d_empty(_deque_)) + { + _deque_->flag = CMC_FLAG_EMPTY; + return 0; + } + _deque_->back = (_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1; + _deque_->buffer[_deque_->back] = (size_t){ 0 }; + _deque_->count--; + _deque_->flag = CMC_FLAG_OK; + if ((_deque_)->callbacks && (_deque_)->callbacks->delete) + (_deque_)->callbacks->delete (); + ; + return 1; +} +size_t d_front(struct deque *_deque_) +{ + if (d_empty(_deque_)) + { + _deque_->flag = CMC_FLAG_EMPTY; + return (size_t){ 0 }; + } + _deque_->flag = CMC_FLAG_OK; + if ((_deque_)->callbacks && (_deque_)->callbacks->read) + (_deque_)->callbacks->read(); + ; + return _deque_->buffer[_deque_->front]; +} +size_t d_back(struct deque *_deque_) +{ + if (d_empty(_deque_)) + { + _deque_->flag = CMC_FLAG_EMPTY; + return (size_t){ 0 }; + } + _deque_->flag = CMC_FLAG_OK; + if ((_deque_)->callbacks && (_deque_)->callbacks->read) + (_deque_)->callbacks->read(); + ; + return _deque_->buffer[(_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1]; +} +_Bool d_contains(struct deque *_deque_, size_t value) +{ + _deque_->flag = CMC_FLAG_OK; + _Bool result = 0; + for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) + { + if (_deque_->f_val->cmp(_deque_->buffer[i], value) == 0) + { + result = 1; + break; + } + i = (i + 1) % _deque_->capacity; + } + if ((_deque_)->callbacks && (_deque_)->callbacks->read) + (_deque_)->callbacks->read(); + ; + return result; +} +_Bool d_empty(struct deque *_deque_) +{ + return _deque_->count == 0; +} +_Bool d_full(struct deque *_deque_) +{ + return _deque_->count >= _deque_->capacity; +} +size_t d_count(struct deque *_deque_) +{ + return _deque_->count; +} +size_t d_capacity(struct deque *_deque_) +{ + return _deque_->capacity; +} +int d_flag(struct deque *_deque_) +{ + return _deque_->flag; +} +_Bool d_resize(struct deque *_deque_, size_t capacity) +{ + _deque_->flag = CMC_FLAG_OK; + if (_deque_->capacity == capacity) + goto success; + if (capacity < _deque_->count) + { + _deque_->flag = CMC_FLAG_INVALID; + return 0; + } + size_t *new_buffer = _deque_->alloc->malloc(sizeof(size_t) * capacity); + if (!new_buffer) + { + _deque_->flag = CMC_FLAG_ALLOC; + return 0; + } + for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) + { + new_buffer[j] = _deque_->buffer[i]; + i = (i + 1) % _deque_->capacity; + } + _deque_->alloc->free(_deque_->buffer); + _deque_->buffer = new_buffer; + _deque_->capacity = capacity; + _deque_->front = 0; + _deque_->back = _deque_->count; +success: + if ((_deque_)->callbacks && (_deque_)->callbacks->resize) + (_deque_)->callbacks->resize(); + ; + return 1; +} +struct deque *d_copy_of(struct deque *_deque_) +{ + struct deque *result = d_new_custom(_deque_->capacity, _deque_->f_val, _deque_->alloc, ((void *)0)); + if (!result) + { + _deque_->flag = CMC_FLAG_ERROR; + return ((void *)0); + } + (result)->callbacks = _deque_->callbacks; + if (_deque_->f_val->cpy) + { + for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) + { + result->buffer[j] = _deque_->f_val->cpy(_deque_->buffer[i]); + i = (i + 1) % _deque_->capacity; + } + } + else + { + for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) + { + result->buffer[j] = _deque_->buffer[i]; + i = (i + 1) % _deque_->capacity; + } + } + result->count = _deque_->count; + result->front = 0; + result->back = _deque_->count; + _deque_->flag = CMC_FLAG_OK; + return result; +} +_Bool d_equals(struct deque *_deque1_, struct deque *_deque2_) +{ + _deque1_->flag = CMC_FLAG_OK; + _deque2_->flag = CMC_FLAG_OK; + if (_deque1_->count != _deque2_->count) + return 0; + size_t i, j, k; + for (i = _deque1_->front, j = _deque2_->front, k = 0; k < _deque1_->count; k++) + { + if (_deque1_->f_val->cmp(_deque1_->buffer[i], _deque2_->buffer[j]) != 0) + return 0; + i = (i + 1) % _deque1_->capacity; + j = (j + 1) % _deque2_->capacity; + } + return 1; +} +struct deque d_init(size_t capacity, struct deque_fval *f_val) +{ + return d_init_custom(capacity, f_val, ((void *)0), ((void *)0)); +} +struct deque d_init_custom(size_t capacity, struct deque_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks) +{ + ; + struct deque _deque_ = { 0 }; + if (capacity < 1) + return _deque_; + if (!f_val) + return _deque_; + if (!alloc) + alloc = &cmc_alloc_node_default; + _deque_.buffer = alloc->calloc(capacity, sizeof(size_t)); + if (!_deque_.buffer) + return _deque_; + _deque_.capacity = capacity; + _deque_.count = 0; + _deque_.front = 0; + _deque_.back = 0; + _deque_.flag = CMC_FLAG_OK; + _deque_.f_val = f_val; + _deque_.alloc = alloc; + (&_deque_)->callbacks = callbacks; + return _deque_; +} +void d_release(struct deque _deque_) +{ + if (_deque_.f_val->free) + { + for (size_t i = _deque_.front, j = 0; j < _deque_.count; j++) + { + _deque_.f_val->free(_deque_.buffer[i]); + i = (i + 1) % _deque_.capacity; + } + } + _deque_.alloc->free(_deque_.buffer); +} +struct deque_iter d_iter_start(struct deque *target) +{ + struct deque_iter iter; + iter.target = target; + iter.cursor = target->front; + iter.index = 0; + iter.start = 1; + iter.end = d_empty(target); + return iter; +} +struct deque_iter d_iter_end(struct deque *target) +{ + struct deque_iter iter; + iter.target = target; + if (!d_empty(target)) + { + if (iter.target->back == 0) + iter.cursor = iter.target->capacity - 1; + else + iter.cursor = iter.target->back - 1; + iter.index = iter.target->count - 1; + } + else + { + iter.cursor = 0; + iter.index = 0; + } + iter.start = d_empty(target); + iter.end = 1; + return iter; +} +_Bool d_iter_at_start(struct deque_iter *iter) +{ + return d_empty(iter->target) || iter->start; +} +_Bool d_iter_at_end(struct deque_iter *iter) +{ + return d_empty(iter->target) || iter->end; +} +_Bool d_iter_to_start(struct deque_iter *iter) +{ + if (!d_empty(iter->target)) + { + iter->cursor = iter->target->front; + iter->index = 0; + iter->start = 1; + iter->end = 0; + return 1; + } + return 0; +} +_Bool d_iter_to_end(struct deque_iter *iter) +{ + if (!d_empty(iter->target)) + { + if (iter->target->back == 0) + iter->cursor = iter->target->capacity - 1; + else + iter->cursor = iter->target->back - 1; + iter->index = iter->target->count - 1; + iter->start = 0; + iter->end = 1; + return 1; + } + return 0; +} +_Bool d_iter_next(struct deque_iter *iter) +{ + if (iter->end) + return 0; + if (iter->index + 1 == iter->target->count) + { + iter->end = 1; + return 0; + } + iter->start = d_empty(iter->target); + iter->cursor = (iter->cursor + 1) % (iter->target->capacity); + iter->index++; + return 1; +} +_Bool d_iter_prev(struct deque_iter *iter) +{ + if (iter->start) + return 0; + if (iter->index == 0) + { + iter->start = 1; + return 0; + } + iter->end = d_empty(iter->target); + iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; + iter->index--; + return 1; +} +_Bool d_iter_advance(struct deque_iter *iter, size_t steps) +{ + if (iter->end) + return 0; + if (iter->index + 1 == iter->target->count) + { + iter->end = 1; + return 0; + } + if (steps == 0 || iter->index + steps >= iter->target->count) + return 0; + iter->start = d_empty(iter->target); + iter->index += steps; + iter->cursor = (iter->cursor + steps) % iter->target->capacity; + return 1; +} +_Bool d_iter_rewind(struct deque_iter *iter, size_t steps) +{ + if (iter->start) + return 0; + if (iter->index == 0) + { + iter->start = 1; + return 0; + } + if (steps == 0 || iter->index < steps) + return 0; + iter->end = d_empty(iter->target); + iter->index -= steps; + if (iter->cursor < steps) + iter->cursor += iter->target->capacity; + iter->cursor -= steps; + return 1; +} +_Bool d_iter_go_to(struct deque_iter *iter, size_t index) +{ + if (index >= iter->target->count) + return 0; + if (iter->index > index) + return d_iter_rewind(iter, iter->index - index); + else if (iter->index < index) + return d_iter_advance(iter, index - iter->index); + return 1; +} +size_t d_iter_value(struct deque_iter *iter) +{ + if (d_empty(iter->target)) + return (size_t){ 0 }; + return iter->target->buffer[iter->cursor]; +} +size_t *d_iter_rvalue(struct deque_iter *iter) +{ + if (d_empty(iter->target)) + return ((void *)0); + return &(iter->target->buffer[iter->cursor]); +} +size_t d_iter_index(struct deque_iter *iter) +{ + return iter->index; +} +_Bool d_to_string(struct deque *_deque_, FILE *fptr) +{ + struct deque *d_ = _deque_; + return 0 <= fprintf(fptr, + "struct %s<%s> " + "at %p { " + "buffer:%p, " + "capacity:%" + "I64u" + ", " + "count:%" + "I64u" + ", " + "front:%" + "I64u" + ", " + "back:%" + "I64u" + ", " + "flag:%d, " + "f_val:%p, " + "alloc:%p, " + "callbacks:%p }", + "deque", "size_t", d_, d_->buffer, d_->capacity, d_->count, d_->front, d_->back, d_->flag, + d_->f_val, d_->alloc, (d_)->callbacks); +} +_Bool d_print(struct deque *_deque_, FILE *fptr, const char *start, const char *separator, const char *end) +{ + fprintf(fptr, "%s", start); + for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) + { + if (!_deque_->f_val->str(fptr, _deque_->buffer[i])) + return 0; + i = (i + 1) % _deque_->capacity; + if (j + 1 < _deque_->count) + fprintf(fptr, "%s", separator); + } + fprintf(fptr, "%s", end); + return 1; +} diff --git a/tests/src/tst_cmc_hashbidimap.c b/tests/src/tst_cmc_hashbidimap.c index 8b46a90..b7381c4 100644 --- a/tests/src/tst_cmc_hashbidimap.c +++ b/tests/src/tst_cmc_hashbidimap.c @@ -1,7 +1,856 @@ - #include "tst_cmc_hashbidimap.h" +#include "tst_cmc_hashbidimap.h" - - static struct hashbidimap_entry * hbm_impl_new_entry(struct hashbidimap * _map_, size_t key, size_t value); static struct hashbidimap_entry * *hbm_impl_get_entry_by_key(struct hashbidimap * _map_, size_t key); static struct hashbidimap_entry * *hbm_impl_get_entry_by_val(struct hashbidimap * _map_, size_t val); static struct hashbidimap_entry * *hbm_impl_add_entry_to_key(struct hashbidimap * _map_, struct hashbidimap_entry * entry); static struct hashbidimap_entry * *hbm_impl_add_entry_to_val(struct hashbidimap * _map_, struct hashbidimap_entry * entry); static size_t hbm_impl_calculate_size(size_t required); static struct hashbidimap_iter hbm_impl_it_start(struct hashbidimap * _map_); static struct hashbidimap_iter hbm_impl_it_end(struct hashbidimap * _map_); struct hashbidimap *hbm_new(size_t capacity, double load, struct hashbidimap_fkey * f_key, struct hashbidimap_fval * f_val) { return hbm_new_custom(capacity, load, f_key, f_val, ((void *)0), ((void *)0)); } struct hashbidimap *hbm_new_custom(size_t capacity, double load, struct hashbidimap_fkey * f_key, struct hashbidimap_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (capacity == 0 || load <= 0 || load >= 1) return ((void *)0); if (capacity >= 0xffffffffffffffffULL * load) return ((void *)0); if (!f_key || !f_val) return ((void *)0); size_t real_capacity = hbm_impl_calculate_size(capacity / load); if (!alloc) alloc = &cmc_alloc_node_default; struct hashbidimap *_map_ = alloc->malloc(sizeof(struct hashbidimap)); if (!_map_) return ((void *)0); _map_->buffer = alloc->calloc(real_capacity, sizeof(struct hashbidimap_entry *[2])); if (!_map_->buffer) { alloc->free(_map_->buffer); alloc->free(_map_); return ((void *)0); } _map_->count = 0; _map_->capacity = real_capacity; _map_->load = load; _map_->flag = CMC_FLAG_OK; _map_->f_key = f_key; _map_->f_val = f_val; _map_->flag = CMC_FLAG_OK; _map_->alloc = alloc; (_map_)->callbacks = callbacks; _map_->it_start = hbm_impl_it_start; _map_->it_end = hbm_impl_it_end; return _map_; } void hbm_clear(struct hashbidimap * _map_) { for (size_t i = 0; i < _map_->capacity; i++) { struct hashbidimap_entry *entry = _map_->buffer[i][0]; if (entry && entry != ((void *)1)) { if (_map_->f_key->free) _map_->f_key->free(entry->key); if (_map_->f_val->free) _map_->f_val->free(entry->value); _map_->alloc->free(entry); } _map_->buffer[i][0] = ((void *)0); _map_->buffer[i][1] = ((void *)0); } _map_->count = 0; _map_->flag = CMC_FLAG_OK; } void hbm_free(struct hashbidimap * _map_) { hbm_clear(_map_); _map_->alloc->free(_map_->buffer); _map_->alloc->free(_map_); } void hbm_customize(struct hashbidimap * _map_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (!alloc) _map_->alloc = &cmc_alloc_node_default; else _map_->alloc = alloc; (_map_)->callbacks = callbacks; _map_->flag = CMC_FLAG_OK; } _Bool hbm_insert(struct hashbidimap * _map_, size_t key, size_t value) { if (hbm_full(_map_)) { if (!hbm_resize(_map_, _map_->capacity + 1)) return 0; } if (hbm_impl_get_entry_by_key(_map_, key) != ((void *)0) || hbm_impl_get_entry_by_val(_map_, value) != ((void *)0)) { _map_->flag = CMC_FLAG_DUPLICATE; return 0; } struct hashbidimap_entry *entry = hbm_impl_new_entry(_map_, key, value); struct hashbidimap_entry **key_entry = hbm_impl_add_entry_to_key(_map_, entry); struct hashbidimap_entry **val_entry = hbm_impl_add_entry_to_val(_map_, entry); if (!key_entry || !val_entry) { if (key_entry) *key_entry = ((void *)1); if (val_entry) *val_entry = ((void *)1); _map_->alloc->free(entry); _map_->flag = CMC_FLAG_ERROR; return 0; } _map_->count++; _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->create) (_map_)->callbacks->create();; return 1; } _Bool hbm_update_key(struct hashbidimap * _map_, size_t val, size_t new_key) { if (hbm_empty(_map_)) { _map_->flag = CMC_FLAG_EMPTY; return 0; } struct hashbidimap_entry * *key_entry, **val_entry; val_entry = hbm_impl_get_entry_by_val(_map_, val); if (!val_entry) { _map_->flag = CMC_FLAG_NOT_FOUND; return 0; } if (_map_->f_key->cmp(new_key, (*val_entry)->key) == 0) goto success; if (hbm_impl_get_entry_by_key(_map_, new_key) != ((void *)0)) { _map_->flag = CMC_FLAG_DUPLICATE; return 0; } key_entry = (*val_entry)->ref[0]; if (!key_entry || *key_entry != *val_entry) { _map_->flag = CMC_FLAG_ERROR; return 0; } struct hashbidimap_entry *to_add = *key_entry; size_t tmp_key = to_add->key; to_add->key = new_key; *key_entry = ((void *)1); if (!hbm_impl_add_entry_to_key(_map_, to_add)) { to_add->key = tmp_key; *key_entry = to_add; _map_->flag = CMC_FLAG_ERROR; return 0; } success: _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->update) (_map_)->callbacks->update();; return 1; } _Bool hbm_update_val(struct hashbidimap * _map_, size_t key, size_t new_val) { if (hbm_empty(_map_)) { _map_->flag = CMC_FLAG_EMPTY; return 0; } struct hashbidimap_entry * *key_entry, **val_entry; key_entry = hbm_impl_get_entry_by_key(_map_, key); if (!key_entry) { _map_->flag = CMC_FLAG_NOT_FOUND; return 0; } if (_map_->f_val->cmp(new_val, (*key_entry)->value) == 0) goto success; if (hbm_impl_get_entry_by_val(_map_, new_val) != ((void *)0)) { _map_->flag = CMC_FLAG_DUPLICATE; return 0; } val_entry = (*key_entry)->ref[1]; if (!val_entry || *val_entry != *key_entry) { _map_->flag = CMC_FLAG_ERROR; return 0; } struct hashbidimap_entry *to_add = *val_entry; size_t tmp_val = to_add->value; to_add->value = new_val; *val_entry = ((void *)1); if (!hbm_impl_add_entry_to_val(_map_, to_add)) { to_add->value = tmp_val; *val_entry = to_add; _map_->flag = CMC_FLAG_ERROR; return 0; } success: _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->update) (_map_)->callbacks->update();; return 1; } _Bool hbm_remove_by_key(struct hashbidimap * _map_, size_t key, size_t * out_key, size_t * out_val) { if (hbm_empty(_map_)) { _map_->flag = CMC_FLAG_EMPTY; return 0; } struct hashbidimap_entry * *key_entry, **val_entry; key_entry = hbm_impl_get_entry_by_key(_map_, key); if (!key_entry) { _map_->flag = CMC_FLAG_NOT_FOUND; return 0; } val_entry = (*key_entry)->ref[1]; if (!val_entry || *val_entry != *key_entry) { _map_->flag = CMC_FLAG_ERROR; return 0; } if (out_key) *out_key = (*key_entry)->key; if (out_val) *out_val = (*key_entry)->value; _map_->alloc->free(*key_entry); *key_entry = ((void *)1); *val_entry = ((void *)1); _map_->count--; _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->delete) (_map_)->callbacks->delete();; return 1; } _Bool hbm_remove_by_val(struct hashbidimap * _map_, size_t val, size_t * out_key, size_t * out_val) { if (hbm_empty(_map_)) { _map_->flag = CMC_FLAG_EMPTY; return 0; } struct hashbidimap_entry * *key_entry, **val_entry; val_entry = hbm_impl_get_entry_by_val(_map_, val); if (!val_entry) { _map_->flag = CMC_FLAG_NOT_FOUND; return 0; } key_entry = (*val_entry)->ref[0]; if (!key_entry || *key_entry != *val_entry) { _map_->flag = CMC_FLAG_ERROR; return 0; } if (out_key) *out_key = (*val_entry)->key; if (out_val) *out_val = (*val_entry)->value; _map_->alloc->free(*val_entry); *key_entry = ((void *)1); *val_entry = ((void *)1); _map_->count--; _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->delete) (_map_)->callbacks->delete();; return 1; } size_t hbm_get_key(struct hashbidimap * _map_, size_t val) { struct hashbidimap_entry **entry = hbm_impl_get_entry_by_val(_map_, val); if (!entry) { _map_->flag = CMC_FLAG_NOT_FOUND; return (size_t){ 0 }; } _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->read) (_map_)->callbacks->read();; return (*entry)->key; } size_t hbm_get_val(struct hashbidimap * _map_, size_t key) { struct hashbidimap_entry **entry = hbm_impl_get_entry_by_key(_map_, key); if (!entry) { _map_->flag = CMC_FLAG_NOT_FOUND; return (size_t){ 0 }; } _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->read) (_map_)->callbacks->read();; return (*entry)->value; } _Bool hbm_contains_key(struct hashbidimap * _map_, size_t key) { _map_->flag = CMC_FLAG_OK; _Bool result = hbm_impl_get_entry_by_key(_map_, key) != ((void *)0); if ((_map_)->callbacks && (_map_)->callbacks->read) (_map_)->callbacks->read();; return result; } _Bool hbm_contains_val(struct hashbidimap * _map_, size_t val) { _map_->flag = CMC_FLAG_OK; _Bool result = hbm_impl_get_entry_by_val(_map_, val) != ((void *)0); if ((_map_)->callbacks && (_map_)->callbacks->read) (_map_)->callbacks->read();; return result; } _Bool hbm_empty(struct hashbidimap * _map_) { return _map_->count == 0; } _Bool hbm_full(struct hashbidimap * _map_) { return (double)_map_->capacity * _map_->load <= (double)_map_->count; } size_t hbm_count(struct hashbidimap * _map_) { return _map_->count; } size_t hbm_capacity(struct hashbidimap * _map_) { return _map_->capacity; } double hbm_load(struct hashbidimap * _map_) { return _map_->load; } int hbm_flag(struct hashbidimap * _map_) { return _map_->flag; } _Bool hbm_resize(struct hashbidimap * _map_, size_t capacity) { _map_->flag = CMC_FLAG_OK; if (_map_->capacity == capacity) goto success; if (_map_->capacity > capacity / _map_->load) goto success; if (capacity >= 0xffffffffffffffffULL * _map_->load) { _map_->flag = CMC_FLAG_ERROR; return 0; } size_t new_cap = hbm_impl_calculate_size(capacity); if (new_cap < _map_->count / _map_->load) { _map_->flag = CMC_FLAG_INVALID; return 0; } struct hashbidimap *_new_map_ = hbm_new_custom(capacity, _map_->load, _map_->f_key, _map_->f_val, _map_->alloc, ((void *)0)); if (!_new_map_) { _map_->flag = CMC_FLAG_ALLOC; return 0; } for (size_t i = 0; i < _map_->capacity; i++) { struct hashbidimap_entry *scan = _map_->buffer[i][0]; if (scan && scan != ((void *)1)) { struct hashbidimap_entry **e1 = hbm_impl_add_entry_to_key(_new_map_, scan); struct hashbidimap_entry **e2 = hbm_impl_add_entry_to_val(_new_map_, scan); if (!e1 || !e2) { _new_map_->f_key = &(struct hashbidimap_fkey){ ((void *)0) }; _new_map_->f_val = &(struct hashbidimap_fval){ ((void *)0) }; _map_->alloc->free(_new_map_->buffer); _map_->alloc->free(_new_map_); _map_->flag = CMC_FLAG_ERROR; return 0; } _new_map_->count++; } } if (_map_->count != _new_map_->count) { _new_map_->f_key = &(struct hashbidimap_fkey){ ((void *)0) }; _new_map_->f_val = &(struct hashbidimap_fval){ ((void *)0) }; _map_->alloc->free(_new_map_->buffer); _map_->alloc->free(_new_map_); _map_->flag = CMC_FLAG_ERROR; return 0; } struct hashbidimap_entry * (*tmp_buff)[2] = _map_->buffer; _map_->buffer = _new_map_->buffer; _map_->capacity = _new_map_->capacity; _map_->alloc->free(tmp_buff); _map_->alloc->free(_new_map_); success: if ((_map_)->callbacks && (_map_)->callbacks->resize) (_map_)->callbacks->resize();; return 1; } struct hashbidimap *hbm_copy_of(struct hashbidimap * _map_) { struct hashbidimap *result = hbm_new_custom(_map_->capacity * _map_->load, _map_->load, _map_->f_key, _map_->f_val, _map_->alloc, ((void *)0)); if (!result) { _map_->flag = CMC_FLAG_ERROR; return ((void *)0); } (result)->callbacks = _map_->callbacks; for (size_t i = 0; i < _map_->capacity; i++) { struct hashbidimap_entry *scan = _map_->buffer[i][0]; if (scan && scan != ((void *)1)) { size_t tmp_key; size_t tmp_val; if (_map_->f_key->cpy) tmp_key = _map_->f_key->cpy(scan->key); else tmp_key = scan->key; if (_map_->f_val->cpy) tmp_val = _map_->f_val->cpy(scan->value); else tmp_val = scan->value; struct hashbidimap_entry *entry = hbm_impl_new_entry(result, tmp_key, tmp_val); hbm_impl_add_entry_to_key(result, entry); hbm_impl_add_entry_to_val(result, entry); result->count++; } } _map_->flag = CMC_FLAG_OK; return result; } _Bool hbm_equals(struct hashbidimap * _map1_, struct hashbidimap * _map2_) { _map1_->flag = CMC_FLAG_OK; _map2_->flag = CMC_FLAG_OK; if (_map1_->count != _map2_->count) return 0; struct hashbidimap *_mapA_; struct hashbidimap *_mapB_; if (_map1_->capacity < _map2_->capacity) { _mapA_ = _map1_; _mapB_ = _map2_; } else { _mapA_ = _map2_; _mapB_ = _map1_; } for (size_t i = 0; i < _mapA_->capacity; i++) { struct hashbidimap_entry *scan = _mapA_->buffer[i][0]; if (scan && scan != ((void *)1)) { struct hashbidimap_entry **entry_B = hbm_impl_get_entry_by_key(_mapB_, scan->key); if (!entry_B) return 0; if (_mapA_->f_val->cmp((*entry_B)->value, scan->value) != 0) return 0; } } return 1; } struct hashbidimap_iter * hbm_iter_new(struct hashbidimap * target) { struct hashbidimap_iter *iter = target->alloc->malloc(sizeof(struct hashbidimap_iter)); if (!iter) return ((void *)0); hbm_iter_init(iter, target); return iter; } void hbm_iter_free(struct hashbidimap_iter * iter) { iter->target->alloc->free(iter); } void hbm_iter_init(struct hashbidimap_iter * iter, struct hashbidimap * target) { memset(iter, 0, sizeof(struct hashbidimap_iter)); iter->target = target; iter->start = 1; iter->end = hbm_empty(target); if (!hbm_empty(target)) { for (size_t i = 0; i < target->capacity; i++) { struct hashbidimap_entry *entry = target->buffer[i][0]; if (entry && entry != ((void *)1)) { iter->first = i; break; } } iter->cursor = iter->first; for (size_t i = target->capacity; i > 0; i--) { struct hashbidimap_entry *entry = target->buffer[i - 1][0]; if (entry && entry != ((void *)1)) { iter->last = i - 1; break; } } } } _Bool hbm_iter_start(struct hashbidimap_iter * iter) { return hbm_empty(iter->target) || iter->start; } _Bool hbm_iter_end(struct hashbidimap_iter * iter) { return hbm_empty(iter->target) || iter->end; } void hbm_iter_to_start(struct hashbidimap_iter * iter) { if (!hbm_empty(iter->target)) { iter->cursor = iter->first; iter->index = 0; iter->start = 1; iter->end = 0; } } void hbm_iter_to_end(struct hashbidimap_iter * iter) { if (!hbm_empty(iter->target)) { iter->cursor = iter->last; iter->index = iter->target->count - 1; iter->start = 0; iter->end = 1; } } _Bool hbm_iter_next(struct hashbidimap_iter * iter) { if (iter->end) return 0; if (iter->index + 1 == iter->target->count) { iter->end = 1; return 0; } iter->start = hbm_empty(iter->target); struct hashbidimap_entry *scan = iter->target->buffer[iter->cursor][0]; iter->index++; while (1) { iter->cursor++; scan = iter->target->buffer[iter->cursor][0]; if (scan != ((void *)0) && scan != ((void *)1)) break; } return 1; } _Bool hbm_iter_prev(struct hashbidimap_iter * iter) { if (iter->start) return 0; if (iter->index == 0) { iter->start = 1; return 0; } iter->end = hbm_empty(iter->target); struct hashbidimap_entry *scan = iter->target->buffer[iter->cursor][0]; iter->index--; while (1) { iter->cursor--; scan = iter->target->buffer[iter->cursor][0]; if (scan != ((void *)0) && scan != ((void *)1)) break; } return 1; } _Bool hbm_iter_advance(struct hashbidimap_iter * iter, size_t steps) { if (iter->end) return 0; if (iter->index + 1 == iter->target->count) { iter->end = 1; return 0; } if (steps == 0 || iter->index + steps >= iter->target->count) return 0; for (size_t i = 0; i < steps; i++) hbm_iter_next(iter); return 1; } _Bool hbm_iter_rewind(struct hashbidimap_iter * iter, size_t steps) { if (iter->start) return 0; if (iter->index == 0) { iter->start = 1; return 0; } if (steps == 0 || iter->index < steps) return 0; for (size_t i = 0; i < steps; i++) hbm_iter_prev(iter); return 1; } _Bool hbm_iter_go_to(struct hashbidimap_iter * iter, size_t index) { if (index >= iter->target->count) return 0; if (iter->index > index) return hbm_iter_rewind(iter, iter->index - index); else if (iter->index < index) return hbm_iter_advance(iter, index - iter->index); return 1; } size_t hbm_iter_key(struct hashbidimap_iter * iter) { if (hbm_empty(iter->target)) { iter->target->flag = CMC_FLAG_EMPTY; return (size_t){ 0 }; } return iter->target->buffer[iter->cursor][0]->key; } size_t hbm_iter_value(struct hashbidimap_iter * iter) { if (hbm_empty(iter->target)) { iter->target->flag = CMC_FLAG_EMPTY; return (size_t){ 0 }; } return iter->target->buffer[iter->cursor][0]->value; } size_t hbm_iter_index(struct hashbidimap_iter * iter) { return iter->index; } static struct hashbidimap_entry * hbm_impl_new_entry(struct hashbidimap * _map_, size_t key, size_t value) { struct hashbidimap_entry *entry = _map_->alloc->malloc(sizeof(struct hashbidimap_entry)); if (!entry) return ((void *)0); entry->key = key; entry->value = value; entry->dist[0] = 0; entry->dist[1] = 0; entry->ref[0] = ((void *)0); entry->ref[1] = ((void *)0); return entry; } static struct hashbidimap_entry * *hbm_impl_get_entry_by_key(struct hashbidimap * _map_, size_t key) { size_t hash = _map_->f_key->hash(key); size_t pos = hash % _map_->capacity; struct hashbidimap_entry *target = _map_->buffer[pos][0]; while (target != ((void *)0)) { if (target != ((void *)1) && _map_->f_key->cmp(target->key, key) == 0) return &(_map_->buffer[pos % _map_->capacity][0]); pos++; target = _map_->buffer[pos % _map_->capacity][0]; } return ((void *)0); } static struct hashbidimap_entry * *hbm_impl_get_entry_by_val(struct hashbidimap * _map_, size_t val) { size_t hash = _map_->f_val->hash(val); size_t pos = hash % _map_->capacity; struct hashbidimap_entry *target = _map_->buffer[pos][1]; while (target != ((void *)0)) { if (target != ((void *)1) && _map_->f_val->cmp(target->value, val) == 0) return &(_map_->buffer[pos % _map_->capacity][1]); pos++; target = _map_->buffer[pos % _map_->capacity][1]; } return ((void *)0); } static struct hashbidimap_entry * *hbm_impl_add_entry_to_key(struct hashbidimap * _map_, struct hashbidimap_entry * entry) { struct hashbidimap_entry **to_return = ((void *)0); size_t hash = _map_->f_key->hash(entry->key); size_t original_pos = hash % _map_->capacity; size_t pos = original_pos; struct hashbidimap_entry **scan = &(_map_->buffer[hash % _map_->capacity][0]); if (*scan == ((void *)0)) { *scan = entry; entry->ref[0] = scan; return scan; } else { while (1) { pos++; scan = &(_map_->buffer[pos % _map_->capacity][0]); if (*scan == ((void *)0) || *scan == ((void *)1)) { if (!to_return) to_return = scan; *scan = entry; entry->ref[0] = scan; entry->dist[0] = pos - original_pos; return to_return; } else if ((*scan)->dist[0] < pos - original_pos) { if (!to_return) to_return = scan; size_t tmp_dist = (*scan)->dist[0]; entry->dist[0] = pos - original_pos; original_pos = pos - tmp_dist; entry->ref[0] = scan; struct hashbidimap_entry *_tmp_ = *scan; *scan = entry; entry = _tmp_; } } } return ((void *)0); } static struct hashbidimap_entry * *hbm_impl_add_entry_to_val(struct hashbidimap * _map_, struct hashbidimap_entry * entry) { struct hashbidimap_entry **to_return = ((void *)0); size_t hash = _map_->f_val->hash(entry->value); size_t original_pos = hash % _map_->capacity; size_t pos = original_pos; struct hashbidimap_entry **scan = &(_map_->buffer[hash % _map_->capacity][1]); if (*scan == ((void *)0)) { *scan = entry; entry->ref[1] = scan; return scan; } else { while (1) { pos++; scan = &(_map_->buffer[pos % _map_->capacity][1]); if (*scan == ((void *)0) || *scan == ((void *)1)) { if (!to_return) to_return = scan; *scan = entry; entry->ref[1] = scan; entry->dist[1] = pos - original_pos; return to_return; } else if ((*scan)->dist[1] < pos - original_pos) { if (!to_return) to_return = scan; size_t tmp_dist = (*scan)->dist[1]; entry->dist[1] = pos - original_pos; original_pos = pos - tmp_dist; entry->ref[1] = scan; struct hashbidimap_entry *_tmp_ = *scan; *scan = entry; entry = _tmp_; } } } return ((void *)0); } static size_t hbm_impl_calculate_size(size_t required) { const size_t count = sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]); if (cmc_hashtable_primes[count - 1] < required) return required; size_t i = 0; while (cmc_hashtable_primes[i] < required) i++; return cmc_hashtable_primes[i]; } static struct hashbidimap_iter hbm_impl_it_start(struct hashbidimap * _map_) { struct hashbidimap_iter iter; hbm_iter_init(&iter, _map_); return iter; } static struct hashbidimap_iter hbm_impl_it_end(struct hashbidimap * _map_) { struct hashbidimap_iter iter; hbm_iter_init(&iter, _map_); hbm_iter_to_end(&iter); return iter; } _Bool hbm_to_string(struct hashbidimap * _map_, FILE * fptr) { struct hashbidimap *m_ = _map_; return 0 <= fprintf(fptr, "struct %s<%s, %s> " "at %p { " "buffer:%p, " "capacity:%" "I64u" ", " "count:%" "I64u" ", " "load:%lf, " "flag:%d, " "f_key:%p, " "f_val:%p, " "alloc:%p, " "callbacks:%p }", "hashbidimap", "size_t", "size_t", m_, m_->buffer, m_->capacity, m_->count, m_->load, m_->flag, m_->f_key, m_->f_val, m_->alloc, (m_)->callbacks); } _Bool hbm_print(struct hashbidimap * _map_, FILE * fptr, const char *start, const char *separator, const char *end, const char *key_val_sep) { fprintf(fptr, "%s", start); size_t last = 0; for (size_t i = _map_->capacity; i > 0; i--) { struct hashbidimap_entry *entry = _map_->buffer[i - 1][0]; if (entry && entry != ((void *)1)) { last = i - 1; break; } } for (size_t i = 0; i < _map_->capacity; i++) { struct hashbidimap_entry *entry = _map_->buffer[i][0]; if (entry && entry != ((void *)1)) { if (!_map_->f_key->str(fptr, entry->key)) return 0; fprintf(fptr, "%s", key_val_sep); if (!_map_->f_val->str(fptr, entry->value)) return 0; if (i + 1 < last) fprintf(fptr, "%s", separator); } } fprintf(fptr, "%s", end); return 1; } - - \ No newline at end of file +static struct hashbidimap_entry *hbm_impl_new_entry(struct hashbidimap *_map_, size_t key, size_t value); +static struct hashbidimap_entry **hbm_impl_get_entry_by_key(struct hashbidimap *_map_, size_t key); +static struct hashbidimap_entry **hbm_impl_get_entry_by_val(struct hashbidimap *_map_, size_t val); +static struct hashbidimap_entry **hbm_impl_add_entry_to_key(struct hashbidimap *_map_, struct hashbidimap_entry *entry); +static struct hashbidimap_entry **hbm_impl_add_entry_to_val(struct hashbidimap *_map_, struct hashbidimap_entry *entry); +static size_t hbm_impl_calculate_size(size_t required); +static struct hashbidimap_iter hbm_impl_it_start(struct hashbidimap *_map_); +static struct hashbidimap_iter hbm_impl_it_end(struct hashbidimap *_map_); +struct hashbidimap *hbm_new(size_t capacity, double load, struct hashbidimap_fkey *f_key, + struct hashbidimap_fval *f_val) +{ + return hbm_new_custom(capacity, load, f_key, f_val, ((void *)0), ((void *)0)); +} +struct hashbidimap *hbm_new_custom(size_t capacity, double load, struct hashbidimap_fkey *f_key, + struct hashbidimap_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks) +{ + ; + if (capacity == 0 || load <= 0 || load >= 1) + return ((void *)0); + if (capacity >= 0xffffffffffffffffULL * load) + return ((void *)0); + if (!f_key || !f_val) + return ((void *)0); + size_t real_capacity = hbm_impl_calculate_size(capacity / load); + if (!alloc) + alloc = &cmc_alloc_node_default; + struct hashbidimap *_map_ = alloc->malloc(sizeof(struct hashbidimap)); + if (!_map_) + return ((void *)0); + _map_->buffer = alloc->calloc(real_capacity, sizeof(struct hashbidimap_entry *[2])); + if (!_map_->buffer) + { + alloc->free(_map_->buffer); + alloc->free(_map_); + return ((void *)0); + } + _map_->count = 0; + _map_->capacity = real_capacity; + _map_->load = load; + _map_->flag = CMC_FLAG_OK; + _map_->f_key = f_key; + _map_->f_val = f_val; + _map_->flag = CMC_FLAG_OK; + _map_->alloc = alloc; + (_map_)->callbacks = callbacks; + _map_->it_start = hbm_impl_it_start; + _map_->it_end = hbm_impl_it_end; + return _map_; +} +void hbm_clear(struct hashbidimap *_map_) +{ + for (size_t i = 0; i < _map_->capacity; i++) + { + struct hashbidimap_entry *entry = _map_->buffer[i][0]; + if (entry && entry != ((void *)1)) + { + if (_map_->f_key->free) + _map_->f_key->free(entry->key); + if (_map_->f_val->free) + _map_->f_val->free(entry->value); + _map_->alloc->free(entry); + } + _map_->buffer[i][0] = ((void *)0); + _map_->buffer[i][1] = ((void *)0); + } + _map_->count = 0; + _map_->flag = CMC_FLAG_OK; +} +void hbm_free(struct hashbidimap *_map_) +{ + hbm_clear(_map_); + _map_->alloc->free(_map_->buffer); + _map_->alloc->free(_map_); +} +void hbm_customize(struct hashbidimap *_map_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks) +{ + ; + if (!alloc) + _map_->alloc = &cmc_alloc_node_default; + else + _map_->alloc = alloc; + (_map_)->callbacks = callbacks; + _map_->flag = CMC_FLAG_OK; +} +_Bool hbm_insert(struct hashbidimap *_map_, size_t key, size_t value) +{ + if (hbm_full(_map_)) + { + if (!hbm_resize(_map_, _map_->capacity + 1)) + return 0; + } + if (hbm_impl_get_entry_by_key(_map_, key) != ((void *)0) || hbm_impl_get_entry_by_val(_map_, value) != ((void *)0)) + { + _map_->flag = CMC_FLAG_DUPLICATE; + return 0; + } + struct hashbidimap_entry *entry = hbm_impl_new_entry(_map_, key, value); + struct hashbidimap_entry **key_entry = hbm_impl_add_entry_to_key(_map_, entry); + struct hashbidimap_entry **val_entry = hbm_impl_add_entry_to_val(_map_, entry); + if (!key_entry || !val_entry) + { + if (key_entry) + *key_entry = ((void *)1); + if (val_entry) + *val_entry = ((void *)1); + _map_->alloc->free(entry); + _map_->flag = CMC_FLAG_ERROR; + return 0; + } + _map_->count++; + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->create) + (_map_)->callbacks->create(); + ; + return 1; +} +_Bool hbm_update_key(struct hashbidimap *_map_, size_t val, size_t new_key) +{ + if (hbm_empty(_map_)) + { + _map_->flag = CMC_FLAG_EMPTY; + return 0; + } + struct hashbidimap_entry **key_entry, **val_entry; + val_entry = hbm_impl_get_entry_by_val(_map_, val); + if (!val_entry) + { + _map_->flag = CMC_FLAG_NOT_FOUND; + return 0; + } + if (_map_->f_key->cmp(new_key, (*val_entry)->key) == 0) + goto success; + if (hbm_impl_get_entry_by_key(_map_, new_key) != ((void *)0)) + { + _map_->flag = CMC_FLAG_DUPLICATE; + return 0; + } + key_entry = (*val_entry)->ref[0]; + if (!key_entry || *key_entry != *val_entry) + { + _map_->flag = CMC_FLAG_ERROR; + return 0; + } + struct hashbidimap_entry *to_add = *key_entry; + size_t tmp_key = to_add->key; + to_add->key = new_key; + *key_entry = ((void *)1); + if (!hbm_impl_add_entry_to_key(_map_, to_add)) + { + to_add->key = tmp_key; + *key_entry = to_add; + _map_->flag = CMC_FLAG_ERROR; + return 0; + } +success: + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->update) + (_map_)->callbacks->update(); + ; + return 1; +} +_Bool hbm_update_val(struct hashbidimap *_map_, size_t key, size_t new_val) +{ + if (hbm_empty(_map_)) + { + _map_->flag = CMC_FLAG_EMPTY; + return 0; + } + struct hashbidimap_entry **key_entry, **val_entry; + key_entry = hbm_impl_get_entry_by_key(_map_, key); + if (!key_entry) + { + _map_->flag = CMC_FLAG_NOT_FOUND; + return 0; + } + if (_map_->f_val->cmp(new_val, (*key_entry)->value) == 0) + goto success; + if (hbm_impl_get_entry_by_val(_map_, new_val) != ((void *)0)) + { + _map_->flag = CMC_FLAG_DUPLICATE; + return 0; + } + val_entry = (*key_entry)->ref[1]; + if (!val_entry || *val_entry != *key_entry) + { + _map_->flag = CMC_FLAG_ERROR; + return 0; + } + struct hashbidimap_entry *to_add = *val_entry; + size_t tmp_val = to_add->value; + to_add->value = new_val; + *val_entry = ((void *)1); + if (!hbm_impl_add_entry_to_val(_map_, to_add)) + { + to_add->value = tmp_val; + *val_entry = to_add; + _map_->flag = CMC_FLAG_ERROR; + return 0; + } +success: + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->update) + (_map_)->callbacks->update(); + ; + return 1; +} +_Bool hbm_remove_by_key(struct hashbidimap *_map_, size_t key, size_t *out_key, size_t *out_val) +{ + if (hbm_empty(_map_)) + { + _map_->flag = CMC_FLAG_EMPTY; + return 0; + } + struct hashbidimap_entry **key_entry, **val_entry; + key_entry = hbm_impl_get_entry_by_key(_map_, key); + if (!key_entry) + { + _map_->flag = CMC_FLAG_NOT_FOUND; + return 0; + } + val_entry = (*key_entry)->ref[1]; + if (!val_entry || *val_entry != *key_entry) + { + _map_->flag = CMC_FLAG_ERROR; + return 0; + } + if (out_key) + *out_key = (*key_entry)->key; + if (out_val) + *out_val = (*key_entry)->value; + _map_->alloc->free(*key_entry); + *key_entry = ((void *)1); + *val_entry = ((void *)1); + _map_->count--; + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->delete) + (_map_)->callbacks->delete (); + ; + return 1; +} +_Bool hbm_remove_by_val(struct hashbidimap *_map_, size_t val, size_t *out_key, size_t *out_val) +{ + if (hbm_empty(_map_)) + { + _map_->flag = CMC_FLAG_EMPTY; + return 0; + } + struct hashbidimap_entry **key_entry, **val_entry; + val_entry = hbm_impl_get_entry_by_val(_map_, val); + if (!val_entry) + { + _map_->flag = CMC_FLAG_NOT_FOUND; + return 0; + } + key_entry = (*val_entry)->ref[0]; + if (!key_entry || *key_entry != *val_entry) + { + _map_->flag = CMC_FLAG_ERROR; + return 0; + } + if (out_key) + *out_key = (*val_entry)->key; + if (out_val) + *out_val = (*val_entry)->value; + _map_->alloc->free(*val_entry); + *key_entry = ((void *)1); + *val_entry = ((void *)1); + _map_->count--; + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->delete) + (_map_)->callbacks->delete (); + ; + return 1; +} +size_t hbm_get_key(struct hashbidimap *_map_, size_t val) +{ + struct hashbidimap_entry **entry = hbm_impl_get_entry_by_val(_map_, val); + if (!entry) + { + _map_->flag = CMC_FLAG_NOT_FOUND; + return (size_t){ 0 }; + } + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->read) + (_map_)->callbacks->read(); + ; + return (*entry)->key; +} +size_t hbm_get_val(struct hashbidimap *_map_, size_t key) +{ + struct hashbidimap_entry **entry = hbm_impl_get_entry_by_key(_map_, key); + if (!entry) + { + _map_->flag = CMC_FLAG_NOT_FOUND; + return (size_t){ 0 }; + } + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->read) + (_map_)->callbacks->read(); + ; + return (*entry)->value; +} +_Bool hbm_contains_key(struct hashbidimap *_map_, size_t key) +{ + _map_->flag = CMC_FLAG_OK; + _Bool result = hbm_impl_get_entry_by_key(_map_, key) != ((void *)0); + if ((_map_)->callbacks && (_map_)->callbacks->read) + (_map_)->callbacks->read(); + ; + return result; +} +_Bool hbm_contains_val(struct hashbidimap *_map_, size_t val) +{ + _map_->flag = CMC_FLAG_OK; + _Bool result = hbm_impl_get_entry_by_val(_map_, val) != ((void *)0); + if ((_map_)->callbacks && (_map_)->callbacks->read) + (_map_)->callbacks->read(); + ; + return result; +} +_Bool hbm_empty(struct hashbidimap *_map_) +{ + return _map_->count == 0; +} +_Bool hbm_full(struct hashbidimap *_map_) +{ + return (double)_map_->capacity * _map_->load <= (double)_map_->count; +} +size_t hbm_count(struct hashbidimap *_map_) +{ + return _map_->count; +} +size_t hbm_capacity(struct hashbidimap *_map_) +{ + return _map_->capacity; +} +double hbm_load(struct hashbidimap *_map_) +{ + return _map_->load; +} +int hbm_flag(struct hashbidimap *_map_) +{ + return _map_->flag; +} +_Bool hbm_resize(struct hashbidimap *_map_, size_t capacity) +{ + _map_->flag = CMC_FLAG_OK; + if (_map_->capacity == capacity) + goto success; + if (_map_->capacity > capacity / _map_->load) + goto success; + if (capacity >= 0xffffffffffffffffULL * _map_->load) + { + _map_->flag = CMC_FLAG_ERROR; + return 0; + } + size_t new_cap = hbm_impl_calculate_size(capacity); + if (new_cap < _map_->count / _map_->load) + { + _map_->flag = CMC_FLAG_INVALID; + return 0; + } + struct hashbidimap *_new_map_ = + hbm_new_custom(capacity, _map_->load, _map_->f_key, _map_->f_val, _map_->alloc, ((void *)0)); + if (!_new_map_) + { + _map_->flag = CMC_FLAG_ALLOC; + return 0; + } + for (size_t i = 0; i < _map_->capacity; i++) + { + struct hashbidimap_entry *scan = _map_->buffer[i][0]; + if (scan && scan != ((void *)1)) + { + struct hashbidimap_entry **e1 = hbm_impl_add_entry_to_key(_new_map_, scan); + struct hashbidimap_entry **e2 = hbm_impl_add_entry_to_val(_new_map_, scan); + if (!e1 || !e2) + { + _new_map_->f_key = &(struct hashbidimap_fkey){ ((void *)0) }; + _new_map_->f_val = &(struct hashbidimap_fval){ ((void *)0) }; + _map_->alloc->free(_new_map_->buffer); + _map_->alloc->free(_new_map_); + _map_->flag = CMC_FLAG_ERROR; + return 0; + } + _new_map_->count++; + } + } + if (_map_->count != _new_map_->count) + { + _new_map_->f_key = &(struct hashbidimap_fkey){ ((void *)0) }; + _new_map_->f_val = &(struct hashbidimap_fval){ ((void *)0) }; + _map_->alloc->free(_new_map_->buffer); + _map_->alloc->free(_new_map_); + _map_->flag = CMC_FLAG_ERROR; + return 0; + } + struct hashbidimap_entry *(*tmp_buff)[2] = _map_->buffer; + _map_->buffer = _new_map_->buffer; + _map_->capacity = _new_map_->capacity; + _map_->alloc->free(tmp_buff); + _map_->alloc->free(_new_map_); +success: + if ((_map_)->callbacks && (_map_)->callbacks->resize) + (_map_)->callbacks->resize(); + ; + return 1; +} +struct hashbidimap *hbm_copy_of(struct hashbidimap *_map_) +{ + struct hashbidimap *result = hbm_new_custom(_map_->capacity * _map_->load, _map_->load, _map_->f_key, _map_->f_val, + _map_->alloc, ((void *)0)); + if (!result) + { + _map_->flag = CMC_FLAG_ERROR; + return ((void *)0); + } + (result)->callbacks = _map_->callbacks; + for (size_t i = 0; i < _map_->capacity; i++) + { + struct hashbidimap_entry *scan = _map_->buffer[i][0]; + if (scan && scan != ((void *)1)) + { + size_t tmp_key; + size_t tmp_val; + if (_map_->f_key->cpy) + tmp_key = _map_->f_key->cpy(scan->key); + else + tmp_key = scan->key; + if (_map_->f_val->cpy) + tmp_val = _map_->f_val->cpy(scan->value); + else + tmp_val = scan->value; + struct hashbidimap_entry *entry = hbm_impl_new_entry(result, tmp_key, tmp_val); + hbm_impl_add_entry_to_key(result, entry); + hbm_impl_add_entry_to_val(result, entry); + result->count++; + } + } + _map_->flag = CMC_FLAG_OK; + return result; +} +_Bool hbm_equals(struct hashbidimap *_map1_, struct hashbidimap *_map2_) +{ + _map1_->flag = CMC_FLAG_OK; + _map2_->flag = CMC_FLAG_OK; + if (_map1_->count != _map2_->count) + return 0; + struct hashbidimap *_mapA_; + struct hashbidimap *_mapB_; + if (_map1_->capacity < _map2_->capacity) + { + _mapA_ = _map1_; + _mapB_ = _map2_; + } + else + { + _mapA_ = _map2_; + _mapB_ = _map1_; + } + for (size_t i = 0; i < _mapA_->capacity; i++) + { + struct hashbidimap_entry *scan = _mapA_->buffer[i][0]; + if (scan && scan != ((void *)1)) + { + struct hashbidimap_entry **entry_B = hbm_impl_get_entry_by_key(_mapB_, scan->key); + if (!entry_B) + return 0; + if (_mapA_->f_val->cmp((*entry_B)->value, scan->value) != 0) + return 0; + } + } + return 1; +} +struct hashbidimap_iter *hbm_iter_new(struct hashbidimap *target) +{ + struct hashbidimap_iter *iter = target->alloc->malloc(sizeof(struct hashbidimap_iter)); + if (!iter) + return ((void *)0); + hbm_iter_init(iter, target); + return iter; +} +void hbm_iter_free(struct hashbidimap_iter *iter) +{ + iter->target->alloc->free(iter); +} +void hbm_iter_init(struct hashbidimap_iter *iter, struct hashbidimap *target) +{ + memset(iter, 0, sizeof(struct hashbidimap_iter)); + iter->target = target; + iter->start = 1; + iter->end = hbm_empty(target); + if (!hbm_empty(target)) + { + for (size_t i = 0; i < target->capacity; i++) + { + struct hashbidimap_entry *entry = target->buffer[i][0]; + if (entry && entry != ((void *)1)) + { + iter->first = i; + break; + } + } + iter->cursor = iter->first; + for (size_t i = target->capacity; i > 0; i--) + { + struct hashbidimap_entry *entry = target->buffer[i - 1][0]; + if (entry && entry != ((void *)1)) + { + iter->last = i - 1; + break; + } + } + } +} +_Bool hbm_iter_start(struct hashbidimap_iter *iter) +{ + return hbm_empty(iter->target) || iter->start; +} +_Bool hbm_iter_end(struct hashbidimap_iter *iter) +{ + return hbm_empty(iter->target) || iter->end; +} +void hbm_iter_to_start(struct hashbidimap_iter *iter) +{ + if (!hbm_empty(iter->target)) + { + iter->cursor = iter->first; + iter->index = 0; + iter->start = 1; + iter->end = 0; + } +} +void hbm_iter_to_end(struct hashbidimap_iter *iter) +{ + if (!hbm_empty(iter->target)) + { + iter->cursor = iter->last; + iter->index = iter->target->count - 1; + iter->start = 0; + iter->end = 1; + } +} +_Bool hbm_iter_next(struct hashbidimap_iter *iter) +{ + if (iter->end) + return 0; + if (iter->index + 1 == iter->target->count) + { + iter->end = 1; + return 0; + } + iter->start = hbm_empty(iter->target); + struct hashbidimap_entry *scan = iter->target->buffer[iter->cursor][0]; + iter->index++; + while (1) + { + iter->cursor++; + scan = iter->target->buffer[iter->cursor][0]; + if (scan != ((void *)0) && scan != ((void *)1)) + break; + } + return 1; +} +_Bool hbm_iter_prev(struct hashbidimap_iter *iter) +{ + if (iter->start) + return 0; + if (iter->index == 0) + { + iter->start = 1; + return 0; + } + iter->end = hbm_empty(iter->target); + struct hashbidimap_entry *scan = iter->target->buffer[iter->cursor][0]; + iter->index--; + while (1) + { + iter->cursor--; + scan = iter->target->buffer[iter->cursor][0]; + if (scan != ((void *)0) && scan != ((void *)1)) + break; + } + return 1; +} +_Bool hbm_iter_advance(struct hashbidimap_iter *iter, size_t steps) +{ + if (iter->end) + return 0; + if (iter->index + 1 == iter->target->count) + { + iter->end = 1; + return 0; + } + if (steps == 0 || iter->index + steps >= iter->target->count) + return 0; + for (size_t i = 0; i < steps; i++) + hbm_iter_next(iter); + return 1; +} +_Bool hbm_iter_rewind(struct hashbidimap_iter *iter, size_t steps) +{ + if (iter->start) + return 0; + if (iter->index == 0) + { + iter->start = 1; + return 0; + } + if (steps == 0 || iter->index < steps) + return 0; + for (size_t i = 0; i < steps; i++) + hbm_iter_prev(iter); + return 1; +} +_Bool hbm_iter_go_to(struct hashbidimap_iter *iter, size_t index) +{ + if (index >= iter->target->count) + return 0; + if (iter->index > index) + return hbm_iter_rewind(iter, iter->index - index); + else if (iter->index < index) + return hbm_iter_advance(iter, index - iter->index); + return 1; +} +size_t hbm_iter_key(struct hashbidimap_iter *iter) +{ + if (hbm_empty(iter->target)) + { + iter->target->flag = CMC_FLAG_EMPTY; + return (size_t){ 0 }; + } + return iter->target->buffer[iter->cursor][0]->key; +} +size_t hbm_iter_value(struct hashbidimap_iter *iter) +{ + if (hbm_empty(iter->target)) + { + iter->target->flag = CMC_FLAG_EMPTY; + return (size_t){ 0 }; + } + return iter->target->buffer[iter->cursor][0]->value; +} +size_t hbm_iter_index(struct hashbidimap_iter *iter) +{ + return iter->index; +} +static struct hashbidimap_entry *hbm_impl_new_entry(struct hashbidimap *_map_, size_t key, size_t value) +{ + struct hashbidimap_entry *entry = _map_->alloc->malloc(sizeof(struct hashbidimap_entry)); + if (!entry) + return ((void *)0); + entry->key = key; + entry->value = value; + entry->dist[0] = 0; + entry->dist[1] = 0; + entry->ref[0] = ((void *)0); + entry->ref[1] = ((void *)0); + return entry; +} +static struct hashbidimap_entry **hbm_impl_get_entry_by_key(struct hashbidimap *_map_, size_t key) +{ + size_t hash = _map_->f_key->hash(key); + size_t pos = hash % _map_->capacity; + struct hashbidimap_entry *target = _map_->buffer[pos][0]; + while (target != ((void *)0)) + { + if (target != ((void *)1) && _map_->f_key->cmp(target->key, key) == 0) + return &(_map_->buffer[pos % _map_->capacity][0]); + pos++; + target = _map_->buffer[pos % _map_->capacity][0]; + } + return ((void *)0); +} +static struct hashbidimap_entry **hbm_impl_get_entry_by_val(struct hashbidimap *_map_, size_t val) +{ + size_t hash = _map_->f_val->hash(val); + size_t pos = hash % _map_->capacity; + struct hashbidimap_entry *target = _map_->buffer[pos][1]; + while (target != ((void *)0)) + { + if (target != ((void *)1) && _map_->f_val->cmp(target->value, val) == 0) + return &(_map_->buffer[pos % _map_->capacity][1]); + pos++; + target = _map_->buffer[pos % _map_->capacity][1]; + } + return ((void *)0); +} +static struct hashbidimap_entry **hbm_impl_add_entry_to_key(struct hashbidimap *_map_, struct hashbidimap_entry *entry) +{ + struct hashbidimap_entry **to_return = ((void *)0); + size_t hash = _map_->f_key->hash(entry->key); + size_t original_pos = hash % _map_->capacity; + size_t pos = original_pos; + struct hashbidimap_entry **scan = &(_map_->buffer[hash % _map_->capacity][0]); + if (*scan == ((void *)0)) + { + *scan = entry; + entry->ref[0] = scan; + return scan; + } + else + { + while (1) + { + pos++; + scan = &(_map_->buffer[pos % _map_->capacity][0]); + if (*scan == ((void *)0) || *scan == ((void *)1)) + { + if (!to_return) + to_return = scan; + *scan = entry; + entry->ref[0] = scan; + entry->dist[0] = pos - original_pos; + return to_return; + } + else if ((*scan)->dist[0] < pos - original_pos) + { + if (!to_return) + to_return = scan; + size_t tmp_dist = (*scan)->dist[0]; + entry->dist[0] = pos - original_pos; + original_pos = pos - tmp_dist; + entry->ref[0] = scan; + struct hashbidimap_entry *_tmp_ = *scan; + *scan = entry; + entry = _tmp_; + } + } + } + return ((void *)0); +} +static struct hashbidimap_entry **hbm_impl_add_entry_to_val(struct hashbidimap *_map_, struct hashbidimap_entry *entry) +{ + struct hashbidimap_entry **to_return = ((void *)0); + size_t hash = _map_->f_val->hash(entry->value); + size_t original_pos = hash % _map_->capacity; + size_t pos = original_pos; + struct hashbidimap_entry **scan = &(_map_->buffer[hash % _map_->capacity][1]); + if (*scan == ((void *)0)) + { + *scan = entry; + entry->ref[1] = scan; + return scan; + } + else + { + while (1) + { + pos++; + scan = &(_map_->buffer[pos % _map_->capacity][1]); + if (*scan == ((void *)0) || *scan == ((void *)1)) + { + if (!to_return) + to_return = scan; + *scan = entry; + entry->ref[1] = scan; + entry->dist[1] = pos - original_pos; + return to_return; + } + else if ((*scan)->dist[1] < pos - original_pos) + { + if (!to_return) + to_return = scan; + size_t tmp_dist = (*scan)->dist[1]; + entry->dist[1] = pos - original_pos; + original_pos = pos - tmp_dist; + entry->ref[1] = scan; + struct hashbidimap_entry *_tmp_ = *scan; + *scan = entry; + entry = _tmp_; + } + } + } + return ((void *)0); +} +static size_t hbm_impl_calculate_size(size_t required) +{ + const size_t count = sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]); + if (cmc_hashtable_primes[count - 1] < required) + return required; + size_t i = 0; + while (cmc_hashtable_primes[i] < required) + i++; + return cmc_hashtable_primes[i]; +} +static struct hashbidimap_iter hbm_impl_it_start(struct hashbidimap *_map_) +{ + struct hashbidimap_iter iter; + hbm_iter_init(&iter, _map_); + return iter; +} +static struct hashbidimap_iter hbm_impl_it_end(struct hashbidimap *_map_) +{ + struct hashbidimap_iter iter; + hbm_iter_init(&iter, _map_); + hbm_iter_to_end(&iter); + return iter; +} +_Bool hbm_to_string(struct hashbidimap *_map_, FILE *fptr) +{ + struct hashbidimap *m_ = _map_; + return 0 <= fprintf(fptr, + "struct %s<%s, %s> " + "at %p { " + "buffer:%p, " + "capacity:%" + "I64u" + ", " + "count:%" + "I64u" + ", " + "load:%lf, " + "flag:%d, " + "f_key:%p, " + "f_val:%p, " + "alloc:%p, " + "callbacks:%p }", + "hashbidimap", "size_t", "size_t", m_, m_->buffer, m_->capacity, m_->count, m_->load, m_->flag, + m_->f_key, m_->f_val, m_->alloc, (m_)->callbacks); +} +_Bool hbm_print(struct hashbidimap *_map_, FILE *fptr, const char *start, const char *separator, const char *end, + const char *key_val_sep) +{ + fprintf(fptr, "%s", start); + size_t last = 0; + for (size_t i = _map_->capacity; i > 0; i--) + { + struct hashbidimap_entry *entry = _map_->buffer[i - 1][0]; + if (entry && entry != ((void *)1)) + { + last = i - 1; + break; + } + } + for (size_t i = 0; i < _map_->capacity; i++) + { + struct hashbidimap_entry *entry = _map_->buffer[i][0]; + if (entry && entry != ((void *)1)) + { + if (!_map_->f_key->str(fptr, entry->key)) + return 0; + fprintf(fptr, "%s", key_val_sep); + if (!_map_->f_val->str(fptr, entry->value)) + return 0; + if (i + 1 < last) + fprintf(fptr, "%s", separator); + } + } + fprintf(fptr, "%s", end); + return 1; +} diff --git a/tests/src/tst_cmc_hashmap.c b/tests/src/tst_cmc_hashmap.c index 19773cf..8135d58 100644 --- a/tests/src/tst_cmc_hashmap.c +++ b/tests/src/tst_cmc_hashmap.c @@ -1,7 +1,788 @@ - #include "tst_cmc_hashmap.h" +#include "tst_cmc_hashmap.h" - - static struct hashmap_entry * hm_impl_get_entry(struct hashmap * _map_, size_t key); static size_t hm_impl_calculate_size(size_t required); struct hashmap *hm_new(size_t capacity, double load, struct hashmap_fkey * f_key, struct hashmap_fval * f_val) { return hm_new_custom(capacity, load, f_key, f_val, ((void *)0), ((void *)0)); } struct hashmap *hm_new_custom(size_t capacity, double load, struct hashmap_fkey * f_key, struct hashmap_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (capacity == 0 || load <= 0 || load >= 1) return ((void *)0); if (capacity >= 0xffffffffffffffffULL * load) return ((void *)0); if (!f_key || !f_val) return ((void *)0); size_t real_capacity = hm_impl_calculate_size(capacity / load); if (!alloc) alloc = &cmc_alloc_node_default; struct hashmap *_map_ = alloc->malloc(sizeof(struct hashmap)); if (!_map_) return ((void *)0); _map_->buffer = alloc->calloc(real_capacity, sizeof(struct hashmap_entry)); if (!_map_->buffer) { alloc->free(_map_); return ((void *)0); } _map_->count = 0; _map_->capacity = real_capacity; _map_->load = load; _map_->flag = CMC_FLAG_OK; _map_->f_key = f_key; _map_->f_val = f_val; _map_->alloc = alloc; (_map_)->callbacks = callbacks; return _map_; } void hm_clear(struct hashmap * _map_) { if (_map_->f_key->free || _map_->f_val->free) { for (size_t i = 0; i < _map_->capacity; i++) { struct hashmap_entry *entry = &(_map_->buffer[i]); if (entry->state == CMC_ES_FILLED) { if (_map_->f_key->free) _map_->f_key->free(entry->key); if (_map_->f_val->free) _map_->f_val->free(entry->value); } } } memset(_map_->buffer, 0, sizeof(struct hashmap_entry) * _map_->capacity); _map_->count = 0; _map_->flag = CMC_FLAG_OK; } void hm_free(struct hashmap * _map_) { if (_map_->f_key->free || _map_->f_val->free) { for (size_t i = 0; i < _map_->capacity; i++) { struct hashmap_entry *entry = &(_map_->buffer[i]); if (entry->state == CMC_ES_FILLED) { if (_map_->f_key->free) _map_->f_key->free(entry->key); if (_map_->f_val->free) _map_->f_val->free(entry->value); } } } _map_->alloc->free(_map_->buffer); _map_->alloc->free(_map_); } void hm_customize(struct hashmap * _map_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (!alloc) _map_->alloc = &cmc_alloc_node_default; else _map_->alloc = alloc; (_map_)->callbacks = callbacks; _map_->flag = CMC_FLAG_OK; } _Bool hm_insert(struct hashmap * _map_, size_t key, size_t value) { if (hm_full(_map_)) { if (!hm_resize(_map_, _map_->capacity + 1)) return 0; } if (hm_impl_get_entry(_map_, key) != ((void *)0)) { _map_->flag = CMC_FLAG_DUPLICATE; return 0; } size_t hash = _map_->f_key->hash(key); size_t original_pos = hash % _map_->capacity; size_t pos = original_pos; struct hashmap_entry *target = &(_map_->buffer[pos]); if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) { target->key = key; target->value = value; target->dist = 0; target->state = CMC_ES_FILLED; } else { while (1) { pos++; target = &(_map_->buffer[pos % _map_->capacity]); if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) { target->key = key; target->value = value; target->dist = pos - original_pos; target->state = CMC_ES_FILLED; break; } else if (target->dist < pos - original_pos) { size_t tmp_k = target->key; size_t tmp_v = target->value; size_t tmp_dist = target->dist; target->key = key; target->value = value; target->dist = pos - original_pos; key = tmp_k; value = tmp_v; original_pos = pos - tmp_dist; } } } _map_->count++; _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->create) (_map_)->callbacks->create();; return 1; } _Bool hm_update(struct hashmap * _map_, size_t key, size_t new_value, size_t * old_value) { if (hm_empty(_map_)) { _map_->flag = CMC_FLAG_EMPTY; return 0; } struct hashmap_entry *entry = hm_impl_get_entry(_map_, key); if (!entry) { _map_->flag = CMC_FLAG_NOT_FOUND; return 0; } if (old_value) *old_value = entry->value; entry->value = new_value; _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->update) (_map_)->callbacks->update();; return 1; } _Bool hm_remove(struct hashmap * _map_, size_t key, size_t * out_value) { if (hm_empty(_map_)) { _map_->flag = CMC_FLAG_EMPTY; return 0; } struct hashmap_entry *result = hm_impl_get_entry(_map_, key); if (result == ((void *)0)) { _map_->flag = CMC_FLAG_NOT_FOUND; return 0; } if (out_value) *out_value = result->value; result->key = (size_t){ 0 }; result->value = (size_t){ 0 }; result->dist = 0; result->state = CMC_ES_DELETED; _map_->count--; _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->delete) (_map_)->callbacks->delete();; return 1; } _Bool hm_max(struct hashmap * _map_, size_t * key, size_t * value) { if (hm_empty(_map_)) { _map_->flag = CMC_FLAG_EMPTY; return 0; } _Bool first = 1; size_t max_key = (size_t){ 0 }; size_t max_val = (size_t){ 0 }; for (size_t i = 0; i < _map_->capacity; i++) { if (_map_->buffer[i].state == CMC_ES_FILLED) { if (first) { max_key = _map_->buffer[i].key; max_val = _map_->buffer[i].value; first = 0; } else if (_map_->f_key->cmp(_map_->buffer[i].key, max_key) > 0) { max_key = _map_->buffer[i].key; max_val = _map_->buffer[i].value; } } } if (key) *key = max_key; if (value) *value = max_val; _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->read) (_map_)->callbacks->read();; return 1; } _Bool hm_min(struct hashmap * _map_, size_t * key, size_t * value) { if (hm_empty(_map_)) { _map_->flag = CMC_FLAG_EMPTY; return 0; } _Bool first = 1; size_t min_key = (size_t){ 0 }; size_t min_val = (size_t){ 0 }; for (size_t i = 0; i < _map_->capacity; i++) { if (_map_->buffer[i].state == CMC_ES_FILLED) { if (first) { min_key = _map_->buffer[i].key; min_val = _map_->buffer[i].value; first = 0; } else if (_map_->f_key->cmp(_map_->buffer[i].key, min_key) < 0) { min_key = _map_->buffer[i].key; min_val = _map_->buffer[i].value; } } } if (key) *key = min_key; if (value) *value = min_val; _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->read) (_map_)->callbacks->read();; return 1; } size_t hm_get(struct hashmap * _map_, size_t key) { if (hm_empty(_map_)) { _map_->flag = CMC_FLAG_EMPTY; return (size_t){ 0 }; } struct hashmap_entry *entry = hm_impl_get_entry(_map_, key); if (!entry) { _map_->flag = CMC_FLAG_NOT_FOUND; return (size_t){ 0 }; } _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->read) (_map_)->callbacks->read();; return entry->value; } size_t *hm_get_ref(struct hashmap * _map_, size_t key) { if (hm_empty(_map_)) { _map_->flag = CMC_FLAG_EMPTY; return ((void *)0); } struct hashmap_entry *entry = hm_impl_get_entry(_map_, key); if (!entry) { _map_->flag = CMC_FLAG_NOT_FOUND; return ((void *)0); } _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->read) (_map_)->callbacks->read();; return &(entry->value); } _Bool hm_contains(struct hashmap * _map_, size_t key) { _map_->flag = CMC_FLAG_OK; _Bool result = hm_impl_get_entry(_map_, key) != ((void *)0); if ((_map_)->callbacks && (_map_)->callbacks->read) (_map_)->callbacks->read();; return result; } _Bool hm_empty(struct hashmap * _map_) { return _map_->count == 0; } _Bool hm_full(struct hashmap * _map_) { return (double)_map_->capacity * _map_->load <= (double)_map_->count; } size_t hm_count(struct hashmap * _map_) { return _map_->count; } size_t hm_capacity(struct hashmap * _map_) { return _map_->capacity; } double hm_load(struct hashmap * _map_) { return _map_->load; } int hm_flag(struct hashmap * _map_) { return _map_->flag; } _Bool hm_resize(struct hashmap * _map_, size_t capacity) { _map_->flag = CMC_FLAG_OK; if (_map_->capacity == capacity) goto success; if (_map_->capacity > capacity / _map_->load) goto success; if (capacity >= 0xffffffffffffffffULL * _map_->load) { _map_->flag = CMC_FLAG_ERROR; return 0; } size_t theoretical_size = hm_impl_calculate_size(capacity); if (theoretical_size < _map_->count / _map_->load) { _map_->flag = CMC_FLAG_INVALID; return 0; } struct hashmap *_new_map_ = hm_new_custom(capacity, _map_->load, _map_->f_key, _map_->f_val, _map_->alloc, ((void *)0)); if (!_new_map_) { _map_->flag = CMC_FLAG_ALLOC; return 0; } for (size_t i = 0; i < _map_->capacity; i++) { if (_map_->buffer[i].state == CMC_ES_FILLED) { size_t key = _map_->buffer[i].key; size_t value = _map_->buffer[i].value; hm_insert(_new_map_, key, value); } } if (_map_->count != _new_map_->count) { hm_free(_new_map_); _map_->flag = CMC_FLAG_ERROR; return 0; } struct hashmap_entry *tmp_b = _map_->buffer; _map_->buffer = _new_map_->buffer; _new_map_->buffer = tmp_b; size_t tmp_c = _map_->capacity; _map_->capacity = _new_map_->capacity; _new_map_->capacity = tmp_c; _new_map_->f_key = &(struct hashmap_fkey){ ((void *)0) }; _new_map_->f_val = &(struct hashmap_fval){ ((void *)0) }; hm_free(_new_map_); success: if ((_map_)->callbacks && (_map_)->callbacks->resize) (_map_)->callbacks->resize();; return 1; } struct hashmap *hm_copy_of(struct hashmap * _map_) { struct hashmap *result = hm_new_custom(_map_->capacity * _map_->load, _map_->load, _map_->f_key, _map_->f_val, _map_->alloc, ((void *)0)); if (!result) { _map_->flag = CMC_FLAG_ERROR; return ((void *)0); } (result)->callbacks = _map_->callbacks; if (_map_->f_key->cpy || _map_->f_val->cpy) { for (size_t i = 0; i < _map_->capacity; i++) { struct hashmap_entry *scan = &(_map_->buffer[i]); if (scan->state != CMC_ES_EMPTY) { struct hashmap_entry *target = &(result->buffer[i]); if (scan->state == CMC_ES_DELETED) target->state = CMC_ES_DELETED; else { target->state = scan->state; target->dist = scan->dist; if (_map_->f_key->cpy) target->key = _map_->f_key->cpy(scan->key); else target->key = scan->key; if (_map_->f_val->cpy) target->value = _map_->f_val->cpy(scan->value); else target->value = scan->value; } } } } else memcpy(result->buffer, _map_->buffer, sizeof(struct hashmap_entry) * _map_->capacity); result->count = _map_->count; _map_->flag = CMC_FLAG_OK; return result; } _Bool hm_equals(struct hashmap * _map1_, struct hashmap * _map2_) { _map1_->flag = CMC_FLAG_OK; _map2_->flag = CMC_FLAG_OK; if (_map1_->count != _map2_->count) return 0; struct hashmap *_map_a_; struct hashmap *_map_b_; _map_a_ = _map1_->capacity < _map2_->capacity ? _map1_ : _map2_; _map_b_ = _map_a_ == _map1_ ? _map2_ : _map1_; for (size_t i = 0; i < _map_a_->capacity; i++) { if (_map_a_->buffer[i].state == CMC_ES_FILLED) { struct hashmap_entry *entry_a = &(_map_a_->buffer[i]); struct hashmap_entry *entry_b = hm_impl_get_entry(_map_b_, entry_a->key); if (!entry_b) return 0; if (_map_a_->f_val->cmp(entry_a->value, entry_b->value) != 0) return 0; } } return 1; } static struct hashmap_entry * hm_impl_get_entry(struct hashmap * _map_, size_t key) { size_t hash = _map_->f_key->hash(key); size_t pos = hash % _map_->capacity; struct hashmap_entry *target = &(_map_->buffer[pos]); while (target->state == CMC_ES_FILLED || target->state == CMC_ES_DELETED) { if (_map_->f_key->cmp(target->key, key) == 0) return target; pos++; target = &(_map_->buffer[pos % _map_->capacity]); } return ((void *)0); } static size_t hm_impl_calculate_size(size_t required) { const size_t count = sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]); if (cmc_hashtable_primes[count - 1] < required) return required; size_t i = 0; while (cmc_hashtable_primes[i] < required) i++; return cmc_hashtable_primes[i]; } struct hashmap hm_init(size_t capacity, double load, struct hashmap_fkey * f_key, struct hashmap_fval * f_val) { return hm_init_custom(capacity, load, f_key, f_val, ((void *)0), ((void *)0)); } struct hashmap hm_init_custom(size_t capacity, double load, struct hashmap_fkey * f_key, struct hashmap_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; struct hashmap _map_ = { 0 }; if (capacity == 0 || load <= 0 || load >= 1) return _map_; if (capacity >= 0xffffffffffffffffULL * load) return _map_; if (!f_key || !f_val) return _map_; size_t real_capacity = hm_impl_calculate_size(capacity / load); if (!alloc) alloc = &cmc_alloc_node_default; _map_.buffer = alloc->calloc(real_capacity, sizeof(struct hashmap_entry)); if (!_map_.buffer) return _map_; _map_.count = 0; _map_.capacity = real_capacity; _map_.load = load; _map_.flag = CMC_FLAG_OK; _map_.f_key = f_key; _map_.f_val = f_val; _map_.alloc = alloc; (&_map_)->callbacks = callbacks; return _map_; } void hm_release(struct hashmap _map_) { if (_map_.f_key->free || _map_.f_val->free) { for (size_t i = 0; i < _map_.capacity; i++) { struct hashmap_entry *entry = &(_map_.buffer[i]); if (entry->state == CMC_ES_FILLED) { if (_map_.f_key->free) _map_.f_key->free(entry->key); if (_map_.f_val->free) _map_.f_val->free(entry->value); } } } _map_.alloc->free(_map_.buffer); } struct hashmap_iter hm_iter_start(struct hashmap * target) { struct hashmap_iter iter; iter.target = target; iter.cursor = 0; iter.index = 0; iter.first = 0; iter.last = 0; iter.start = 1; iter.end = hm_empty(target); if (!hm_empty(target)) { for (size_t i = 0; i < target->capacity; i++) { if (target->buffer[i].state == CMC_ES_FILLED) { iter.first = i; break; } } iter.cursor = iter.first; for (size_t i = target->capacity; i > 0; i--) { if (target->buffer[i - 1].state == CMC_ES_FILLED) { iter.last = i - 1; break; } } } return iter; } struct hashmap_iter hm_iter_end(struct hashmap * target) { struct hashmap_iter iter; iter.target = target; iter.cursor = 0; iter.index = 0; iter.first = 0; iter.last = 0; iter.start = hm_empty(target); iter.end = 1; if (!hm_empty(target)) { for (size_t i = 0; i < target->capacity; i++) { if (target->buffer[i].state == CMC_ES_FILLED) { iter.first = i; break; } } for (size_t i = target->capacity; i > 0; i--) { if (target->buffer[i - 1].state == CMC_ES_FILLED) { iter.last = i - 1; break; } } iter.cursor = iter.last; iter.index = target->count - 1; } return iter; } _Bool hm_iter_at_start(struct hashmap_iter * iter) { return hm_empty(iter->target) || iter->start; } _Bool hm_iter_at_end(struct hashmap_iter * iter) { return hm_empty(iter->target) || iter->end; } _Bool hm_iter_to_start(struct hashmap_iter * iter) { if (!hm_empty(iter->target)) { iter->cursor = iter->first; iter->index = 0; iter->start = 1; iter->end = hm_empty(iter->target); return 1; } return 0; } _Bool hm_iter_to_end(struct hashmap_iter * iter) { if (!hm_empty(iter->target)) { iter->cursor = iter->last; iter->index = iter->target->count - 1; iter->start = hm_empty(iter->target); iter->end = 1; return 1; } return 0; } _Bool hm_iter_next(struct hashmap_iter * iter) { if (iter->end) return 0; if (iter->index + 1 == iter->target->count) { iter->end = 1; return 0; } iter->start = hm_empty(iter->target); struct hashmap_entry *scan = &(iter->target->buffer[iter->cursor]); iter->index++; while (1) { iter->cursor++; scan = &(iter->target->buffer[iter->cursor]); if (scan->state == CMC_ES_FILLED) break; } return 1; } _Bool hm_iter_prev(struct hashmap_iter * iter) { if (iter->start) return 0; if (iter->index == 0) { iter->start = 1; return 0; } iter->end = hm_empty(iter->target); struct hashmap_entry *scan = &(iter->target->buffer[iter->cursor]); iter->index--; while (1) { iter->cursor--; scan = &(iter->target->buffer[iter->cursor]); if (scan->state == CMC_ES_FILLED) break; } return 1; } _Bool hm_iter_advance(struct hashmap_iter * iter, size_t steps) { if (iter->end) return 0; if (iter->index + 1 == iter->target->count) { iter->end = 1; return 0; } if (steps == 0 || iter->index + steps >= iter->target->count) return 0; for (size_t i = 0; i < steps; i++) hm_iter_next(iter); return 1; } _Bool hm_iter_rewind(struct hashmap_iter * iter, size_t steps) { if (iter->start) return 0; if (iter->index == 0) { iter->start = 1; return 0; } if (steps == 0 || iter->index < steps) return 0; for (size_t i = 0; i < steps; i++) hm_iter_prev(iter); return 1; } _Bool hm_iter_go_to(struct hashmap_iter * iter, size_t index) { if (index >= iter->target->count) return 0; if (iter->index > index) return hm_iter_rewind(iter, iter->index - index); else if (iter->index < index) return hm_iter_advance(iter, index - iter->index); return 1; } size_t hm_iter_key(struct hashmap_iter * iter) { if (hm_empty(iter->target)) return (size_t){ 0 }; return iter->target->buffer[iter->cursor].key; } size_t hm_iter_value(struct hashmap_iter * iter) { if (hm_empty(iter->target)) return (size_t){ 0 }; return iter->target->buffer[iter->cursor].value; } size_t *hm_iter_rvalue(struct hashmap_iter * iter) { if (hm_empty(iter->target)) return ((void *)0); return &(iter->target->buffer[iter->cursor].value); } size_t hm_iter_index(struct hashmap_iter * iter) { return iter->index; } _Bool hm_to_string(struct hashmap * _map_, FILE * fptr) { struct hashmap *m_ = _map_; return 0 <= fprintf(fptr, "struct %s<%s, %s> " "at %p { " "buffer:%p, " "capacity:%" "I64u" ", " "count:%" "I64u" ", " "load:%lf, " "flag:%d, " "f_key:%p, " "f_val:%p, " "alloc:%p, " "callbacks:%p }", "hashmap", "size_t", "size_t", m_, m_->buffer, m_->capacity, m_->count, m_->load, m_->flag, m_->f_key, m_->f_val, m_->alloc, (m_)->callbacks); } _Bool hm_print(struct hashmap * _map_, FILE * fptr, const char *start, const char *separator, const char *end, const char *key_val_sep) { fprintf(fptr, "%s", start); size_t last = 0; for (size_t i = _map_->capacity; i > 0; i--) { if ((_map_->buffer[i - 1]).state == CMC_ES_FILLED) { last = i - 1; break; } } for (size_t i = 0; i < _map_->capacity; i++) { struct hashmap_entry *entry = &(_map_->buffer[i]); if (entry->state == CMC_ES_FILLED) { if (!_map_->f_key->str(fptr, entry->key)) return 0; fprintf(fptr, "%s", key_val_sep); if (!_map_->f_val->str(fptr, entry->value)) return 0; if (i + 1 < last) fprintf(fptr, "%s", separator); } } fprintf(fptr, "%s", end); return 1; } - - \ No newline at end of file +static struct hashmap_entry *hm_impl_get_entry(struct hashmap *_map_, size_t key); +static size_t hm_impl_calculate_size(size_t required); +struct hashmap *hm_new(size_t capacity, double load, struct hashmap_fkey *f_key, struct hashmap_fval *f_val) +{ + return hm_new_custom(capacity, load, f_key, f_val, ((void *)0), ((void *)0)); +} +struct hashmap *hm_new_custom(size_t capacity, double load, struct hashmap_fkey *f_key, struct hashmap_fval *f_val, + struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks) +{ + ; + if (capacity == 0 || load <= 0 || load >= 1) + return ((void *)0); + if (capacity >= 0xffffffffffffffffULL * load) + return ((void *)0); + if (!f_key || !f_val) + return ((void *)0); + size_t real_capacity = hm_impl_calculate_size(capacity / load); + if (!alloc) + alloc = &cmc_alloc_node_default; + struct hashmap *_map_ = alloc->malloc(sizeof(struct hashmap)); + if (!_map_) + return ((void *)0); + _map_->buffer = alloc->calloc(real_capacity, sizeof(struct hashmap_entry)); + if (!_map_->buffer) + { + alloc->free(_map_); + return ((void *)0); + } + _map_->count = 0; + _map_->capacity = real_capacity; + _map_->load = load; + _map_->flag = CMC_FLAG_OK; + _map_->f_key = f_key; + _map_->f_val = f_val; + _map_->alloc = alloc; + (_map_)->callbacks = callbacks; + return _map_; +} +void hm_clear(struct hashmap *_map_) +{ + if (_map_->f_key->free || _map_->f_val->free) + { + for (size_t i = 0; i < _map_->capacity; i++) + { + struct hashmap_entry *entry = &(_map_->buffer[i]); + if (entry->state == CMC_ES_FILLED) + { + if (_map_->f_key->free) + _map_->f_key->free(entry->key); + if (_map_->f_val->free) + _map_->f_val->free(entry->value); + } + } + } + memset(_map_->buffer, 0, sizeof(struct hashmap_entry) * _map_->capacity); + _map_->count = 0; + _map_->flag = CMC_FLAG_OK; +} +void hm_free(struct hashmap *_map_) +{ + if (_map_->f_key->free || _map_->f_val->free) + { + for (size_t i = 0; i < _map_->capacity; i++) + { + struct hashmap_entry *entry = &(_map_->buffer[i]); + if (entry->state == CMC_ES_FILLED) + { + if (_map_->f_key->free) + _map_->f_key->free(entry->key); + if (_map_->f_val->free) + _map_->f_val->free(entry->value); + } + } + } + _map_->alloc->free(_map_->buffer); + _map_->alloc->free(_map_); +} +void hm_customize(struct hashmap *_map_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks) +{ + ; + if (!alloc) + _map_->alloc = &cmc_alloc_node_default; + else + _map_->alloc = alloc; + (_map_)->callbacks = callbacks; + _map_->flag = CMC_FLAG_OK; +} +_Bool hm_insert(struct hashmap *_map_, size_t key, size_t value) +{ + if (hm_full(_map_)) + { + if (!hm_resize(_map_, _map_->capacity + 1)) + return 0; + } + if (hm_impl_get_entry(_map_, key) != ((void *)0)) + { + _map_->flag = CMC_FLAG_DUPLICATE; + return 0; + } + size_t hash = _map_->f_key->hash(key); + size_t original_pos = hash % _map_->capacity; + size_t pos = original_pos; + struct hashmap_entry *target = &(_map_->buffer[pos]); + if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) + { + target->key = key; + target->value = value; + target->dist = 0; + target->state = CMC_ES_FILLED; + } + else + { + while (1) + { + pos++; + target = &(_map_->buffer[pos % _map_->capacity]); + if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) + { + target->key = key; + target->value = value; + target->dist = pos - original_pos; + target->state = CMC_ES_FILLED; + break; + } + else if (target->dist < pos - original_pos) + { + size_t tmp_k = target->key; + size_t tmp_v = target->value; + size_t tmp_dist = target->dist; + target->key = key; + target->value = value; + target->dist = pos - original_pos; + key = tmp_k; + value = tmp_v; + original_pos = pos - tmp_dist; + } + } + } + _map_->count++; + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->create) + (_map_)->callbacks->create(); + ; + return 1; +} +_Bool hm_update(struct hashmap *_map_, size_t key, size_t new_value, size_t *old_value) +{ + if (hm_empty(_map_)) + { + _map_->flag = CMC_FLAG_EMPTY; + return 0; + } + struct hashmap_entry *entry = hm_impl_get_entry(_map_, key); + if (!entry) + { + _map_->flag = CMC_FLAG_NOT_FOUND; + return 0; + } + if (old_value) + *old_value = entry->value; + entry->value = new_value; + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->update) + (_map_)->callbacks->update(); + ; + return 1; +} +_Bool hm_remove(struct hashmap *_map_, size_t key, size_t *out_value) +{ + if (hm_empty(_map_)) + { + _map_->flag = CMC_FLAG_EMPTY; + return 0; + } + struct hashmap_entry *result = hm_impl_get_entry(_map_, key); + if (result == ((void *)0)) + { + _map_->flag = CMC_FLAG_NOT_FOUND; + return 0; + } + if (out_value) + *out_value = result->value; + result->key = (size_t){ 0 }; + result->value = (size_t){ 0 }; + result->dist = 0; + result->state = CMC_ES_DELETED; + _map_->count--; + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->delete) + (_map_)->callbacks->delete (); + ; + return 1; +} +_Bool hm_max(struct hashmap *_map_, size_t *key, size_t *value) +{ + if (hm_empty(_map_)) + { + _map_->flag = CMC_FLAG_EMPTY; + return 0; + } + _Bool first = 1; + size_t max_key = (size_t){ 0 }; + size_t max_val = (size_t){ 0 }; + for (size_t i = 0; i < _map_->capacity; i++) + { + if (_map_->buffer[i].state == CMC_ES_FILLED) + { + if (first) + { + max_key = _map_->buffer[i].key; + max_val = _map_->buffer[i].value; + first = 0; + } + else if (_map_->f_key->cmp(_map_->buffer[i].key, max_key) > 0) + { + max_key = _map_->buffer[i].key; + max_val = _map_->buffer[i].value; + } + } + } + if (key) + *key = max_key; + if (value) + *value = max_val; + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->read) + (_map_)->callbacks->read(); + ; + return 1; +} +_Bool hm_min(struct hashmap *_map_, size_t *key, size_t *value) +{ + if (hm_empty(_map_)) + { + _map_->flag = CMC_FLAG_EMPTY; + return 0; + } + _Bool first = 1; + size_t min_key = (size_t){ 0 }; + size_t min_val = (size_t){ 0 }; + for (size_t i = 0; i < _map_->capacity; i++) + { + if (_map_->buffer[i].state == CMC_ES_FILLED) + { + if (first) + { + min_key = _map_->buffer[i].key; + min_val = _map_->buffer[i].value; + first = 0; + } + else if (_map_->f_key->cmp(_map_->buffer[i].key, min_key) < 0) + { + min_key = _map_->buffer[i].key; + min_val = _map_->buffer[i].value; + } + } + } + if (key) + *key = min_key; + if (value) + *value = min_val; + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->read) + (_map_)->callbacks->read(); + ; + return 1; +} +size_t hm_get(struct hashmap *_map_, size_t key) +{ + if (hm_empty(_map_)) + { + _map_->flag = CMC_FLAG_EMPTY; + return (size_t){ 0 }; + } + struct hashmap_entry *entry = hm_impl_get_entry(_map_, key); + if (!entry) + { + _map_->flag = CMC_FLAG_NOT_FOUND; + return (size_t){ 0 }; + } + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->read) + (_map_)->callbacks->read(); + ; + return entry->value; +} +size_t *hm_get_ref(struct hashmap *_map_, size_t key) +{ + if (hm_empty(_map_)) + { + _map_->flag = CMC_FLAG_EMPTY; + return ((void *)0); + } + struct hashmap_entry *entry = hm_impl_get_entry(_map_, key); + if (!entry) + { + _map_->flag = CMC_FLAG_NOT_FOUND; + return ((void *)0); + } + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->read) + (_map_)->callbacks->read(); + ; + return &(entry->value); +} +_Bool hm_contains(struct hashmap *_map_, size_t key) +{ + _map_->flag = CMC_FLAG_OK; + _Bool result = hm_impl_get_entry(_map_, key) != ((void *)0); + if ((_map_)->callbacks && (_map_)->callbacks->read) + (_map_)->callbacks->read(); + ; + return result; +} +_Bool hm_empty(struct hashmap *_map_) +{ + return _map_->count == 0; +} +_Bool hm_full(struct hashmap *_map_) +{ + return (double)_map_->capacity * _map_->load <= (double)_map_->count; +} +size_t hm_count(struct hashmap *_map_) +{ + return _map_->count; +} +size_t hm_capacity(struct hashmap *_map_) +{ + return _map_->capacity; +} +double hm_load(struct hashmap *_map_) +{ + return _map_->load; +} +int hm_flag(struct hashmap *_map_) +{ + return _map_->flag; +} +_Bool hm_resize(struct hashmap *_map_, size_t capacity) +{ + _map_->flag = CMC_FLAG_OK; + if (_map_->capacity == capacity) + goto success; + if (_map_->capacity > capacity / _map_->load) + goto success; + if (capacity >= 0xffffffffffffffffULL * _map_->load) + { + _map_->flag = CMC_FLAG_ERROR; + return 0; + } + size_t theoretical_size = hm_impl_calculate_size(capacity); + if (theoretical_size < _map_->count / _map_->load) + { + _map_->flag = CMC_FLAG_INVALID; + return 0; + } + struct hashmap *_new_map_ = + hm_new_custom(capacity, _map_->load, _map_->f_key, _map_->f_val, _map_->alloc, ((void *)0)); + if (!_new_map_) + { + _map_->flag = CMC_FLAG_ALLOC; + return 0; + } + for (size_t i = 0; i < _map_->capacity; i++) + { + if (_map_->buffer[i].state == CMC_ES_FILLED) + { + size_t key = _map_->buffer[i].key; + size_t value = _map_->buffer[i].value; + hm_insert(_new_map_, key, value); + } + } + if (_map_->count != _new_map_->count) + { + hm_free(_new_map_); + _map_->flag = CMC_FLAG_ERROR; + return 0; + } + struct hashmap_entry *tmp_b = _map_->buffer; + _map_->buffer = _new_map_->buffer; + _new_map_->buffer = tmp_b; + size_t tmp_c = _map_->capacity; + _map_->capacity = _new_map_->capacity; + _new_map_->capacity = tmp_c; + _new_map_->f_key = &(struct hashmap_fkey){ ((void *)0) }; + _new_map_->f_val = &(struct hashmap_fval){ ((void *)0) }; + hm_free(_new_map_); +success: + if ((_map_)->callbacks && (_map_)->callbacks->resize) + (_map_)->callbacks->resize(); + ; + return 1; +} +struct hashmap *hm_copy_of(struct hashmap *_map_) +{ + struct hashmap *result = hm_new_custom(_map_->capacity * _map_->load, _map_->load, _map_->f_key, _map_->f_val, + _map_->alloc, ((void *)0)); + if (!result) + { + _map_->flag = CMC_FLAG_ERROR; + return ((void *)0); + } + (result)->callbacks = _map_->callbacks; + if (_map_->f_key->cpy || _map_->f_val->cpy) + { + for (size_t i = 0; i < _map_->capacity; i++) + { + struct hashmap_entry *scan = &(_map_->buffer[i]); + if (scan->state != CMC_ES_EMPTY) + { + struct hashmap_entry *target = &(result->buffer[i]); + if (scan->state == CMC_ES_DELETED) + target->state = CMC_ES_DELETED; + else + { + target->state = scan->state; + target->dist = scan->dist; + if (_map_->f_key->cpy) + target->key = _map_->f_key->cpy(scan->key); + else + target->key = scan->key; + if (_map_->f_val->cpy) + target->value = _map_->f_val->cpy(scan->value); + else + target->value = scan->value; + } + } + } + } + else + memcpy(result->buffer, _map_->buffer, sizeof(struct hashmap_entry) * _map_->capacity); + result->count = _map_->count; + _map_->flag = CMC_FLAG_OK; + return result; +} +_Bool hm_equals(struct hashmap *_map1_, struct hashmap *_map2_) +{ + _map1_->flag = CMC_FLAG_OK; + _map2_->flag = CMC_FLAG_OK; + if (_map1_->count != _map2_->count) + return 0; + struct hashmap *_map_a_; + struct hashmap *_map_b_; + _map_a_ = _map1_->capacity < _map2_->capacity ? _map1_ : _map2_; + _map_b_ = _map_a_ == _map1_ ? _map2_ : _map1_; + for (size_t i = 0; i < _map_a_->capacity; i++) + { + if (_map_a_->buffer[i].state == CMC_ES_FILLED) + { + struct hashmap_entry *entry_a = &(_map_a_->buffer[i]); + struct hashmap_entry *entry_b = hm_impl_get_entry(_map_b_, entry_a->key); + if (!entry_b) + return 0; + if (_map_a_->f_val->cmp(entry_a->value, entry_b->value) != 0) + return 0; + } + } + return 1; +} +static struct hashmap_entry *hm_impl_get_entry(struct hashmap *_map_, size_t key) +{ + size_t hash = _map_->f_key->hash(key); + size_t pos = hash % _map_->capacity; + struct hashmap_entry *target = &(_map_->buffer[pos]); + while (target->state == CMC_ES_FILLED || target->state == CMC_ES_DELETED) + { + if (_map_->f_key->cmp(target->key, key) == 0) + return target; + pos++; + target = &(_map_->buffer[pos % _map_->capacity]); + } + return ((void *)0); +} +static size_t hm_impl_calculate_size(size_t required) +{ + const size_t count = sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]); + if (cmc_hashtable_primes[count - 1] < required) + return required; + size_t i = 0; + while (cmc_hashtable_primes[i] < required) + i++; + return cmc_hashtable_primes[i]; +} +struct hashmap hm_init(size_t capacity, double load, struct hashmap_fkey *f_key, struct hashmap_fval *f_val) +{ + return hm_init_custom(capacity, load, f_key, f_val, ((void *)0), ((void *)0)); +} +struct hashmap hm_init_custom(size_t capacity, double load, struct hashmap_fkey *f_key, struct hashmap_fval *f_val, + struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks) +{ + ; + struct hashmap _map_ = { 0 }; + if (capacity == 0 || load <= 0 || load >= 1) + return _map_; + if (capacity >= 0xffffffffffffffffULL * load) + return _map_; + if (!f_key || !f_val) + return _map_; + size_t real_capacity = hm_impl_calculate_size(capacity / load); + if (!alloc) + alloc = &cmc_alloc_node_default; + _map_.buffer = alloc->calloc(real_capacity, sizeof(struct hashmap_entry)); + if (!_map_.buffer) + return _map_; + _map_.count = 0; + _map_.capacity = real_capacity; + _map_.load = load; + _map_.flag = CMC_FLAG_OK; + _map_.f_key = f_key; + _map_.f_val = f_val; + _map_.alloc = alloc; + (&_map_)->callbacks = callbacks; + return _map_; +} +void hm_release(struct hashmap _map_) +{ + if (_map_.f_key->free || _map_.f_val->free) + { + for (size_t i = 0; i < _map_.capacity; i++) + { + struct hashmap_entry *entry = &(_map_.buffer[i]); + if (entry->state == CMC_ES_FILLED) + { + if (_map_.f_key->free) + _map_.f_key->free(entry->key); + if (_map_.f_val->free) + _map_.f_val->free(entry->value); + } + } + } + _map_.alloc->free(_map_.buffer); +} +struct hashmap_iter hm_iter_start(struct hashmap *target) +{ + struct hashmap_iter iter; + iter.target = target; + iter.cursor = 0; + iter.index = 0; + iter.first = 0; + iter.last = 0; + iter.start = 1; + iter.end = hm_empty(target); + if (!hm_empty(target)) + { + for (size_t i = 0; i < target->capacity; i++) + { + if (target->buffer[i].state == CMC_ES_FILLED) + { + iter.first = i; + break; + } + } + iter.cursor = iter.first; + for (size_t i = target->capacity; i > 0; i--) + { + if (target->buffer[i - 1].state == CMC_ES_FILLED) + { + iter.last = i - 1; + break; + } + } + } + return iter; +} +struct hashmap_iter hm_iter_end(struct hashmap *target) +{ + struct hashmap_iter iter; + iter.target = target; + iter.cursor = 0; + iter.index = 0; + iter.first = 0; + iter.last = 0; + iter.start = hm_empty(target); + iter.end = 1; + if (!hm_empty(target)) + { + for (size_t i = 0; i < target->capacity; i++) + { + if (target->buffer[i].state == CMC_ES_FILLED) + { + iter.first = i; + break; + } + } + for (size_t i = target->capacity; i > 0; i--) + { + if (target->buffer[i - 1].state == CMC_ES_FILLED) + { + iter.last = i - 1; + break; + } + } + iter.cursor = iter.last; + iter.index = target->count - 1; + } + return iter; +} +_Bool hm_iter_at_start(struct hashmap_iter *iter) +{ + return hm_empty(iter->target) || iter->start; +} +_Bool hm_iter_at_end(struct hashmap_iter *iter) +{ + return hm_empty(iter->target) || iter->end; +} +_Bool hm_iter_to_start(struct hashmap_iter *iter) +{ + if (!hm_empty(iter->target)) + { + iter->cursor = iter->first; + iter->index = 0; + iter->start = 1; + iter->end = hm_empty(iter->target); + return 1; + } + return 0; +} +_Bool hm_iter_to_end(struct hashmap_iter *iter) +{ + if (!hm_empty(iter->target)) + { + iter->cursor = iter->last; + iter->index = iter->target->count - 1; + iter->start = hm_empty(iter->target); + iter->end = 1; + return 1; + } + return 0; +} +_Bool hm_iter_next(struct hashmap_iter *iter) +{ + if (iter->end) + return 0; + if (iter->index + 1 == iter->target->count) + { + iter->end = 1; + return 0; + } + iter->start = hm_empty(iter->target); + struct hashmap_entry *scan = &(iter->target->buffer[iter->cursor]); + iter->index++; + while (1) + { + iter->cursor++; + scan = &(iter->target->buffer[iter->cursor]); + if (scan->state == CMC_ES_FILLED) + break; + } + return 1; +} +_Bool hm_iter_prev(struct hashmap_iter *iter) +{ + if (iter->start) + return 0; + if (iter->index == 0) + { + iter->start = 1; + return 0; + } + iter->end = hm_empty(iter->target); + struct hashmap_entry *scan = &(iter->target->buffer[iter->cursor]); + iter->index--; + while (1) + { + iter->cursor--; + scan = &(iter->target->buffer[iter->cursor]); + if (scan->state == CMC_ES_FILLED) + break; + } + return 1; +} +_Bool hm_iter_advance(struct hashmap_iter *iter, size_t steps) +{ + if (iter->end) + return 0; + if (iter->index + 1 == iter->target->count) + { + iter->end = 1; + return 0; + } + if (steps == 0 || iter->index + steps >= iter->target->count) + return 0; + for (size_t i = 0; i < steps; i++) + hm_iter_next(iter); + return 1; +} +_Bool hm_iter_rewind(struct hashmap_iter *iter, size_t steps) +{ + if (iter->start) + return 0; + if (iter->index == 0) + { + iter->start = 1; + return 0; + } + if (steps == 0 || iter->index < steps) + return 0; + for (size_t i = 0; i < steps; i++) + hm_iter_prev(iter); + return 1; +} +_Bool hm_iter_go_to(struct hashmap_iter *iter, size_t index) +{ + if (index >= iter->target->count) + return 0; + if (iter->index > index) + return hm_iter_rewind(iter, iter->index - index); + else if (iter->index < index) + return hm_iter_advance(iter, index - iter->index); + return 1; +} +size_t hm_iter_key(struct hashmap_iter *iter) +{ + if (hm_empty(iter->target)) + return (size_t){ 0 }; + return iter->target->buffer[iter->cursor].key; +} +size_t hm_iter_value(struct hashmap_iter *iter) +{ + if (hm_empty(iter->target)) + return (size_t){ 0 }; + return iter->target->buffer[iter->cursor].value; +} +size_t *hm_iter_rvalue(struct hashmap_iter *iter) +{ + if (hm_empty(iter->target)) + return ((void *)0); + return &(iter->target->buffer[iter->cursor].value); +} +size_t hm_iter_index(struct hashmap_iter *iter) +{ + return iter->index; +} +_Bool hm_to_string(struct hashmap *_map_, FILE *fptr) +{ + struct hashmap *m_ = _map_; + return 0 <= fprintf(fptr, + "struct %s<%s, %s> " + "at %p { " + "buffer:%p, " + "capacity:%" + "I64u" + ", " + "count:%" + "I64u" + ", " + "load:%lf, " + "flag:%d, " + "f_key:%p, " + "f_val:%p, " + "alloc:%p, " + "callbacks:%p }", + "hashmap", "size_t", "size_t", m_, m_->buffer, m_->capacity, m_->count, m_->load, m_->flag, + m_->f_key, m_->f_val, m_->alloc, (m_)->callbacks); +} +_Bool hm_print(struct hashmap *_map_, FILE *fptr, const char *start, const char *separator, const char *end, + const char *key_val_sep) +{ + fprintf(fptr, "%s", start); + size_t last = 0; + for (size_t i = _map_->capacity; i > 0; i--) + { + if ((_map_->buffer[i - 1]).state == CMC_ES_FILLED) + { + last = i - 1; + break; + } + } + for (size_t i = 0; i < _map_->capacity; i++) + { + struct hashmap_entry *entry = &(_map_->buffer[i]); + if (entry->state == CMC_ES_FILLED) + { + if (!_map_->f_key->str(fptr, entry->key)) + return 0; + fprintf(fptr, "%s", key_val_sep); + if (!_map_->f_val->str(fptr, entry->value)) + return 0; + if (i + 1 < last) + fprintf(fptr, "%s", separator); + } + } + fprintf(fptr, "%s", end); + return 1; +} diff --git a/tests/src/tst_cmc_hashmultimap.c b/tests/src/tst_cmc_hashmultimap.c index fa8d7c1..79177d4 100644 --- a/tests/src/tst_cmc_hashmultimap.c +++ b/tests/src/tst_cmc_hashmultimap.c @@ -1,7 +1,931 @@ - #include "tst_cmc_hashmultimap.h" +#include "tst_cmc_hashmultimap.h" - - struct hashmultimap_entry * hmm_impl_new_entry(struct hashmultimap * _map_, size_t key, size_t value); struct hashmultimap_entry * hmm_impl_get_entry(struct hashmultimap * _map_, size_t key); size_t hmm_impl_key_count(struct hashmultimap * _map_, size_t key); size_t hmm_impl_calculate_size(size_t required); struct hashmultimap *hmm_new(size_t capacity, double load, struct hashmultimap_fkey * f_key, struct hashmultimap_fval * f_val) { return hmm_new_custom(capacity, load, f_key, f_val, ((void *)0), ((void *)0)); } struct hashmultimap *hmm_new_custom(size_t capacity, double load, struct hashmultimap_fkey * f_key, struct hashmultimap_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (capacity == 0 || load <= 0) return ((void *)0); if (capacity >= 0xffffffffffffffffULL * load) return ((void *)0); if (!f_key || !f_val) return ((void *)0); if (!alloc) alloc = &cmc_alloc_node_default; size_t real_capacity = hmm_impl_calculate_size(capacity / load); struct hashmultimap *_map_ = alloc->malloc(sizeof(struct hashmultimap)); if (!_map_) return ((void *)0); _map_->buffer = alloc->calloc(real_capacity, sizeof(struct hashmultimap_entry *[2])); if (!_map_->buffer) { alloc->free(_map_); return ((void *)0); } _map_->count = 0; _map_->capacity = real_capacity; _map_->load = load; _map_->flag = CMC_FLAG_OK; _map_->f_key = f_key; _map_->f_val = f_val; _map_->alloc = alloc; (_map_)->callbacks = callbacks; return _map_; } void hmm_clear(struct hashmultimap * _map_) { for (size_t i = 0; i < _map_->capacity; i++) { struct hashmultimap_entry *scan = _map_->buffer[i][0]; while (scan) { struct hashmultimap_entry *next = scan->next; if (_map_->f_key->free) _map_->f_key->free(scan->key); if (_map_->f_val->free) _map_->f_val->free(scan->value); _map_->alloc->free(scan); scan = next; } } memset(_map_->buffer, 0, sizeof(struct hashmultimap_entry *[2]) * _map_->capacity); _map_->count = 0; _map_->flag = CMC_FLAG_OK; } void hmm_free(struct hashmultimap * _map_) { size_t index = 0; while (index < _map_->capacity) { struct hashmultimap_entry *scan = _map_->buffer[index][0]; if (scan) { if (scan->next == ((void *)0) && scan->prev == ((void *)0)) { if (_map_->f_key->free) _map_->f_key->free(scan->key); if (_map_->f_val->free) _map_->f_val->free(scan->value); _map_->alloc->free(scan); } else { while (scan) { struct hashmultimap_entry *tmp = scan; scan = scan->next; if (_map_->f_key->free) _map_->f_key->free(tmp->key); if (_map_->f_val->free) _map_->f_val->free(tmp->value); _map_->alloc->free(tmp); } } } index++; } _map_->alloc->free(_map_->buffer); _map_->alloc->free(_map_); } void hmm_customize(struct hashmultimap * _map_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (!alloc) _map_->alloc = &cmc_alloc_node_default; else _map_->alloc = alloc; (_map_)->callbacks = callbacks; _map_->flag = CMC_FLAG_OK; } _Bool hmm_insert(struct hashmultimap * _map_, size_t key, size_t value) { if (hmm_full(_map_)) { if (!hmm_resize(_map_, _map_->capacity + 1)) return 0; } size_t hash = _map_->f_key->hash(key); size_t pos = hash % _map_->capacity; struct hashmultimap_entry *entry = hmm_impl_new_entry(_map_, key, value); if (_map_->buffer[pos][0] == ((void *)0)) { _map_->buffer[pos][0] = entry; _map_->buffer[pos][1] = entry; } else { entry->prev = _map_->buffer[pos][1]; _map_->buffer[pos][1]->next = entry; _map_->buffer[pos][1] = entry; } _map_->count++; _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->create) (_map_)->callbacks->create();; return 1; } _Bool hmm_update(struct hashmultimap * _map_, size_t key, size_t new_value, size_t * old_value) { if (hmm_empty(_map_)) { _map_->flag = CMC_FLAG_EMPTY; return 0; } struct hashmultimap_entry *entry = hmm_impl_get_entry(_map_, key); if (!entry) { _map_->flag = CMC_FLAG_NOT_FOUND; return 0; } if (old_value) *old_value = entry->value; entry->value = new_value; _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->update) (_map_)->callbacks->update();; return 1; } size_t hmm_update_all(struct hashmultimap * _map_, size_t key, size_t new_value, size_t * *old_values) { if (hmm_empty(_map_)) { _map_->flag = CMC_FLAG_EMPTY; return 0; } size_t hash = _map_->f_key->hash(key); struct hashmultimap_entry *entry = _map_->buffer[hash % _map_->capacity][0]; if (entry == ((void *)0)) { _map_->flag = CMC_FLAG_NOT_FOUND; return 0; } if (old_values) { size_t total = hmm_impl_key_count(_map_, key); if (total == 0) { _map_->flag = CMC_FLAG_NOT_FOUND; return 0; } *old_values = _map_->alloc->malloc(sizeof(size_t) * total); if (!(*old_values)) { _map_->flag = CMC_FLAG_ALLOC; return 0; } } size_t index = 0; while (entry) { if (_map_->f_key->cmp(entry->key, key) == 0) { if (old_values) (*old_values)[index] = entry->value; index++; entry->value = new_value; } entry = entry->next; } _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->update) (_map_)->callbacks->update();; return index; } _Bool hmm_remove(struct hashmultimap * _map_, size_t key, size_t * out_value) { if (hmm_empty(_map_)) { _map_->flag = CMC_FLAG_EMPTY; return 0; } size_t hash = _map_->f_key->hash(key); struct hashmultimap_entry **head = &(_map_->buffer[hash % _map_->capacity][0]); struct hashmultimap_entry **tail = &(_map_->buffer[hash % _map_->capacity][1]); if (*head == ((void *)0)) { _map_->flag = CMC_FLAG_NOT_FOUND; return 0; } struct hashmultimap_entry *entry = *head; if (entry->next == ((void *)0) && entry->prev == ((void *)0)) { if (_map_->f_key->cmp(entry->key, key) == 0) { *head = ((void *)0); *tail = ((void *)0); if (out_value) *out_value = entry->value; } else { _map_->flag = CMC_FLAG_NOT_FOUND; return 0; } } else { _Bool found = 0; while (entry) { if (_map_->f_key->cmp(entry->key, key) == 0) { if (*head == entry) *head = entry->next; if (*tail == entry) *tail = entry->prev; if (entry->prev) entry->prev->next = entry->next; if (entry->next) entry->next->prev = entry->prev; if (out_value) *out_value = entry->value; found = 1; break; } else entry = entry->next; } if (!found) { _map_->flag = CMC_FLAG_NOT_FOUND; return 0; } } _map_->alloc->free(entry); _map_->count--; _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->delete) (_map_)->callbacks->delete();; return 1; } size_t hmm_remove_all(struct hashmultimap * _map_, size_t key, size_t * *out_values) { if (hmm_empty(_map_)) { _map_->flag = CMC_FLAG_EMPTY; return 0; } size_t hash = _map_->f_key->hash(key); struct hashmultimap_entry **head = &(_map_->buffer[hash % _map_->capacity][0]); struct hashmultimap_entry **tail = &(_map_->buffer[hash % _map_->capacity][1]); if (*head == ((void *)0)) { _map_->flag = CMC_FLAG_NOT_FOUND; return 0; } if (out_values) { size_t total = hmm_impl_key_count(_map_, key); if (total == 0) { _map_->flag = CMC_FLAG_NOT_FOUND; return 0; } *out_values = _map_->alloc->malloc(sizeof(size_t) * total); if (!(*out_values)) { _map_->flag = CMC_FLAG_ALLOC; return 0; } } size_t index = 0; struct hashmultimap_entry *entry = *head; if (entry->next == ((void *)0)) { *head = ((void *)0); *tail = ((void *)0); if (out_values) (*out_values)[index] = entry->value; index++; _map_->alloc->free(entry); } else { while (entry) { if (_map_->f_key->cmp(entry->key, key) == 0) { if (*head == entry) *head = entry->next; if (*tail == entry) *tail = entry->prev; struct hashmultimap_entry *next = entry->next; if (entry->prev) entry->prev->next = entry->next; if (entry->next) entry->next->prev = entry->prev; if (out_values) (*out_values)[index] = entry->value; index++; _map_->alloc->free(entry); entry = next; } else entry = entry->next; } } _map_->count -= index; _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->delete) (_map_)->callbacks->delete();; return index; } _Bool hmm_max(struct hashmultimap * _map_, size_t * key, size_t * value) { if (hmm_empty(_map_)) { _map_->flag = CMC_FLAG_EMPTY; return 0; } _Bool first = 1; size_t max_key = (size_t){ 0 }; size_t max_val = (size_t){ 0 }; for (size_t i = 0; i < _map_->capacity; i++) { struct hashmultimap_entry *scan = _map_->buffer[i][0]; while (scan) { if (first) { max_key = scan->key; max_val = scan->value; first = 0; } else if (_map_->f_key->cmp(scan->key, max_key) > 0) { max_key = scan->key; max_val = scan->value; } scan = scan->next; } } if (key) *key = max_key; if (value) *value = max_val; _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->read) (_map_)->callbacks->read();; return 1; } _Bool hmm_min(struct hashmultimap * _map_, size_t * key, size_t * value) { if (hmm_empty(_map_)) { _map_->flag = CMC_FLAG_EMPTY; return 0; } _Bool first = 1; size_t min_key = (size_t){ 0 }; size_t min_val = (size_t){ 0 }; for (size_t i = 0; i < _map_->capacity; i++) { struct hashmultimap_entry *scan = _map_->buffer[i][0]; while (scan) { if (first) { min_key = scan->key; min_val = scan->value; first = 0; } else if (_map_->f_key->cmp(scan->key, min_key) < 0) { min_key = scan->key; min_val = scan->value; } scan = scan->next; } } if (key) *key = min_key; if (value) *value = min_val; _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->read) (_map_)->callbacks->read();; return 1; } size_t hmm_get(struct hashmultimap * _map_, size_t key) { if (hmm_empty(_map_)) { _map_->flag = CMC_FLAG_EMPTY; return (size_t){ 0 }; } struct hashmultimap_entry *entry = hmm_impl_get_entry(_map_, key); if (!entry) { _map_->flag = CMC_FLAG_NOT_FOUND; return (size_t){ 0 }; } _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->read) (_map_)->callbacks->read();; return entry->value; } size_t *hmm_get_ref(struct hashmultimap * _map_, size_t key) { if (hmm_empty(_map_)) { _map_->flag = CMC_FLAG_EMPTY; return ((void *)0); } struct hashmultimap_entry *entry = hmm_impl_get_entry(_map_, key); if (!entry) { _map_->flag = CMC_FLAG_NOT_FOUND; return ((void *)0); } _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->read) (_map_)->callbacks->read();; return &(entry->value); } _Bool hmm_contains(struct hashmultimap * _map_, size_t key) { _map_->flag = CMC_FLAG_OK; _Bool result = hmm_impl_get_entry(_map_, key) != ((void *)0); if ((_map_)->callbacks && (_map_)->callbacks->read) (_map_)->callbacks->read();; return result; } _Bool hmm_empty(struct hashmultimap * _map_) { return _map_->count == 0; } _Bool hmm_full(struct hashmultimap * _map_) { return (double)_map_->capacity * _map_->load <= (double)_map_->count; } size_t hmm_count(struct hashmultimap * _map_) { return _map_->count; } size_t hmm_key_count(struct hashmultimap * _map_, size_t key) { return hmm_impl_key_count(_map_, key); } size_t hmm_capacity(struct hashmultimap * _map_) { return _map_->capacity; } double hmm_load(struct hashmultimap * _map_) { return _map_->load; } int hmm_flag(struct hashmultimap * _map_) { return _map_->flag; } _Bool hmm_resize(struct hashmultimap * _map_, size_t capacity) { _map_->flag = CMC_FLAG_OK; if (_map_->capacity == capacity) goto success; if (_map_->capacity > capacity / _map_->load) goto success; if (capacity >= 0xffffffffffffffffULL * _map_->load) { _map_->flag = CMC_FLAG_ERROR; return 0; } size_t theoretical_size = hmm_impl_calculate_size(capacity); if (theoretical_size < _map_->count / _map_->load) { _map_->flag = CMC_FLAG_INVALID; return 0; } struct hashmultimap *_new_map_ = hmm_new_custom(capacity, _map_->load, _map_->f_key, _map_->f_val, _map_->alloc, ((void *)0)); if (!_new_map_) { _map_->flag = CMC_FLAG_ALLOC; return 0; } for (size_t i = 0; i < _map_->capacity; i++) { struct hashmultimap_entry *scan = _map_->buffer[i][0]; while (scan) { hmm_insert(_new_map_, scan->key, scan->value); scan = scan->next; } } if (_map_->count != _new_map_->count) { hmm_free(_new_map_); _map_->flag = CMC_FLAG_ERROR; return 0; } struct hashmultimap_entry * (*tmp_b)[2] = _map_->buffer; _map_->buffer = _new_map_->buffer; _new_map_->buffer = tmp_b; size_t tmp_c = _map_->capacity; _map_->capacity = _new_map_->capacity; _new_map_->capacity = tmp_c; _new_map_->f_key = &(struct hashmultimap_fkey){ ((void *)0) }; _new_map_->f_val = &(struct hashmultimap_fval){ ((void *)0) }; hmm_free(_new_map_); success: if ((_map_)->callbacks && (_map_)->callbacks->resize) (_map_)->callbacks->resize();; return 1; } struct hashmultimap *hmm_copy_of(struct hashmultimap * _map_) { struct hashmultimap *result = hmm_new_custom(_map_->capacity * _map_->load, _map_->load, _map_->f_key, _map_->f_val, _map_->alloc, ((void *)0)); if (!result) { _map_->flag = CMC_FLAG_ERROR; return ((void *)0); } for (size_t i = 0; i < _map_->capacity; i++) { struct hashmultimap_entry *scan = _map_->buffer[i][0]; while (scan) { size_t key; size_t value; if (_map_->f_key->cpy) key = _map_->f_key->cpy(scan->key); else key = scan->key; if (_map_->f_val->cpy) value = _map_->f_val->cpy(scan->value); else value = scan->value; hmm_insert(result, key, value); scan = scan->next; } } (result)->callbacks = _map_->callbacks; _map_->flag = CMC_FLAG_OK; return result; } _Bool hmm_equals(struct hashmultimap * _map1_, struct hashmultimap * _map2_) { _map1_->flag = CMC_FLAG_OK; _map2_->flag = CMC_FLAG_OK; if (_map1_->count != _map2_->count) return 0; struct hashmultimap *_map_a_; struct hashmultimap *_map_b_; _map_a_ = _map1_->capacity < _map2_->capacity ? _map1_ : _map2_; _map_b_ = _map_a_ == _map1_ ? _map2_ : _map1_; for (size_t i = 0; i < _map_a_->capacity; i++) { struct hashmultimap_entry *scan = _map_a_->buffer[i][0]; while (scan) { if (hmm_impl_key_count(_map_a_, scan->key) != hmm_impl_key_count(_map_b_, scan->key)) return 0; scan = scan->next; } } return 1; } struct hashmultimap_entry * hmm_impl_new_entry(struct hashmultimap * _map_, size_t key, size_t value) { struct hashmultimap_entry *entry = _map_->alloc->malloc(sizeof(struct hashmultimap_entry)); if (!entry) return ((void *)0); entry->key = key; entry->value = value; entry->next = ((void *)0); entry->prev = ((void *)0); return entry; } struct hashmultimap_entry * hmm_impl_get_entry(struct hashmultimap * _map_, size_t key) { size_t hash = _map_->f_key->hash(key); struct hashmultimap_entry *entry = _map_->buffer[hash % _map_->capacity][0]; while (entry) { if (_map_->f_key->cmp(entry->key, key) == 0) return entry; entry = entry->next; } return ((void *)0); } size_t hmm_impl_key_count(struct hashmultimap * _map_, size_t key) { size_t hash = _map_->f_key->hash(key); struct hashmultimap_entry *entry = _map_->buffer[hash % _map_->capacity][0]; size_t total_count = 0; if (!entry) return total_count; while (entry) { if (_map_->f_key->cmp(entry->key, key) == 0) total_count++; entry = entry->next; } return total_count; } size_t hmm_impl_calculate_size(size_t required) { const size_t count = sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]); if (cmc_hashtable_primes[count - 1] < required) return required; size_t i = 0; while (cmc_hashtable_primes[i] < required) i++; return cmc_hashtable_primes[i]; } struct hashmultimap_iter hmm_iter_start(struct hashmultimap * target) { struct hashmultimap_iter iter; iter.target = target; iter.curr_entry = ((void *)0); iter.cursor = 0; iter.index = 0; iter.first = 0; iter.last = 0; iter.start = 1; iter.end = hmm_empty(target); if (!hmm_empty(target)) { for (size_t i = 0; i < target->capacity; i++) { struct hashmultimap_entry *entry = target->buffer[i][0]; if (entry && entry != ((void *)1)) { iter.curr_entry = target->buffer[i][0]; iter.first = i; break; } } iter.cursor = iter.first; for (size_t i = target->capacity; i > 0; i--) { struct hashmultimap_entry *entry = target->buffer[i - 1][1]; if (entry && entry != ((void *)1)) { iter.last = i - 1; break; } } } return iter; } struct hashmultimap_iter hmm_iter_end(struct hashmultimap * target) { struct hashmultimap_iter iter; iter.target = target; iter.curr_entry = ((void *)0); iter.cursor = 0; iter.index = 0; iter.first = 0; iter.last = 0; iter.start = hmm_empty(target); iter.end = 1; if (!hmm_empty(target)) { for (size_t i = 0; i < target->capacity; i++) { struct hashmultimap_entry *entry = target->buffer[i][0]; if (entry && entry != ((void *)1)) { iter.first = i; break; } } for (size_t i = target->capacity; i > 0; i--) { struct hashmultimap_entry *entry = target->buffer[i - 1][1]; if (entry && entry != ((void *)1)) { iter.curr_entry = target->buffer[i - 1][1]; iter.last = i - 1; break; } } iter.cursor = iter.last; iter.index = target->count - 1; } return iter; } _Bool hmm_iter_at_start(struct hashmultimap_iter * iter) { return hmm_empty(iter->target) || iter->start; } _Bool hmm_iter_at_end(struct hashmultimap_iter * iter) { return hmm_empty(iter->target) || iter->end; } _Bool hmm_iter_to_start(struct hashmultimap_iter * iter) { if (!hmm_empty(iter->target)) { iter->cursor = iter->first; iter->index = 0; iter->start = 1; iter->end = hmm_empty(iter->target); iter->curr_entry = iter->target->buffer[iter->first][0]; return 1; } return 0; } _Bool hmm_iter_to_end(struct hashmultimap_iter * iter) { if (!hmm_empty(iter->target)) { iter->cursor = iter->last; iter->index = iter->target->count - 1; iter->start = hmm_empty(iter->target); iter->end = 1; iter->curr_entry = iter->target->buffer[iter->last][1]; return 1; } return 0; } _Bool hmm_iter_next(struct hashmultimap_iter * iter) { if (iter->end) return 0; if (iter->curr_entry->next != ((void *)0)) { iter->curr_entry = iter->curr_entry->next; iter->index++; } else { if (iter->cursor == iter->last) { iter->end = 1; return 0; } iter->cursor++; while (iter->target->buffer[iter->cursor][0] == ((void *)0)) iter->cursor++; iter->curr_entry = iter->target->buffer[iter->cursor][0]; iter->index++; } iter->start = hmm_empty(iter->target); return 1; } _Bool hmm_iter_prev(struct hashmultimap_iter * iter) { if (iter->start) return 0; if (iter->curr_entry->prev != ((void *)0)) { iter->curr_entry = iter->curr_entry->prev; iter->index--; } else { if (iter->cursor == iter->first) { iter->start = 1; return 0; } iter->cursor--; while (iter->target->buffer[iter->cursor][1] == ((void *)0)) iter->cursor--; iter->curr_entry = iter->target->buffer[iter->cursor][1]; iter->index--; } iter->end = hmm_empty(iter->target); return 1; } _Bool hmm_iter_advance(struct hashmultimap_iter * iter, size_t steps) { if (iter->end) return 0; if (iter->index + 1 == iter->target->count) { iter->end = 1; return 0; } if (steps == 0 || iter->index + steps >= iter->target->count) return 0; for (size_t i = 0; i < steps; i++) hmm_iter_next(iter); return 1; } _Bool hmm_iter_rewind(struct hashmultimap_iter * iter, size_t steps) { if (iter->start) return 0; if (iter->index == 0) { iter->start = 1; return 0; } if (steps == 0 || iter->index < steps) return 0; for (size_t i = 0; i < steps; i++) hmm_iter_prev(iter); return 1; } _Bool hmm_iter_go_to(struct hashmultimap_iter * iter, size_t index) { if (index >= iter->target->count) return 0; if (iter->index > index) return hmm_iter_rewind(iter, iter->index - index); else if (iter->index < index) return hmm_iter_advance(iter, index - iter->index); return 1; } size_t hmm_iter_key(struct hashmultimap_iter * iter) { if (hmm_empty(iter->target)) return (size_t){ 0 }; return iter->curr_entry->key; } size_t hmm_iter_value(struct hashmultimap_iter * iter) { if (hmm_empty(iter->target)) return (size_t){ 0 }; return iter->curr_entry->value; } size_t *hmm_iter_rvalue(struct hashmultimap_iter * iter) { if (hmm_empty(iter->target)) return ((void *)0); return &(iter->curr_entry->value); } size_t hmm_iter_index(struct hashmultimap_iter * iter) { return iter->index; } _Bool hmm_to_string(struct hashmultimap * _map_, FILE * fptr) { struct hashmultimap *m_ = _map_; return 0 <= fprintf(fptr, "struct %s<%s, %s> " "at %p { " "buffer:%p, " "capacity:%" "I64u" ", " "count:%" "I64u" ", " "load:%lf, " "flag:%d, " "f_key:%p, " "f_val:%p, " "alloc:%p, " "callbacks:%p }", "hashmultimap", "size_t", "size_t", m_, m_->buffer, m_->capacity, m_->count, m_->load, m_->flag, m_->f_key, m_->f_val, m_->alloc, (m_)->callbacks); } _Bool hmm_print(struct hashmultimap * _map_, FILE * fptr, const char *start, const char *separator, const char *end, const char *key_val_sep) { fprintf(fptr, "%s", start); size_t last = 0; for (size_t i = _map_->capacity; i > 0; i--) { struct hashmultimap_entry *entry = _map_->buffer[i - 1][1]; if (entry && entry != ((void *)1)) { last = i - 1; break; } } for (size_t i = 0; i < _map_->capacity; i++) { struct hashmultimap_entry *scan = _map_->buffer[i][0]; while (scan != ((void *)0)) { if (!_map_->f_key->str(fptr, scan->key)) return 0; fprintf(fptr, "%s", key_val_sep); if (!_map_->f_val->str(fptr, scan->value)) return 0; scan = scan->next; if (i + 1 < last) fprintf(fptr, "%s", separator); } } fprintf(fptr, "%s", end); return 1; } - - \ No newline at end of file +struct hashmultimap_entry *hmm_impl_new_entry(struct hashmultimap *_map_, size_t key, size_t value); +struct hashmultimap_entry *hmm_impl_get_entry(struct hashmultimap *_map_, size_t key); +size_t hmm_impl_key_count(struct hashmultimap *_map_, size_t key); +size_t hmm_impl_calculate_size(size_t required); +struct hashmultimap *hmm_new(size_t capacity, double load, struct hashmultimap_fkey *f_key, + struct hashmultimap_fval *f_val) +{ + return hmm_new_custom(capacity, load, f_key, f_val, ((void *)0), ((void *)0)); +} +struct hashmultimap *hmm_new_custom(size_t capacity, double load, struct hashmultimap_fkey *f_key, + struct hashmultimap_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks) +{ + ; + if (capacity == 0 || load <= 0) + return ((void *)0); + if (capacity >= 0xffffffffffffffffULL * load) + return ((void *)0); + if (!f_key || !f_val) + return ((void *)0); + if (!alloc) + alloc = &cmc_alloc_node_default; + size_t real_capacity = hmm_impl_calculate_size(capacity / load); + struct hashmultimap *_map_ = alloc->malloc(sizeof(struct hashmultimap)); + if (!_map_) + return ((void *)0); + _map_->buffer = alloc->calloc(real_capacity, sizeof(struct hashmultimap_entry *[2])); + if (!_map_->buffer) + { + alloc->free(_map_); + return ((void *)0); + } + _map_->count = 0; + _map_->capacity = real_capacity; + _map_->load = load; + _map_->flag = CMC_FLAG_OK; + _map_->f_key = f_key; + _map_->f_val = f_val; + _map_->alloc = alloc; + (_map_)->callbacks = callbacks; + return _map_; +} +void hmm_clear(struct hashmultimap *_map_) +{ + for (size_t i = 0; i < _map_->capacity; i++) + { + struct hashmultimap_entry *scan = _map_->buffer[i][0]; + while (scan) + { + struct hashmultimap_entry *next = scan->next; + if (_map_->f_key->free) + _map_->f_key->free(scan->key); + if (_map_->f_val->free) + _map_->f_val->free(scan->value); + _map_->alloc->free(scan); + scan = next; + } + } + memset(_map_->buffer, 0, sizeof(struct hashmultimap_entry *[2]) * _map_->capacity); + _map_->count = 0; + _map_->flag = CMC_FLAG_OK; +} +void hmm_free(struct hashmultimap *_map_) +{ + size_t index = 0; + while (index < _map_->capacity) + { + struct hashmultimap_entry *scan = _map_->buffer[index][0]; + if (scan) + { + if (scan->next == ((void *)0) && scan->prev == ((void *)0)) + { + if (_map_->f_key->free) + _map_->f_key->free(scan->key); + if (_map_->f_val->free) + _map_->f_val->free(scan->value); + _map_->alloc->free(scan); + } + else + { + while (scan) + { + struct hashmultimap_entry *tmp = scan; + scan = scan->next; + if (_map_->f_key->free) + _map_->f_key->free(tmp->key); + if (_map_->f_val->free) + _map_->f_val->free(tmp->value); + _map_->alloc->free(tmp); + } + } + } + index++; + } + _map_->alloc->free(_map_->buffer); + _map_->alloc->free(_map_); +} +void hmm_customize(struct hashmultimap *_map_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks) +{ + ; + if (!alloc) + _map_->alloc = &cmc_alloc_node_default; + else + _map_->alloc = alloc; + (_map_)->callbacks = callbacks; + _map_->flag = CMC_FLAG_OK; +} +_Bool hmm_insert(struct hashmultimap *_map_, size_t key, size_t value) +{ + if (hmm_full(_map_)) + { + if (!hmm_resize(_map_, _map_->capacity + 1)) + return 0; + } + size_t hash = _map_->f_key->hash(key); + size_t pos = hash % _map_->capacity; + struct hashmultimap_entry *entry = hmm_impl_new_entry(_map_, key, value); + if (_map_->buffer[pos][0] == ((void *)0)) + { + _map_->buffer[pos][0] = entry; + _map_->buffer[pos][1] = entry; + } + else + { + entry->prev = _map_->buffer[pos][1]; + _map_->buffer[pos][1]->next = entry; + _map_->buffer[pos][1] = entry; + } + _map_->count++; + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->create) + (_map_)->callbacks->create(); + ; + return 1; +} +_Bool hmm_update(struct hashmultimap *_map_, size_t key, size_t new_value, size_t *old_value) +{ + if (hmm_empty(_map_)) + { + _map_->flag = CMC_FLAG_EMPTY; + return 0; + } + struct hashmultimap_entry *entry = hmm_impl_get_entry(_map_, key); + if (!entry) + { + _map_->flag = CMC_FLAG_NOT_FOUND; + return 0; + } + if (old_value) + *old_value = entry->value; + entry->value = new_value; + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->update) + (_map_)->callbacks->update(); + ; + return 1; +} +size_t hmm_update_all(struct hashmultimap *_map_, size_t key, size_t new_value, size_t **old_values) +{ + if (hmm_empty(_map_)) + { + _map_->flag = CMC_FLAG_EMPTY; + return 0; + } + size_t hash = _map_->f_key->hash(key); + struct hashmultimap_entry *entry = _map_->buffer[hash % _map_->capacity][0]; + if (entry == ((void *)0)) + { + _map_->flag = CMC_FLAG_NOT_FOUND; + return 0; + } + if (old_values) + { + size_t total = hmm_impl_key_count(_map_, key); + if (total == 0) + { + _map_->flag = CMC_FLAG_NOT_FOUND; + return 0; + } + *old_values = _map_->alloc->malloc(sizeof(size_t) * total); + if (!(*old_values)) + { + _map_->flag = CMC_FLAG_ALLOC; + return 0; + } + } + size_t index = 0; + while (entry) + { + if (_map_->f_key->cmp(entry->key, key) == 0) + { + if (old_values) + (*old_values)[index] = entry->value; + index++; + entry->value = new_value; + } + entry = entry->next; + } + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->update) + (_map_)->callbacks->update(); + ; + return index; +} +_Bool hmm_remove(struct hashmultimap *_map_, size_t key, size_t *out_value) +{ + if (hmm_empty(_map_)) + { + _map_->flag = CMC_FLAG_EMPTY; + return 0; + } + size_t hash = _map_->f_key->hash(key); + struct hashmultimap_entry **head = &(_map_->buffer[hash % _map_->capacity][0]); + struct hashmultimap_entry **tail = &(_map_->buffer[hash % _map_->capacity][1]); + if (*head == ((void *)0)) + { + _map_->flag = CMC_FLAG_NOT_FOUND; + return 0; + } + struct hashmultimap_entry *entry = *head; + if (entry->next == ((void *)0) && entry->prev == ((void *)0)) + { + if (_map_->f_key->cmp(entry->key, key) == 0) + { + *head = ((void *)0); + *tail = ((void *)0); + if (out_value) + *out_value = entry->value; + } + else + { + _map_->flag = CMC_FLAG_NOT_FOUND; + return 0; + } + } + else + { + _Bool found = 0; + while (entry) + { + if (_map_->f_key->cmp(entry->key, key) == 0) + { + if (*head == entry) + *head = entry->next; + if (*tail == entry) + *tail = entry->prev; + if (entry->prev) + entry->prev->next = entry->next; + if (entry->next) + entry->next->prev = entry->prev; + if (out_value) + *out_value = entry->value; + found = 1; + break; + } + else + entry = entry->next; + } + if (!found) + { + _map_->flag = CMC_FLAG_NOT_FOUND; + return 0; + } + } + _map_->alloc->free(entry); + _map_->count--; + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->delete) + (_map_)->callbacks->delete (); + ; + return 1; +} +size_t hmm_remove_all(struct hashmultimap *_map_, size_t key, size_t **out_values) +{ + if (hmm_empty(_map_)) + { + _map_->flag = CMC_FLAG_EMPTY; + return 0; + } + size_t hash = _map_->f_key->hash(key); + struct hashmultimap_entry **head = &(_map_->buffer[hash % _map_->capacity][0]); + struct hashmultimap_entry **tail = &(_map_->buffer[hash % _map_->capacity][1]); + if (*head == ((void *)0)) + { + _map_->flag = CMC_FLAG_NOT_FOUND; + return 0; + } + if (out_values) + { + size_t total = hmm_impl_key_count(_map_, key); + if (total == 0) + { + _map_->flag = CMC_FLAG_NOT_FOUND; + return 0; + } + *out_values = _map_->alloc->malloc(sizeof(size_t) * total); + if (!(*out_values)) + { + _map_->flag = CMC_FLAG_ALLOC; + return 0; + } + } + size_t index = 0; + struct hashmultimap_entry *entry = *head; + if (entry->next == ((void *)0)) + { + *head = ((void *)0); + *tail = ((void *)0); + if (out_values) + (*out_values)[index] = entry->value; + index++; + _map_->alloc->free(entry); + } + else + { + while (entry) + { + if (_map_->f_key->cmp(entry->key, key) == 0) + { + if (*head == entry) + *head = entry->next; + if (*tail == entry) + *tail = entry->prev; + struct hashmultimap_entry *next = entry->next; + if (entry->prev) + entry->prev->next = entry->next; + if (entry->next) + entry->next->prev = entry->prev; + if (out_values) + (*out_values)[index] = entry->value; + index++; + _map_->alloc->free(entry); + entry = next; + } + else + entry = entry->next; + } + } + _map_->count -= index; + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->delete) + (_map_)->callbacks->delete (); + ; + return index; +} +_Bool hmm_max(struct hashmultimap *_map_, size_t *key, size_t *value) +{ + if (hmm_empty(_map_)) + { + _map_->flag = CMC_FLAG_EMPTY; + return 0; + } + _Bool first = 1; + size_t max_key = (size_t){ 0 }; + size_t max_val = (size_t){ 0 }; + for (size_t i = 0; i < _map_->capacity; i++) + { + struct hashmultimap_entry *scan = _map_->buffer[i][0]; + while (scan) + { + if (first) + { + max_key = scan->key; + max_val = scan->value; + first = 0; + } + else if (_map_->f_key->cmp(scan->key, max_key) > 0) + { + max_key = scan->key; + max_val = scan->value; + } + scan = scan->next; + } + } + if (key) + *key = max_key; + if (value) + *value = max_val; + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->read) + (_map_)->callbacks->read(); + ; + return 1; +} +_Bool hmm_min(struct hashmultimap *_map_, size_t *key, size_t *value) +{ + if (hmm_empty(_map_)) + { + _map_->flag = CMC_FLAG_EMPTY; + return 0; + } + _Bool first = 1; + size_t min_key = (size_t){ 0 }; + size_t min_val = (size_t){ 0 }; + for (size_t i = 0; i < _map_->capacity; i++) + { + struct hashmultimap_entry *scan = _map_->buffer[i][0]; + while (scan) + { + if (first) + { + min_key = scan->key; + min_val = scan->value; + first = 0; + } + else if (_map_->f_key->cmp(scan->key, min_key) < 0) + { + min_key = scan->key; + min_val = scan->value; + } + scan = scan->next; + } + } + if (key) + *key = min_key; + if (value) + *value = min_val; + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->read) + (_map_)->callbacks->read(); + ; + return 1; +} +size_t hmm_get(struct hashmultimap *_map_, size_t key) +{ + if (hmm_empty(_map_)) + { + _map_->flag = CMC_FLAG_EMPTY; + return (size_t){ 0 }; + } + struct hashmultimap_entry *entry = hmm_impl_get_entry(_map_, key); + if (!entry) + { + _map_->flag = CMC_FLAG_NOT_FOUND; + return (size_t){ 0 }; + } + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->read) + (_map_)->callbacks->read(); + ; + return entry->value; +} +size_t *hmm_get_ref(struct hashmultimap *_map_, size_t key) +{ + if (hmm_empty(_map_)) + { + _map_->flag = CMC_FLAG_EMPTY; + return ((void *)0); + } + struct hashmultimap_entry *entry = hmm_impl_get_entry(_map_, key); + if (!entry) + { + _map_->flag = CMC_FLAG_NOT_FOUND; + return ((void *)0); + } + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->read) + (_map_)->callbacks->read(); + ; + return &(entry->value); +} +_Bool hmm_contains(struct hashmultimap *_map_, size_t key) +{ + _map_->flag = CMC_FLAG_OK; + _Bool result = hmm_impl_get_entry(_map_, key) != ((void *)0); + if ((_map_)->callbacks && (_map_)->callbacks->read) + (_map_)->callbacks->read(); + ; + return result; +} +_Bool hmm_empty(struct hashmultimap *_map_) +{ + return _map_->count == 0; +} +_Bool hmm_full(struct hashmultimap *_map_) +{ + return (double)_map_->capacity * _map_->load <= (double)_map_->count; +} +size_t hmm_count(struct hashmultimap *_map_) +{ + return _map_->count; +} +size_t hmm_key_count(struct hashmultimap *_map_, size_t key) +{ + return hmm_impl_key_count(_map_, key); +} +size_t hmm_capacity(struct hashmultimap *_map_) +{ + return _map_->capacity; +} +double hmm_load(struct hashmultimap *_map_) +{ + return _map_->load; +} +int hmm_flag(struct hashmultimap *_map_) +{ + return _map_->flag; +} +_Bool hmm_resize(struct hashmultimap *_map_, size_t capacity) +{ + _map_->flag = CMC_FLAG_OK; + if (_map_->capacity == capacity) + goto success; + if (_map_->capacity > capacity / _map_->load) + goto success; + if (capacity >= 0xffffffffffffffffULL * _map_->load) + { + _map_->flag = CMC_FLAG_ERROR; + return 0; + } + size_t theoretical_size = hmm_impl_calculate_size(capacity); + if (theoretical_size < _map_->count / _map_->load) + { + _map_->flag = CMC_FLAG_INVALID; + return 0; + } + struct hashmultimap *_new_map_ = + hmm_new_custom(capacity, _map_->load, _map_->f_key, _map_->f_val, _map_->alloc, ((void *)0)); + if (!_new_map_) + { + _map_->flag = CMC_FLAG_ALLOC; + return 0; + } + for (size_t i = 0; i < _map_->capacity; i++) + { + struct hashmultimap_entry *scan = _map_->buffer[i][0]; + while (scan) + { + hmm_insert(_new_map_, scan->key, scan->value); + scan = scan->next; + } + } + if (_map_->count != _new_map_->count) + { + hmm_free(_new_map_); + _map_->flag = CMC_FLAG_ERROR; + return 0; + } + struct hashmultimap_entry *(*tmp_b)[2] = _map_->buffer; + _map_->buffer = _new_map_->buffer; + _new_map_->buffer = tmp_b; + size_t tmp_c = _map_->capacity; + _map_->capacity = _new_map_->capacity; + _new_map_->capacity = tmp_c; + _new_map_->f_key = &(struct hashmultimap_fkey){ ((void *)0) }; + _new_map_->f_val = &(struct hashmultimap_fval){ ((void *)0) }; + hmm_free(_new_map_); +success: + if ((_map_)->callbacks && (_map_)->callbacks->resize) + (_map_)->callbacks->resize(); + ; + return 1; +} +struct hashmultimap *hmm_copy_of(struct hashmultimap *_map_) +{ + struct hashmultimap *result = hmm_new_custom(_map_->capacity * _map_->load, _map_->load, _map_->f_key, _map_->f_val, + _map_->alloc, ((void *)0)); + if (!result) + { + _map_->flag = CMC_FLAG_ERROR; + return ((void *)0); + } + for (size_t i = 0; i < _map_->capacity; i++) + { + struct hashmultimap_entry *scan = _map_->buffer[i][0]; + while (scan) + { + size_t key; + size_t value; + if (_map_->f_key->cpy) + key = _map_->f_key->cpy(scan->key); + else + key = scan->key; + if (_map_->f_val->cpy) + value = _map_->f_val->cpy(scan->value); + else + value = scan->value; + hmm_insert(result, key, value); + scan = scan->next; + } + } + (result)->callbacks = _map_->callbacks; + _map_->flag = CMC_FLAG_OK; + return result; +} +_Bool hmm_equals(struct hashmultimap *_map1_, struct hashmultimap *_map2_) +{ + _map1_->flag = CMC_FLAG_OK; + _map2_->flag = CMC_FLAG_OK; + if (_map1_->count != _map2_->count) + return 0; + struct hashmultimap *_map_a_; + struct hashmultimap *_map_b_; + _map_a_ = _map1_->capacity < _map2_->capacity ? _map1_ : _map2_; + _map_b_ = _map_a_ == _map1_ ? _map2_ : _map1_; + for (size_t i = 0; i < _map_a_->capacity; i++) + { + struct hashmultimap_entry *scan = _map_a_->buffer[i][0]; + while (scan) + { + if (hmm_impl_key_count(_map_a_, scan->key) != hmm_impl_key_count(_map_b_, scan->key)) + return 0; + scan = scan->next; + } + } + return 1; +} +struct hashmultimap_entry *hmm_impl_new_entry(struct hashmultimap *_map_, size_t key, size_t value) +{ + struct hashmultimap_entry *entry = _map_->alloc->malloc(sizeof(struct hashmultimap_entry)); + if (!entry) + return ((void *)0); + entry->key = key; + entry->value = value; + entry->next = ((void *)0); + entry->prev = ((void *)0); + return entry; +} +struct hashmultimap_entry *hmm_impl_get_entry(struct hashmultimap *_map_, size_t key) +{ + size_t hash = _map_->f_key->hash(key); + struct hashmultimap_entry *entry = _map_->buffer[hash % _map_->capacity][0]; + while (entry) + { + if (_map_->f_key->cmp(entry->key, key) == 0) + return entry; + entry = entry->next; + } + return ((void *)0); +} +size_t hmm_impl_key_count(struct hashmultimap *_map_, size_t key) +{ + size_t hash = _map_->f_key->hash(key); + struct hashmultimap_entry *entry = _map_->buffer[hash % _map_->capacity][0]; + size_t total_count = 0; + if (!entry) + return total_count; + while (entry) + { + if (_map_->f_key->cmp(entry->key, key) == 0) + total_count++; + entry = entry->next; + } + return total_count; +} +size_t hmm_impl_calculate_size(size_t required) +{ + const size_t count = sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]); + if (cmc_hashtable_primes[count - 1] < required) + return required; + size_t i = 0; + while (cmc_hashtable_primes[i] < required) + i++; + return cmc_hashtable_primes[i]; +} +struct hashmultimap_iter hmm_iter_start(struct hashmultimap *target) +{ + struct hashmultimap_iter iter; + iter.target = target; + iter.curr_entry = ((void *)0); + iter.cursor = 0; + iter.index = 0; + iter.first = 0; + iter.last = 0; + iter.start = 1; + iter.end = hmm_empty(target); + if (!hmm_empty(target)) + { + for (size_t i = 0; i < target->capacity; i++) + { + struct hashmultimap_entry *entry = target->buffer[i][0]; + if (entry && entry != ((void *)1)) + { + iter.curr_entry = target->buffer[i][0]; + iter.first = i; + break; + } + } + iter.cursor = iter.first; + for (size_t i = target->capacity; i > 0; i--) + { + struct hashmultimap_entry *entry = target->buffer[i - 1][1]; + if (entry && entry != ((void *)1)) + { + iter.last = i - 1; + break; + } + } + } + return iter; +} +struct hashmultimap_iter hmm_iter_end(struct hashmultimap *target) +{ + struct hashmultimap_iter iter; + iter.target = target; + iter.curr_entry = ((void *)0); + iter.cursor = 0; + iter.index = 0; + iter.first = 0; + iter.last = 0; + iter.start = hmm_empty(target); + iter.end = 1; + if (!hmm_empty(target)) + { + for (size_t i = 0; i < target->capacity; i++) + { + struct hashmultimap_entry *entry = target->buffer[i][0]; + if (entry && entry != ((void *)1)) + { + iter.first = i; + break; + } + } + for (size_t i = target->capacity; i > 0; i--) + { + struct hashmultimap_entry *entry = target->buffer[i - 1][1]; + if (entry && entry != ((void *)1)) + { + iter.curr_entry = target->buffer[i - 1][1]; + iter.last = i - 1; + break; + } + } + iter.cursor = iter.last; + iter.index = target->count - 1; + } + return iter; +} +_Bool hmm_iter_at_start(struct hashmultimap_iter *iter) +{ + return hmm_empty(iter->target) || iter->start; +} +_Bool hmm_iter_at_end(struct hashmultimap_iter *iter) +{ + return hmm_empty(iter->target) || iter->end; +} +_Bool hmm_iter_to_start(struct hashmultimap_iter *iter) +{ + if (!hmm_empty(iter->target)) + { + iter->cursor = iter->first; + iter->index = 0; + iter->start = 1; + iter->end = hmm_empty(iter->target); + iter->curr_entry = iter->target->buffer[iter->first][0]; + return 1; + } + return 0; +} +_Bool hmm_iter_to_end(struct hashmultimap_iter *iter) +{ + if (!hmm_empty(iter->target)) + { + iter->cursor = iter->last; + iter->index = iter->target->count - 1; + iter->start = hmm_empty(iter->target); + iter->end = 1; + iter->curr_entry = iter->target->buffer[iter->last][1]; + return 1; + } + return 0; +} +_Bool hmm_iter_next(struct hashmultimap_iter *iter) +{ + if (iter->end) + return 0; + if (iter->curr_entry->next != ((void *)0)) + { + iter->curr_entry = iter->curr_entry->next; + iter->index++; + } + else + { + if (iter->cursor == iter->last) + { + iter->end = 1; + return 0; + } + iter->cursor++; + while (iter->target->buffer[iter->cursor][0] == ((void *)0)) + iter->cursor++; + iter->curr_entry = iter->target->buffer[iter->cursor][0]; + iter->index++; + } + iter->start = hmm_empty(iter->target); + return 1; +} +_Bool hmm_iter_prev(struct hashmultimap_iter *iter) +{ + if (iter->start) + return 0; + if (iter->curr_entry->prev != ((void *)0)) + { + iter->curr_entry = iter->curr_entry->prev; + iter->index--; + } + else + { + if (iter->cursor == iter->first) + { + iter->start = 1; + return 0; + } + iter->cursor--; + while (iter->target->buffer[iter->cursor][1] == ((void *)0)) + iter->cursor--; + iter->curr_entry = iter->target->buffer[iter->cursor][1]; + iter->index--; + } + iter->end = hmm_empty(iter->target); + return 1; +} +_Bool hmm_iter_advance(struct hashmultimap_iter *iter, size_t steps) +{ + if (iter->end) + return 0; + if (iter->index + 1 == iter->target->count) + { + iter->end = 1; + return 0; + } + if (steps == 0 || iter->index + steps >= iter->target->count) + return 0; + for (size_t i = 0; i < steps; i++) + hmm_iter_next(iter); + return 1; +} +_Bool hmm_iter_rewind(struct hashmultimap_iter *iter, size_t steps) +{ + if (iter->start) + return 0; + if (iter->index == 0) + { + iter->start = 1; + return 0; + } + if (steps == 0 || iter->index < steps) + return 0; + for (size_t i = 0; i < steps; i++) + hmm_iter_prev(iter); + return 1; +} +_Bool hmm_iter_go_to(struct hashmultimap_iter *iter, size_t index) +{ + if (index >= iter->target->count) + return 0; + if (iter->index > index) + return hmm_iter_rewind(iter, iter->index - index); + else if (iter->index < index) + return hmm_iter_advance(iter, index - iter->index); + return 1; +} +size_t hmm_iter_key(struct hashmultimap_iter *iter) +{ + if (hmm_empty(iter->target)) + return (size_t){ 0 }; + return iter->curr_entry->key; +} +size_t hmm_iter_value(struct hashmultimap_iter *iter) +{ + if (hmm_empty(iter->target)) + return (size_t){ 0 }; + return iter->curr_entry->value; +} +size_t *hmm_iter_rvalue(struct hashmultimap_iter *iter) +{ + if (hmm_empty(iter->target)) + return ((void *)0); + return &(iter->curr_entry->value); +} +size_t hmm_iter_index(struct hashmultimap_iter *iter) +{ + return iter->index; +} +_Bool hmm_to_string(struct hashmultimap *_map_, FILE *fptr) +{ + struct hashmultimap *m_ = _map_; + return 0 <= fprintf(fptr, + "struct %s<%s, %s> " + "at %p { " + "buffer:%p, " + "capacity:%" + "I64u" + ", " + "count:%" + "I64u" + ", " + "load:%lf, " + "flag:%d, " + "f_key:%p, " + "f_val:%p, " + "alloc:%p, " + "callbacks:%p }", + "hashmultimap", "size_t", "size_t", m_, m_->buffer, m_->capacity, m_->count, m_->load, m_->flag, + m_->f_key, m_->f_val, m_->alloc, (m_)->callbacks); +} +_Bool hmm_print(struct hashmultimap *_map_, FILE *fptr, const char *start, const char *separator, const char *end, + const char *key_val_sep) +{ + fprintf(fptr, "%s", start); + size_t last = 0; + for (size_t i = _map_->capacity; i > 0; i--) + { + struct hashmultimap_entry *entry = _map_->buffer[i - 1][1]; + if (entry && entry != ((void *)1)) + { + last = i - 1; + break; + } + } + for (size_t i = 0; i < _map_->capacity; i++) + { + struct hashmultimap_entry *scan = _map_->buffer[i][0]; + while (scan != ((void *)0)) + { + if (!_map_->f_key->str(fptr, scan->key)) + return 0; + fprintf(fptr, "%s", key_val_sep); + if (!_map_->f_val->str(fptr, scan->value)) + return 0; + scan = scan->next; + if (i + 1 < last) + fprintf(fptr, "%s", separator); + } + } + fprintf(fptr, "%s", end); + return 1; +} diff --git a/tests/src/tst_cmc_hashmultiset.c b/tests/src/tst_cmc_hashmultiset.c index 0a9f492..d10d4b8 100644 --- a/tests/src/tst_cmc_hashmultiset.c +++ b/tests/src/tst_cmc_hashmultiset.c @@ -1,7 +1,972 @@ - #include "tst_cmc_hashmultiset.h" +#include "tst_cmc_hashmultiset.h" - - static size_t hms_impl_multiplicity_of(struct hashmultiset * _set_, size_t value); static struct hashmultiset_entry * hms_impl_insert_and_return(struct hashmultiset * _set_, size_t value, _Bool *new_node); static struct hashmultiset_entry * hms_impl_get_entry(struct hashmultiset * _set_, size_t value); static size_t hms_impl_calculate_size(size_t required); struct hashmultiset *hms_new(size_t capacity, double load, struct hashmultiset_fval * f_val) { return hms_new_custom(capacity, load, f_val, ((void *)0), ((void *)0)); } struct hashmultiset *hms_new_custom(size_t capacity, double load, struct hashmultiset_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (capacity == 0 || load <= 0 || load >= 1) return ((void *)0); if (capacity >= 0xffffffffffffffffULL * load) return ((void *)0); if (!f_val) return ((void *)0); size_t real_capacity = hms_impl_calculate_size(capacity / load); if (!alloc) alloc = &cmc_alloc_node_default; struct hashmultiset *_set_ = alloc->malloc(sizeof(struct hashmultiset)); if (!_set_) return ((void *)0); _set_->buffer = alloc->calloc(real_capacity, sizeof(struct hashmultiset_entry)); if (!_set_->buffer) { alloc->free(_set_); return ((void *)0); } _set_->count = 0; _set_->cardinality = 0; _set_->capacity = real_capacity; _set_->load = load; _set_->flag = CMC_FLAG_OK; _set_->f_val = f_val; _set_->alloc = alloc; (_set_)->callbacks = callbacks; return _set_; } void hms_clear(struct hashmultiset * _set_) { if (_set_->f_val->free) { for (size_t i = 0; i < _set_->capacity; i++) { struct hashmultiset_entry *entry = &(_set_->buffer[i]); if (entry->state == CMC_ES_FILLED) { _set_->f_val->free(entry->value); } } } memset(_set_->buffer, 0, sizeof(struct hashmultiset_entry) * _set_->capacity); _set_->count = 0; _set_->flag = CMC_FLAG_OK; } void hms_free(struct hashmultiset * _set_) { if (_set_->f_val->free) { for (size_t i = 0; i < _set_->capacity; i++) { struct hashmultiset_entry *entry = &(_set_->buffer[i]); if (entry->state == CMC_ES_FILLED) { _set_->f_val->free(entry->value); } } } _set_->alloc->free(_set_->buffer); _set_->alloc->free(_set_); } void hms_customize(struct hashmultiset * _set_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (!alloc) _set_->alloc = &cmc_alloc_node_default; else _set_->alloc = alloc; (_set_)->callbacks = callbacks; _set_->flag = CMC_FLAG_OK; } _Bool hms_insert(struct hashmultiset * _set_, size_t value) { _Bool new_node; struct hashmultiset_entry *entry = hms_impl_insert_and_return(_set_, value, &new_node); if (!entry) { _set_->flag = CMC_FLAG_ERROR; return 0; } if (!new_node) entry->multiplicity++; _set_->cardinality++; _set_->flag = CMC_FLAG_OK; if ((_set_)->callbacks && (_set_)->callbacks->create) (_set_)->callbacks->create();; return 1; } _Bool hms_insert_many(struct hashmultiset * _set_, size_t value, size_t count) { if (count == 0) goto success; _Bool new_node; struct hashmultiset_entry *entry = hms_impl_insert_and_return(_set_, value, &new_node); if (!entry) { _set_->flag = CMC_FLAG_ERROR; return 0; } if (new_node) entry->multiplicity = count; else entry->multiplicity += count; _set_->cardinality += count; success: _set_->flag = CMC_FLAG_OK; if ((_set_)->callbacks && (_set_)->callbacks->create) (_set_)->callbacks->create();; return 1; } _Bool hms_update(struct hashmultiset * _set_, size_t value, size_t multiplicity) { if (multiplicity == 0) { struct hashmultiset_entry *result = hms_impl_get_entry(_set_, value); if (!result) goto success; _set_->count--; _set_->cardinality -= result->multiplicity; result->value = (size_t){ 0 }; result->multiplicity = 0; result->dist = 0; result->state = CMC_ES_DELETED; goto success; } _Bool new_node; struct hashmultiset_entry *entry = hms_impl_insert_and_return(_set_, value, &new_node); if (!entry) return 0; if (new_node) _set_->cardinality++; _set_->cardinality = (_set_->cardinality - entry->multiplicity) + multiplicity; entry->multiplicity = multiplicity; success: _set_->flag = CMC_FLAG_OK; if ((_set_)->callbacks && (_set_)->callbacks->update) (_set_)->callbacks->update();; return 1; } _Bool hms_remove(struct hashmultiset * _set_, size_t value) { if (hms_empty(_set_)) { _set_->flag = CMC_FLAG_EMPTY; return 0; } struct hashmultiset_entry *result = hms_impl_get_entry(_set_, value); if (!result) { _set_->flag = CMC_FLAG_NOT_FOUND; return 0; } if (result->multiplicity > 1) result->multiplicity--; else { result->value = (size_t){ 0 }; result->multiplicity = 0; result->dist = 0; result->state = CMC_ES_DELETED; _set_->count--; } _set_->cardinality--; _set_->flag = CMC_FLAG_OK; if ((_set_)->callbacks && (_set_)->callbacks->delete) (_set_)->callbacks->delete();; return 1; } size_t hms_remove_all(struct hashmultiset * _set_, size_t value) { if (hms_empty(_set_)) { _set_->flag = CMC_FLAG_EMPTY; return 0; } struct hashmultiset_entry *result = hms_impl_get_entry(_set_, value); if (!result) { _set_->flag = CMC_FLAG_NOT_FOUND; return 0; } size_t removed = result->multiplicity; result->value = (size_t){ 0 }; result->multiplicity = 0; result->dist = 0; result->state = CMC_ES_DELETED; _set_->count--; _set_->cardinality -= removed; _set_->flag = CMC_FLAG_OK; if ((_set_)->callbacks && (_set_)->callbacks->delete) (_set_)->callbacks->delete();; return removed; } _Bool hms_max(struct hashmultiset * _set_, size_t * value) { if (hms_empty(_set_)) { _set_->flag = CMC_FLAG_EMPTY; return 0; } _Bool first = 1; size_t max_val = (size_t){ 0 }; for (size_t i = 0; i < _set_->capacity; i++) { if (_set_->buffer[i].state == CMC_ES_FILLED) { if (first) { max_val = _set_->buffer[i].value; first = 0; } else if (_set_->f_val->cmp(_set_->buffer[i].value, max_val) > 0) { max_val = _set_->buffer[i].value; } } } if (value) *value = max_val; _set_->flag = CMC_FLAG_OK; if ((_set_)->callbacks && (_set_)->callbacks->read) (_set_)->callbacks->read();; return 1; } _Bool hms_min(struct hashmultiset * _set_, size_t * value) { if (hms_empty(_set_)) { _set_->flag = CMC_FLAG_EMPTY; return 0; } _Bool first = 1; size_t min_val = (size_t){ 0 }; for (size_t i = 0; i < _set_->capacity; i++) { if (_set_->buffer[i].state == CMC_ES_FILLED) { if (first) { min_val = _set_->buffer[i].value; first = 0; } else if (_set_->f_val->cmp(_set_->buffer[i].value, min_val) < 0) { min_val = _set_->buffer[i].value; } } } if (value) *value = min_val; _set_->flag = CMC_FLAG_OK; if ((_set_)->callbacks && (_set_)->callbacks->read) (_set_)->callbacks->read();; return 1; } size_t hms_multiplicity_of(struct hashmultiset * _set_, size_t value) { struct hashmultiset_entry *entry = hms_impl_get_entry(_set_, value); _set_->flag = CMC_FLAG_OK; if ((_set_)->callbacks && (_set_)->callbacks->read) (_set_)->callbacks->read();; if (!entry) return 0; return entry->multiplicity; } _Bool hms_contains(struct hashmultiset * _set_, size_t value) { _set_->flag = CMC_FLAG_OK; _Bool result = hms_impl_get_entry(_set_, value) != ((void *)0); if ((_set_)->callbacks && (_set_)->callbacks->read) (_set_)->callbacks->read();; return result; } _Bool hms_empty(struct hashmultiset * _set_) { return _set_->count == 0; } _Bool hms_full(struct hashmultiset * _set_) { return (double)_set_->capacity * _set_->load <= (double)_set_->count; } size_t hms_count(struct hashmultiset * _set_) { return _set_->count; } size_t hms_cardinality(struct hashmultiset * _set_) { return _set_->cardinality; } size_t hms_capacity(struct hashmultiset * _set_) { return _set_->capacity; } double hms_load(struct hashmultiset * _set_) { return _set_->load; } int hms_flag(struct hashmultiset * _set_) { return _set_->flag; } _Bool hms_resize(struct hashmultiset * _set_, size_t capacity) { _set_->flag = CMC_FLAG_OK; if (_set_->capacity == capacity) goto success; if (_set_->capacity > capacity / _set_->load) goto success; if (capacity >= 0xffffffffffffffffULL * _set_->load) { _set_->flag = CMC_FLAG_ERROR; return 0; } size_t theoretical_size = hms_impl_calculate_size(capacity); if (theoretical_size < _set_->count / _set_->load) { _set_->flag = CMC_FLAG_INVALID; return 0; } struct hashmultiset *_new_set_ = hms_new_custom(capacity, _set_->load, _set_->f_val, _set_->alloc, ((void *)0)); if (!_new_set_) { _set_->flag = CMC_FLAG_ERROR; return 0; } for (size_t i = 0; i < _set_->capacity; i++) { if (_set_->buffer[i].state == CMC_ES_FILLED) { size_t value = _set_->buffer[i].value; size_t multiplicity = _set_->buffer[i].multiplicity; struct hashmultiset_entry *entry = hms_impl_insert_and_return(_new_set_, value, ((void *)0)); entry->multiplicity = multiplicity; } } if (_set_->count != _new_set_->count) { hms_free(_new_set_); _set_->flag = CMC_FLAG_ERROR; return 0; } struct hashmultiset_entry *tmp_b = _set_->buffer; _set_->buffer = _new_set_->buffer; _new_set_->buffer = tmp_b; size_t tmp_c = _set_->capacity; _set_->capacity = _new_set_->capacity; _new_set_->capacity = tmp_c; _new_set_->f_val = &(struct hashmultiset_fval){ ((void *)0) }; hms_free(_new_set_); success: if ((_set_)->callbacks && (_set_)->callbacks->resize) (_set_)->callbacks->resize();; return 1; } struct hashmultiset *hms_copy_of(struct hashmultiset * _set_) { struct hashmultiset *result = hms_new_custom(_set_->capacity * _set_->load, _set_->load, _set_->f_val, _set_->alloc, ((void *)0)); if (!result) { _set_->flag = CMC_FLAG_ERROR; return ((void *)0); } (result)->callbacks = _set_->callbacks; if (_set_->f_val->cpy) { for (size_t i = 0; i < _set_->capacity; i++) { struct hashmultiset_entry *scan = &(_set_->buffer[i]); if (scan->state != CMC_ES_EMPTY) { struct hashmultiset_entry *target = &(result->buffer[i]); if (scan->state == CMC_ES_DELETED) target->state = CMC_ES_DELETED; else { target->state = scan->state; target->dist = scan->dist; target->multiplicity = scan->multiplicity; target->value = _set_->f_val->cpy(scan->value); } } } } else memcpy(result->buffer, _set_->buffer, sizeof(struct hashmultiset_entry) * _set_->capacity); result->count = _set_->count; result->cardinality = _set_->cardinality; _set_->flag = CMC_FLAG_OK; return result; } _Bool hms_equals(struct hashmultiset * _set1_, struct hashmultiset * _set2_) { _set1_->flag = CMC_FLAG_OK; _set2_->flag = CMC_FLAG_OK; if (_set1_->count != _set2_->count) return 0; if (_set1_->cardinality != _set2_->cardinality) return 0; if (_set1_->count == 0) return 1; struct hashmultiset *_set_a_; struct hashmultiset *_set_b_; _set_a_ = _set1_->capacity < _set2_->capacity ? _set1_ : _set2_; _set_b_ = _set_a_ == _set1_ ? _set2_ : _set1_; for (size_t i = 0; i < _set_a_->capacity; i++) { if (_set_a_->buffer[i].state == CMC_ES_FILLED) { struct hashmultiset_entry *entry_a = &(_set_a_->buffer[i]); struct hashmultiset_entry *entry_b = hms_impl_get_entry(_set_b_, entry_a->value); if (!entry_b) return 0; if (entry_a->multiplicity != entry_b->multiplicity) return 0; } } return 1; } static size_t hms_impl_multiplicity_of(struct hashmultiset * _set_, size_t value) { struct hashmultiset_entry *entry = hms_impl_get_entry(_set_, value); if (!entry) return 0; return entry->multiplicity; } static struct hashmultiset_entry * hms_impl_insert_and_return(struct hashmultiset * _set_, size_t value, _Bool *new_node) { if (new_node) *new_node = 0; struct hashmultiset_entry *entry = hms_impl_get_entry(_set_, value); if (entry != ((void *)0)) return entry; if (new_node) *new_node = 1; if (hms_full(_set_)) { if (!hms_resize(_set_, _set_->capacity + 1)) return ((void *)0); } size_t hash = _set_->f_val->hash(value); size_t original_pos = hash % _set_->capacity; size_t pos = original_pos; size_t curr_mul = 1; struct hashmultiset_entry *target = &(_set_->buffer[pos]); struct hashmultiset_entry *to_return = ((void *)0); if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) { target->value = value; target->multiplicity = curr_mul; target->dist = pos - original_pos; target->state = CMC_ES_FILLED; to_return = target; } else { while (1) { pos++; target = &(_set_->buffer[pos % _set_->capacity]); if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) { target->value = value; target->multiplicity = curr_mul; target->dist = pos - original_pos; target->state = CMC_ES_FILLED; if (!to_return) to_return = target; break; } else if (target->dist < pos - original_pos) { size_t tmp = target->value; size_t tmp_dist = target->dist; size_t tmp_mul = target->multiplicity; target->value = value; target->dist = pos - original_pos; target->multiplicity = curr_mul; value = tmp; original_pos = pos - tmp_dist; curr_mul = tmp_mul; if (!to_return) to_return = target; } } } _set_->count++; return to_return; } static struct hashmultiset_entry * hms_impl_get_entry(struct hashmultiset * _set_, size_t value) { size_t hash = _set_->f_val->hash(value); size_t pos = hash % _set_->capacity; struct hashmultiset_entry *target = &(_set_->buffer[pos]); while (target->state == CMC_ES_FILLED || target->state == CMC_ES_DELETED) { if (_set_->f_val->cmp(target->value, value) == 0) return target; pos++; target = &(_set_->buffer[pos % _set_->capacity]); } return ((void *)0); } static size_t hms_impl_calculate_size(size_t required) { const size_t count = sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]); if (cmc_hashtable_primes[count - 1] < required) return required; size_t i = 0; while (cmc_hashtable_primes[i] < required) i++; return cmc_hashtable_primes[i]; } struct hashmultiset_iter hms_iter_start(struct hashmultiset * target) { struct hashmultiset_iter iter; iter.target = target; iter.cursor = 0; iter.index = 0; iter.first = 0; iter.last = 0; iter.start = 1; iter.end = hms_empty(target); if (!hms_empty(target)) { for (size_t i = 0; i < target->capacity; i++) { if (target->buffer[i].state == CMC_ES_FILLED) { iter.first = i; break; } } iter.cursor = iter.first; for (size_t i = target->capacity; i > 0; i--) { if (target->buffer[i - 1].state == CMC_ES_FILLED) { iter.last = i - 1; break; } } } return iter; } struct hashmultiset_iter hms_iter_end(struct hashmultiset * target) { struct hashmultiset_iter iter; iter.target = target; iter.cursor = 0; iter.index = 0; iter.first = 0; iter.last = 0; iter.start = hms_empty(target); iter.end = 1; if (!hms_empty(target)) { for (size_t i = 0; i < target->capacity; i++) { if (target->buffer[i].state == CMC_ES_FILLED) { iter.first = i; break; } } for (size_t i = target->capacity; i > 0; i--) { if (target->buffer[i - 1].state == CMC_ES_FILLED) { iter.last = i - 1; break; } } iter.cursor = iter.last; iter.index = target->count - 1; } return iter; } _Bool hms_iter_at_start(struct hashmultiset_iter * iter) { return hms_empty(iter->target) || iter->start; } _Bool hms_iter_at_end(struct hashmultiset_iter * iter) { return hms_empty(iter->target) || iter->end; } _Bool hms_iter_to_start(struct hashmultiset_iter * iter) { if (!hms_empty(iter->target)) { iter->cursor = iter->first; iter->index = 0; iter->start = 1; iter->end = hms_empty(iter->target); return 1; } return 0; } _Bool hms_iter_to_end(struct hashmultiset_iter * iter) { if (!hms_empty(iter->target)) { iter->cursor = iter->last; iter->index = iter->target->count - 1; iter->start = hms_empty(iter->target); iter->end = 1; return 1; } return 0; } _Bool hms_iter_next(struct hashmultiset_iter * iter) { if (iter->end) return 0; if (iter->index + 1 == iter->target->count) { iter->end = 1; return 0; } iter->start = hms_empty(iter->target); struct hashmultiset_entry *scan = &(iter->target->buffer[iter->cursor]); iter->index++; while (1) { iter->cursor++; scan = &(iter->target->buffer[iter->cursor]); if (scan->state == CMC_ES_FILLED) break; } return 1; } _Bool hms_iter_prev(struct hashmultiset_iter * iter) { if (iter->start) return 0; if (iter->index == 0) { iter->start = 1; return 0; } iter->end = hms_empty(iter->target); struct hashmultiset_entry *scan = &(iter->target->buffer[iter->cursor]); iter->index--; while (1) { iter->cursor--; scan = &(iter->target->buffer[iter->cursor]); if (scan->state == CMC_ES_FILLED) break; } return 1; } _Bool hms_iter_advance(struct hashmultiset_iter * iter, size_t steps) { if (iter->end) return 0; if (iter->index + 1 == iter->target->count) { iter->end = 1; return 0; } if (steps == 0 || iter->index + steps >= iter->target->count) return 0; for (size_t i = 0; i < steps; i++) hms_iter_next(iter); return 1; } _Bool hms_iter_rewind(struct hashmultiset_iter * iter, size_t steps) { if (iter->start) return 0; if (iter->index == 0) { iter->start = 1; return 0; } if (steps == 0 || iter->index < steps) return 0; for (size_t i = 0; i < steps; i++) hms_iter_prev(iter); return 1; } _Bool hms_iter_go_to(struct hashmultiset_iter * iter, size_t index) { if (index >= iter->target->count) return 0; if (iter->index > index) return hms_iter_rewind(iter, iter->index - index); else if (iter->index < index) return hms_iter_advance(iter, index - iter->index); return 1; } size_t hms_iter_value(struct hashmultiset_iter * iter) { if (hms_empty(iter->target)) return (size_t){ 0 }; return iter->target->buffer[iter->cursor].value; } size_t hms_iter_multiplicity(struct hashmultiset_iter * iter) { if (hms_empty(iter->target)) return 0; return iter->target->buffer[iter->cursor].multiplicity; } size_t hms_iter_index(struct hashmultiset_iter * iter) { return iter->index; } struct hashmultiset *hms_union(struct hashmultiset * _set1_, struct hashmultiset * _set2_) { struct hashmultiset *_set_r_ = hms_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, ((void *)0)); if (!_set_r_) return ((void *)0); struct hashmultiset_iter iter1 = hms_iter_start(_set1_); struct hashmultiset_iter iter2 = hms_iter_start(_set2_); for (; !hms_iter_at_end(&iter1); hms_iter_next(&iter1)) { size_t value = hms_iter_value(&iter1); size_t m1 = hms_iter_multiplicity(&iter1); size_t m2 = hms_impl_multiplicity_of(_set2_, value); size_t max_ = m1 > m2 ? m1 : m2; hms_update(_set_r_, value, max_); } for (; !hms_iter_at_end(&iter2); hms_iter_next(&iter2)) { size_t value = hms_iter_value(&iter2); size_t m1 = hms_impl_multiplicity_of(_set1_, value); size_t m2 = hms_iter_multiplicity(&iter2); size_t max_ = m1 > m2 ? m1 : m2; hms_update(_set_r_, value, max_); } (_set_r_)->callbacks = _set1_->callbacks; return _set_r_; } struct hashmultiset *hms_intersection(struct hashmultiset * _set1_, struct hashmultiset * _set2_) { struct hashmultiset *_set_r_ = hms_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, ((void *)0)); if (!_set_r_) return ((void *)0); struct hashmultiset *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; struct hashmultiset *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; struct hashmultiset_iter iter = hms_iter_start(_set_A_); for (; !hms_iter_at_end(&iter); hms_iter_next(&iter)) { size_t value = hms_iter_value(&iter); size_t m1 = hms_iter_multiplicity(&iter); size_t m2 = hms_impl_multiplicity_of(_set_B_, value); size_t max_ = m1 < m2 ? m1 : m2; hms_update(_set_r_, value, max_); } (_set_r_)->callbacks = _set1_->callbacks; return _set_r_; } struct hashmultiset *hms_difference(struct hashmultiset * _set1_, struct hashmultiset * _set2_) { struct hashmultiset *_set_r_ = hms_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, ((void *)0)); if (!_set_r_) return ((void *)0); struct hashmultiset_iter iter = hms_iter_start(_set1_); for (; !hms_iter_at_end(&iter); hms_iter_next(&iter)) { size_t value = hms_iter_value(&iter); size_t m1 = hms_iter_multiplicity(&iter); size_t m2 = hms_impl_multiplicity_of(_set2_, value); if (m1 > m2) hms_update(_set_r_, value, m1 - m2); } (_set_r_)->callbacks = _set1_->callbacks; return _set_r_; } struct hashmultiset *hms_summation(struct hashmultiset * _set1_, struct hashmultiset * _set2_) { struct hashmultiset *_set_r_ = hms_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, ((void *)0)); if (!_set_r_) return ((void *)0); struct hashmultiset_iter iter1 = hms_iter_start(_set1_); struct hashmultiset_iter iter2 = hms_iter_start(_set2_); for (; !hms_iter_at_end(&iter1); hms_iter_next(&iter1)) { hms_insert_many (_set_r_, hms_iter_value(&iter1), hms_iter_multiplicity(&iter1)); } for (; !hms_iter_at_end(&iter2); hms_iter_next(&iter2)) { hms_insert_many (_set_r_, hms_iter_value(&iter2), hms_iter_multiplicity(&iter2)); } (_set_r_)->callbacks = _set1_->callbacks; return _set_r_; } struct hashmultiset *hms_symmetric_difference(struct hashmultiset * _set1_, struct hashmultiset * _set2_) { struct hashmultiset *_set_r_ = hms_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, ((void *)0)); if (!_set_r_) return ((void *)0); struct hashmultiset_iter iter1 = hms_iter_start(_set1_); struct hashmultiset_iter iter2 = hms_iter_start(_set2_); for (; !hms_iter_at_end(&iter1); hms_iter_next(&iter1)) { size_t value = hms_iter_value(&iter1); size_t m1 = hms_iter_multiplicity(&iter1); size_t m2 = hms_impl_multiplicity_of(_set2_, value); if (m1 != m2) { if (m1 > m2) hms_update(_set_r_, value, m1 - m2); else hms_update(_set_r_, value, m2 - m1); } } for (; !hms_iter_at_end(&iter2); hms_iter_next(&iter2)) { size_t value = hms_iter_value(&iter2); size_t m1 = hms_impl_multiplicity_of(_set1_, value); size_t m2 = hms_iter_multiplicity(&iter2); if (m1 != m2) { if (m1 > m2) hms_update(_set_r_, value, m1 - m2); else hms_update(_set_r_, value, m2 - m1); } } (_set_r_)->callbacks = _set1_->callbacks; return _set_r_; } _Bool hms_is_subset(struct hashmultiset * _set1_, struct hashmultiset * _set2_) { if (_set1_->count > _set2_->count) return 0; if (hms_empty(_set1_)) return 1; struct hashmultiset_iter iter = hms_iter_start(_set1_); for (; !hms_iter_at_end(&iter); hms_iter_next(&iter)) { size_t value = hms_iter_value(&iter); size_t m1 = hms_iter_multiplicity(&iter); size_t m2 = hms_impl_multiplicity_of(_set2_, value); if (m1 > m2) return 0; } return 1; } _Bool hms_is_superset(struct hashmultiset * _set1_, struct hashmultiset * _set2_) { return hms_is_subset(_set2_, _set1_); } _Bool hms_is_proper_subset(struct hashmultiset * _set1_, struct hashmultiset * _set2_) { if (_set1_->count >= _set2_->count) return 0; if (hms_empty(_set1_)) { if (!hms_empty(_set2_)) return 1; else return 0; } struct hashmultiset_iter iter = hms_iter_start(_set1_); for (; !hms_iter_at_end(&iter); hms_iter_next(&iter)) { size_t value = hms_iter_value(&iter); size_t m1 = hms_iter_multiplicity(&iter); size_t m2 = hms_impl_multiplicity_of(_set2_, value); if (m1 >= m2) return 0; } return 1; } _Bool hms_is_proper_superset(struct hashmultiset * _set1_, struct hashmultiset * _set2_) { return hms_is_proper_subset(_set2_, _set1_); } _Bool hms_is_disjointset(struct hashmultiset * _set1_, struct hashmultiset * _set2_) { if (hms_empty(_set1_)) return 1; struct hashmultiset_iter iter = hms_iter_start(_set1_); for (; !hms_iter_at_end(&iter); hms_iter_next(&iter)) { size_t value = hms_iter_value(&iter); if (hms_impl_get_entry(_set2_, value) != ((void *)0)) return 0; } return 1; } _Bool hms_to_string(struct hashmultiset * _set_, FILE * fptr) { struct hashmultiset *s_ = _set_; return 0 <= fprintf(fptr, "struct %s<%s> " "at %p { " "buffer:%p, " "capacity:%" "I64u" ", " "count:%" "I64u" ", " "cardinality:%" "I64u" ", " "load:%lf, " "flag:%d, " "f_val:%p, " "alloc:%p, " "callbacks:%p }", "hashmultiset", "size_t", s_, s_->buffer, s_->capacity, s_->count, s_->cardinality, s_->load, s_->flag, s_->f_val, s_->alloc, (s_)->callbacks); } _Bool hms_print(struct hashmultiset * _set_, FILE * fptr, const char *start, const char *separator, const char *end, const char *val_mul_sep) { fprintf(fptr, "%s", start); size_t last = 0; for (size_t i = _set_->capacity; i > 0; i--) { if ((_set_->buffer[i - 1]).state == CMC_ES_FILLED) { last = i - 1; break; } } for (size_t i = 0; i < _set_->capacity; i++) { struct hashmultiset_entry *entry = &(_set_->buffer[i]); if (entry->state == CMC_ES_FILLED) { if (!_set_->f_val->str(fptr, entry->value)) return 0; fprintf(fptr, "%s", val_mul_sep); if (fprintf(fptr, "%" "I64u" "", entry->multiplicity) < 0) return 0; if (i + 1 < last) fprintf(fptr, "%s", separator); } } fprintf(fptr, "%s", end); return 1; } - - \ No newline at end of file +static size_t hms_impl_multiplicity_of(struct hashmultiset *_set_, size_t value); +static struct hashmultiset_entry *hms_impl_insert_and_return(struct hashmultiset *_set_, size_t value, _Bool *new_node); +static struct hashmultiset_entry *hms_impl_get_entry(struct hashmultiset *_set_, size_t value); +static size_t hms_impl_calculate_size(size_t required); +struct hashmultiset *hms_new(size_t capacity, double load, struct hashmultiset_fval *f_val) +{ + return hms_new_custom(capacity, load, f_val, ((void *)0), ((void *)0)); +} +struct hashmultiset *hms_new_custom(size_t capacity, double load, struct hashmultiset_fval *f_val, + struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks) +{ + ; + if (capacity == 0 || load <= 0 || load >= 1) + return ((void *)0); + if (capacity >= 0xffffffffffffffffULL * load) + return ((void *)0); + if (!f_val) + return ((void *)0); + size_t real_capacity = hms_impl_calculate_size(capacity / load); + if (!alloc) + alloc = &cmc_alloc_node_default; + struct hashmultiset *_set_ = alloc->malloc(sizeof(struct hashmultiset)); + if (!_set_) + return ((void *)0); + _set_->buffer = alloc->calloc(real_capacity, sizeof(struct hashmultiset_entry)); + if (!_set_->buffer) + { + alloc->free(_set_); + return ((void *)0); + } + _set_->count = 0; + _set_->cardinality = 0; + _set_->capacity = real_capacity; + _set_->load = load; + _set_->flag = CMC_FLAG_OK; + _set_->f_val = f_val; + _set_->alloc = alloc; + (_set_)->callbacks = callbacks; + return _set_; +} +void hms_clear(struct hashmultiset *_set_) +{ + if (_set_->f_val->free) + { + for (size_t i = 0; i < _set_->capacity; i++) + { + struct hashmultiset_entry *entry = &(_set_->buffer[i]); + if (entry->state == CMC_ES_FILLED) + { + _set_->f_val->free(entry->value); + } + } + } + memset(_set_->buffer, 0, sizeof(struct hashmultiset_entry) * _set_->capacity); + _set_->count = 0; + _set_->flag = CMC_FLAG_OK; +} +void hms_free(struct hashmultiset *_set_) +{ + if (_set_->f_val->free) + { + for (size_t i = 0; i < _set_->capacity; i++) + { + struct hashmultiset_entry *entry = &(_set_->buffer[i]); + if (entry->state == CMC_ES_FILLED) + { + _set_->f_val->free(entry->value); + } + } + } + _set_->alloc->free(_set_->buffer); + _set_->alloc->free(_set_); +} +void hms_customize(struct hashmultiset *_set_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks) +{ + ; + if (!alloc) + _set_->alloc = &cmc_alloc_node_default; + else + _set_->alloc = alloc; + (_set_)->callbacks = callbacks; + _set_->flag = CMC_FLAG_OK; +} +_Bool hms_insert(struct hashmultiset *_set_, size_t value) +{ + _Bool new_node; + struct hashmultiset_entry *entry = hms_impl_insert_and_return(_set_, value, &new_node); + if (!entry) + { + _set_->flag = CMC_FLAG_ERROR; + return 0; + } + if (!new_node) + entry->multiplicity++; + _set_->cardinality++; + _set_->flag = CMC_FLAG_OK; + if ((_set_)->callbacks && (_set_)->callbacks->create) + (_set_)->callbacks->create(); + ; + return 1; +} +_Bool hms_insert_many(struct hashmultiset *_set_, size_t value, size_t count) +{ + if (count == 0) + goto success; + _Bool new_node; + struct hashmultiset_entry *entry = hms_impl_insert_and_return(_set_, value, &new_node); + if (!entry) + { + _set_->flag = CMC_FLAG_ERROR; + return 0; + } + if (new_node) + entry->multiplicity = count; + else + entry->multiplicity += count; + _set_->cardinality += count; +success: + _set_->flag = CMC_FLAG_OK; + if ((_set_)->callbacks && (_set_)->callbacks->create) + (_set_)->callbacks->create(); + ; + return 1; +} +_Bool hms_update(struct hashmultiset *_set_, size_t value, size_t multiplicity) +{ + if (multiplicity == 0) + { + struct hashmultiset_entry *result = hms_impl_get_entry(_set_, value); + if (!result) + goto success; + _set_->count--; + _set_->cardinality -= result->multiplicity; + result->value = (size_t){ 0 }; + result->multiplicity = 0; + result->dist = 0; + result->state = CMC_ES_DELETED; + goto success; + } + _Bool new_node; + struct hashmultiset_entry *entry = hms_impl_insert_and_return(_set_, value, &new_node); + if (!entry) + return 0; + if (new_node) + _set_->cardinality++; + _set_->cardinality = (_set_->cardinality - entry->multiplicity) + multiplicity; + entry->multiplicity = multiplicity; +success: + _set_->flag = CMC_FLAG_OK; + if ((_set_)->callbacks && (_set_)->callbacks->update) + (_set_)->callbacks->update(); + ; + return 1; +} +_Bool hms_remove(struct hashmultiset *_set_, size_t value) +{ + if (hms_empty(_set_)) + { + _set_->flag = CMC_FLAG_EMPTY; + return 0; + } + struct hashmultiset_entry *result = hms_impl_get_entry(_set_, value); + if (!result) + { + _set_->flag = CMC_FLAG_NOT_FOUND; + return 0; + } + if (result->multiplicity > 1) + result->multiplicity--; + else + { + result->value = (size_t){ 0 }; + result->multiplicity = 0; + result->dist = 0; + result->state = CMC_ES_DELETED; + _set_->count--; + } + _set_->cardinality--; + _set_->flag = CMC_FLAG_OK; + if ((_set_)->callbacks && (_set_)->callbacks->delete) + (_set_)->callbacks->delete (); + ; + return 1; +} +size_t hms_remove_all(struct hashmultiset *_set_, size_t value) +{ + if (hms_empty(_set_)) + { + _set_->flag = CMC_FLAG_EMPTY; + return 0; + } + struct hashmultiset_entry *result = hms_impl_get_entry(_set_, value); + if (!result) + { + _set_->flag = CMC_FLAG_NOT_FOUND; + return 0; + } + size_t removed = result->multiplicity; + result->value = (size_t){ 0 }; + result->multiplicity = 0; + result->dist = 0; + result->state = CMC_ES_DELETED; + _set_->count--; + _set_->cardinality -= removed; + _set_->flag = CMC_FLAG_OK; + if ((_set_)->callbacks && (_set_)->callbacks->delete) + (_set_)->callbacks->delete (); + ; + return removed; +} +_Bool hms_max(struct hashmultiset *_set_, size_t *value) +{ + if (hms_empty(_set_)) + { + _set_->flag = CMC_FLAG_EMPTY; + return 0; + } + _Bool first = 1; + size_t max_val = (size_t){ 0 }; + for (size_t i = 0; i < _set_->capacity; i++) + { + if (_set_->buffer[i].state == CMC_ES_FILLED) + { + if (first) + { + max_val = _set_->buffer[i].value; + first = 0; + } + else if (_set_->f_val->cmp(_set_->buffer[i].value, max_val) > 0) + { + max_val = _set_->buffer[i].value; + } + } + } + if (value) + *value = max_val; + _set_->flag = CMC_FLAG_OK; + if ((_set_)->callbacks && (_set_)->callbacks->read) + (_set_)->callbacks->read(); + ; + return 1; +} +_Bool hms_min(struct hashmultiset *_set_, size_t *value) +{ + if (hms_empty(_set_)) + { + _set_->flag = CMC_FLAG_EMPTY; + return 0; + } + _Bool first = 1; + size_t min_val = (size_t){ 0 }; + for (size_t i = 0; i < _set_->capacity; i++) + { + if (_set_->buffer[i].state == CMC_ES_FILLED) + { + if (first) + { + min_val = _set_->buffer[i].value; + first = 0; + } + else if (_set_->f_val->cmp(_set_->buffer[i].value, min_val) < 0) + { + min_val = _set_->buffer[i].value; + } + } + } + if (value) + *value = min_val; + _set_->flag = CMC_FLAG_OK; + if ((_set_)->callbacks && (_set_)->callbacks->read) + (_set_)->callbacks->read(); + ; + return 1; +} +size_t hms_multiplicity_of(struct hashmultiset *_set_, size_t value) +{ + struct hashmultiset_entry *entry = hms_impl_get_entry(_set_, value); + _set_->flag = CMC_FLAG_OK; + if ((_set_)->callbacks && (_set_)->callbacks->read) + (_set_)->callbacks->read(); + ; + if (!entry) + return 0; + return entry->multiplicity; +} +_Bool hms_contains(struct hashmultiset *_set_, size_t value) +{ + _set_->flag = CMC_FLAG_OK; + _Bool result = hms_impl_get_entry(_set_, value) != ((void *)0); + if ((_set_)->callbacks && (_set_)->callbacks->read) + (_set_)->callbacks->read(); + ; + return result; +} +_Bool hms_empty(struct hashmultiset *_set_) +{ + return _set_->count == 0; +} +_Bool hms_full(struct hashmultiset *_set_) +{ + return (double)_set_->capacity * _set_->load <= (double)_set_->count; +} +size_t hms_count(struct hashmultiset *_set_) +{ + return _set_->count; +} +size_t hms_cardinality(struct hashmultiset *_set_) +{ + return _set_->cardinality; +} +size_t hms_capacity(struct hashmultiset *_set_) +{ + return _set_->capacity; +} +double hms_load(struct hashmultiset *_set_) +{ + return _set_->load; +} +int hms_flag(struct hashmultiset *_set_) +{ + return _set_->flag; +} +_Bool hms_resize(struct hashmultiset *_set_, size_t capacity) +{ + _set_->flag = CMC_FLAG_OK; + if (_set_->capacity == capacity) + goto success; + if (_set_->capacity > capacity / _set_->load) + goto success; + if (capacity >= 0xffffffffffffffffULL * _set_->load) + { + _set_->flag = CMC_FLAG_ERROR; + return 0; + } + size_t theoretical_size = hms_impl_calculate_size(capacity); + if (theoretical_size < _set_->count / _set_->load) + { + _set_->flag = CMC_FLAG_INVALID; + return 0; + } + struct hashmultiset *_new_set_ = hms_new_custom(capacity, _set_->load, _set_->f_val, _set_->alloc, ((void *)0)); + if (!_new_set_) + { + _set_->flag = CMC_FLAG_ERROR; + return 0; + } + for (size_t i = 0; i < _set_->capacity; i++) + { + if (_set_->buffer[i].state == CMC_ES_FILLED) + { + size_t value = _set_->buffer[i].value; + size_t multiplicity = _set_->buffer[i].multiplicity; + struct hashmultiset_entry *entry = hms_impl_insert_and_return(_new_set_, value, ((void *)0)); + entry->multiplicity = multiplicity; + } + } + if (_set_->count != _new_set_->count) + { + hms_free(_new_set_); + _set_->flag = CMC_FLAG_ERROR; + return 0; + } + struct hashmultiset_entry *tmp_b = _set_->buffer; + _set_->buffer = _new_set_->buffer; + _new_set_->buffer = tmp_b; + size_t tmp_c = _set_->capacity; + _set_->capacity = _new_set_->capacity; + _new_set_->capacity = tmp_c; + _new_set_->f_val = &(struct hashmultiset_fval){ ((void *)0) }; + hms_free(_new_set_); +success: + if ((_set_)->callbacks && (_set_)->callbacks->resize) + (_set_)->callbacks->resize(); + ; + return 1; +} +struct hashmultiset *hms_copy_of(struct hashmultiset *_set_) +{ + struct hashmultiset *result = + hms_new_custom(_set_->capacity * _set_->load, _set_->load, _set_->f_val, _set_->alloc, ((void *)0)); + if (!result) + { + _set_->flag = CMC_FLAG_ERROR; + return ((void *)0); + } + (result)->callbacks = _set_->callbacks; + if (_set_->f_val->cpy) + { + for (size_t i = 0; i < _set_->capacity; i++) + { + struct hashmultiset_entry *scan = &(_set_->buffer[i]); + if (scan->state != CMC_ES_EMPTY) + { + struct hashmultiset_entry *target = &(result->buffer[i]); + if (scan->state == CMC_ES_DELETED) + target->state = CMC_ES_DELETED; + else + { + target->state = scan->state; + target->dist = scan->dist; + target->multiplicity = scan->multiplicity; + target->value = _set_->f_val->cpy(scan->value); + } + } + } + } + else + memcpy(result->buffer, _set_->buffer, sizeof(struct hashmultiset_entry) * _set_->capacity); + result->count = _set_->count; + result->cardinality = _set_->cardinality; + _set_->flag = CMC_FLAG_OK; + return result; +} +_Bool hms_equals(struct hashmultiset *_set1_, struct hashmultiset *_set2_) +{ + _set1_->flag = CMC_FLAG_OK; + _set2_->flag = CMC_FLAG_OK; + if (_set1_->count != _set2_->count) + return 0; + if (_set1_->cardinality != _set2_->cardinality) + return 0; + if (_set1_->count == 0) + return 1; + struct hashmultiset *_set_a_; + struct hashmultiset *_set_b_; + _set_a_ = _set1_->capacity < _set2_->capacity ? _set1_ : _set2_; + _set_b_ = _set_a_ == _set1_ ? _set2_ : _set1_; + for (size_t i = 0; i < _set_a_->capacity; i++) + { + if (_set_a_->buffer[i].state == CMC_ES_FILLED) + { + struct hashmultiset_entry *entry_a = &(_set_a_->buffer[i]); + struct hashmultiset_entry *entry_b = hms_impl_get_entry(_set_b_, entry_a->value); + if (!entry_b) + return 0; + if (entry_a->multiplicity != entry_b->multiplicity) + return 0; + } + } + return 1; +} +static size_t hms_impl_multiplicity_of(struct hashmultiset *_set_, size_t value) +{ + struct hashmultiset_entry *entry = hms_impl_get_entry(_set_, value); + if (!entry) + return 0; + return entry->multiplicity; +} +static struct hashmultiset_entry *hms_impl_insert_and_return(struct hashmultiset *_set_, size_t value, _Bool *new_node) +{ + if (new_node) + *new_node = 0; + struct hashmultiset_entry *entry = hms_impl_get_entry(_set_, value); + if (entry != ((void *)0)) + return entry; + if (new_node) + *new_node = 1; + if (hms_full(_set_)) + { + if (!hms_resize(_set_, _set_->capacity + 1)) + return ((void *)0); + } + size_t hash = _set_->f_val->hash(value); + size_t original_pos = hash % _set_->capacity; + size_t pos = original_pos; + size_t curr_mul = 1; + struct hashmultiset_entry *target = &(_set_->buffer[pos]); + struct hashmultiset_entry *to_return = ((void *)0); + if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) + { + target->value = value; + target->multiplicity = curr_mul; + target->dist = pos - original_pos; + target->state = CMC_ES_FILLED; + to_return = target; + } + else + { + while (1) + { + pos++; + target = &(_set_->buffer[pos % _set_->capacity]); + if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) + { + target->value = value; + target->multiplicity = curr_mul; + target->dist = pos - original_pos; + target->state = CMC_ES_FILLED; + if (!to_return) + to_return = target; + break; + } + else if (target->dist < pos - original_pos) + { + size_t tmp = target->value; + size_t tmp_dist = target->dist; + size_t tmp_mul = target->multiplicity; + target->value = value; + target->dist = pos - original_pos; + target->multiplicity = curr_mul; + value = tmp; + original_pos = pos - tmp_dist; + curr_mul = tmp_mul; + if (!to_return) + to_return = target; + } + } + } + _set_->count++; + return to_return; +} +static struct hashmultiset_entry *hms_impl_get_entry(struct hashmultiset *_set_, size_t value) +{ + size_t hash = _set_->f_val->hash(value); + size_t pos = hash % _set_->capacity; + struct hashmultiset_entry *target = &(_set_->buffer[pos]); + while (target->state == CMC_ES_FILLED || target->state == CMC_ES_DELETED) + { + if (_set_->f_val->cmp(target->value, value) == 0) + return target; + pos++; + target = &(_set_->buffer[pos % _set_->capacity]); + } + return ((void *)0); +} +static size_t hms_impl_calculate_size(size_t required) +{ + const size_t count = sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]); + if (cmc_hashtable_primes[count - 1] < required) + return required; + size_t i = 0; + while (cmc_hashtable_primes[i] < required) + i++; + return cmc_hashtable_primes[i]; +} +struct hashmultiset_iter hms_iter_start(struct hashmultiset *target) +{ + struct hashmultiset_iter iter; + iter.target = target; + iter.cursor = 0; + iter.index = 0; + iter.first = 0; + iter.last = 0; + iter.start = 1; + iter.end = hms_empty(target); + if (!hms_empty(target)) + { + for (size_t i = 0; i < target->capacity; i++) + { + if (target->buffer[i].state == CMC_ES_FILLED) + { + iter.first = i; + break; + } + } + iter.cursor = iter.first; + for (size_t i = target->capacity; i > 0; i--) + { + if (target->buffer[i - 1].state == CMC_ES_FILLED) + { + iter.last = i - 1; + break; + } + } + } + return iter; +} +struct hashmultiset_iter hms_iter_end(struct hashmultiset *target) +{ + struct hashmultiset_iter iter; + iter.target = target; + iter.cursor = 0; + iter.index = 0; + iter.first = 0; + iter.last = 0; + iter.start = hms_empty(target); + iter.end = 1; + if (!hms_empty(target)) + { + for (size_t i = 0; i < target->capacity; i++) + { + if (target->buffer[i].state == CMC_ES_FILLED) + { + iter.first = i; + break; + } + } + for (size_t i = target->capacity; i > 0; i--) + { + if (target->buffer[i - 1].state == CMC_ES_FILLED) + { + iter.last = i - 1; + break; + } + } + iter.cursor = iter.last; + iter.index = target->count - 1; + } + return iter; +} +_Bool hms_iter_at_start(struct hashmultiset_iter *iter) +{ + return hms_empty(iter->target) || iter->start; +} +_Bool hms_iter_at_end(struct hashmultiset_iter *iter) +{ + return hms_empty(iter->target) || iter->end; +} +_Bool hms_iter_to_start(struct hashmultiset_iter *iter) +{ + if (!hms_empty(iter->target)) + { + iter->cursor = iter->first; + iter->index = 0; + iter->start = 1; + iter->end = hms_empty(iter->target); + return 1; + } + return 0; +} +_Bool hms_iter_to_end(struct hashmultiset_iter *iter) +{ + if (!hms_empty(iter->target)) + { + iter->cursor = iter->last; + iter->index = iter->target->count - 1; + iter->start = hms_empty(iter->target); + iter->end = 1; + return 1; + } + return 0; +} +_Bool hms_iter_next(struct hashmultiset_iter *iter) +{ + if (iter->end) + return 0; + if (iter->index + 1 == iter->target->count) + { + iter->end = 1; + return 0; + } + iter->start = hms_empty(iter->target); + struct hashmultiset_entry *scan = &(iter->target->buffer[iter->cursor]); + iter->index++; + while (1) + { + iter->cursor++; + scan = &(iter->target->buffer[iter->cursor]); + if (scan->state == CMC_ES_FILLED) + break; + } + return 1; +} +_Bool hms_iter_prev(struct hashmultiset_iter *iter) +{ + if (iter->start) + return 0; + if (iter->index == 0) + { + iter->start = 1; + return 0; + } + iter->end = hms_empty(iter->target); + struct hashmultiset_entry *scan = &(iter->target->buffer[iter->cursor]); + iter->index--; + while (1) + { + iter->cursor--; + scan = &(iter->target->buffer[iter->cursor]); + if (scan->state == CMC_ES_FILLED) + break; + } + return 1; +} +_Bool hms_iter_advance(struct hashmultiset_iter *iter, size_t steps) +{ + if (iter->end) + return 0; + if (iter->index + 1 == iter->target->count) + { + iter->end = 1; + return 0; + } + if (steps == 0 || iter->index + steps >= iter->target->count) + return 0; + for (size_t i = 0; i < steps; i++) + hms_iter_next(iter); + return 1; +} +_Bool hms_iter_rewind(struct hashmultiset_iter *iter, size_t steps) +{ + if (iter->start) + return 0; + if (iter->index == 0) + { + iter->start = 1; + return 0; + } + if (steps == 0 || iter->index < steps) + return 0; + for (size_t i = 0; i < steps; i++) + hms_iter_prev(iter); + return 1; +} +_Bool hms_iter_go_to(struct hashmultiset_iter *iter, size_t index) +{ + if (index >= iter->target->count) + return 0; + if (iter->index > index) + return hms_iter_rewind(iter, iter->index - index); + else if (iter->index < index) + return hms_iter_advance(iter, index - iter->index); + return 1; +} +size_t hms_iter_value(struct hashmultiset_iter *iter) +{ + if (hms_empty(iter->target)) + return (size_t){ 0 }; + return iter->target->buffer[iter->cursor].value; +} +size_t hms_iter_multiplicity(struct hashmultiset_iter *iter) +{ + if (hms_empty(iter->target)) + return 0; + return iter->target->buffer[iter->cursor].multiplicity; +} +size_t hms_iter_index(struct hashmultiset_iter *iter) +{ + return iter->index; +} +struct hashmultiset *hms_union(struct hashmultiset *_set1_, struct hashmultiset *_set2_) +{ + struct hashmultiset *_set_r_ = + hms_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, ((void *)0)); + if (!_set_r_) + return ((void *)0); + struct hashmultiset_iter iter1 = hms_iter_start(_set1_); + struct hashmultiset_iter iter2 = hms_iter_start(_set2_); + for (; !hms_iter_at_end(&iter1); hms_iter_next(&iter1)) + { + size_t value = hms_iter_value(&iter1); + size_t m1 = hms_iter_multiplicity(&iter1); + size_t m2 = hms_impl_multiplicity_of(_set2_, value); + size_t max_ = m1 > m2 ? m1 : m2; + hms_update(_set_r_, value, max_); + } + for (; !hms_iter_at_end(&iter2); hms_iter_next(&iter2)) + { + size_t value = hms_iter_value(&iter2); + size_t m1 = hms_impl_multiplicity_of(_set1_, value); + size_t m2 = hms_iter_multiplicity(&iter2); + size_t max_ = m1 > m2 ? m1 : m2; + hms_update(_set_r_, value, max_); + } + (_set_r_)->callbacks = _set1_->callbacks; + return _set_r_; +} +struct hashmultiset *hms_intersection(struct hashmultiset *_set1_, struct hashmultiset *_set2_) +{ + struct hashmultiset *_set_r_ = + hms_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, ((void *)0)); + if (!_set_r_) + return ((void *)0); + struct hashmultiset *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; + struct hashmultiset *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; + struct hashmultiset_iter iter = hms_iter_start(_set_A_); + for (; !hms_iter_at_end(&iter); hms_iter_next(&iter)) + { + size_t value = hms_iter_value(&iter); + size_t m1 = hms_iter_multiplicity(&iter); + size_t m2 = hms_impl_multiplicity_of(_set_B_, value); + size_t max_ = m1 < m2 ? m1 : m2; + hms_update(_set_r_, value, max_); + } + (_set_r_)->callbacks = _set1_->callbacks; + return _set_r_; +} +struct hashmultiset *hms_difference(struct hashmultiset *_set1_, struct hashmultiset *_set2_) +{ + struct hashmultiset *_set_r_ = + hms_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, ((void *)0)); + if (!_set_r_) + return ((void *)0); + struct hashmultiset_iter iter = hms_iter_start(_set1_); + for (; !hms_iter_at_end(&iter); hms_iter_next(&iter)) + { + size_t value = hms_iter_value(&iter); + size_t m1 = hms_iter_multiplicity(&iter); + size_t m2 = hms_impl_multiplicity_of(_set2_, value); + if (m1 > m2) + hms_update(_set_r_, value, m1 - m2); + } + (_set_r_)->callbacks = _set1_->callbacks; + return _set_r_; +} +struct hashmultiset *hms_summation(struct hashmultiset *_set1_, struct hashmultiset *_set2_) +{ + struct hashmultiset *_set_r_ = + hms_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, ((void *)0)); + if (!_set_r_) + return ((void *)0); + struct hashmultiset_iter iter1 = hms_iter_start(_set1_); + struct hashmultiset_iter iter2 = hms_iter_start(_set2_); + for (; !hms_iter_at_end(&iter1); hms_iter_next(&iter1)) + { + hms_insert_many(_set_r_, hms_iter_value(&iter1), hms_iter_multiplicity(&iter1)); + } + for (; !hms_iter_at_end(&iter2); hms_iter_next(&iter2)) + { + hms_insert_many(_set_r_, hms_iter_value(&iter2), hms_iter_multiplicity(&iter2)); + } + (_set_r_)->callbacks = _set1_->callbacks; + return _set_r_; +} +struct hashmultiset *hms_symmetric_difference(struct hashmultiset *_set1_, struct hashmultiset *_set2_) +{ + struct hashmultiset *_set_r_ = + hms_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, ((void *)0)); + if (!_set_r_) + return ((void *)0); + struct hashmultiset_iter iter1 = hms_iter_start(_set1_); + struct hashmultiset_iter iter2 = hms_iter_start(_set2_); + for (; !hms_iter_at_end(&iter1); hms_iter_next(&iter1)) + { + size_t value = hms_iter_value(&iter1); + size_t m1 = hms_iter_multiplicity(&iter1); + size_t m2 = hms_impl_multiplicity_of(_set2_, value); + if (m1 != m2) + { + if (m1 > m2) + hms_update(_set_r_, value, m1 - m2); + else + hms_update(_set_r_, value, m2 - m1); + } + } + for (; !hms_iter_at_end(&iter2); hms_iter_next(&iter2)) + { + size_t value = hms_iter_value(&iter2); + size_t m1 = hms_impl_multiplicity_of(_set1_, value); + size_t m2 = hms_iter_multiplicity(&iter2); + if (m1 != m2) + { + if (m1 > m2) + hms_update(_set_r_, value, m1 - m2); + else + hms_update(_set_r_, value, m2 - m1); + } + } + (_set_r_)->callbacks = _set1_->callbacks; + return _set_r_; +} +_Bool hms_is_subset(struct hashmultiset *_set1_, struct hashmultiset *_set2_) +{ + if (_set1_->count > _set2_->count) + return 0; + if (hms_empty(_set1_)) + return 1; + struct hashmultiset_iter iter = hms_iter_start(_set1_); + for (; !hms_iter_at_end(&iter); hms_iter_next(&iter)) + { + size_t value = hms_iter_value(&iter); + size_t m1 = hms_iter_multiplicity(&iter); + size_t m2 = hms_impl_multiplicity_of(_set2_, value); + if (m1 > m2) + return 0; + } + return 1; +} +_Bool hms_is_superset(struct hashmultiset *_set1_, struct hashmultiset *_set2_) +{ + return hms_is_subset(_set2_, _set1_); +} +_Bool hms_is_proper_subset(struct hashmultiset *_set1_, struct hashmultiset *_set2_) +{ + if (_set1_->count >= _set2_->count) + return 0; + if (hms_empty(_set1_)) + { + if (!hms_empty(_set2_)) + return 1; + else + return 0; + } + struct hashmultiset_iter iter = hms_iter_start(_set1_); + for (; !hms_iter_at_end(&iter); hms_iter_next(&iter)) + { + size_t value = hms_iter_value(&iter); + size_t m1 = hms_iter_multiplicity(&iter); + size_t m2 = hms_impl_multiplicity_of(_set2_, value); + if (m1 >= m2) + return 0; + } + return 1; +} +_Bool hms_is_proper_superset(struct hashmultiset *_set1_, struct hashmultiset *_set2_) +{ + return hms_is_proper_subset(_set2_, _set1_); +} +_Bool hms_is_disjointset(struct hashmultiset *_set1_, struct hashmultiset *_set2_) +{ + if (hms_empty(_set1_)) + return 1; + struct hashmultiset_iter iter = hms_iter_start(_set1_); + for (; !hms_iter_at_end(&iter); hms_iter_next(&iter)) + { + size_t value = hms_iter_value(&iter); + if (hms_impl_get_entry(_set2_, value) != ((void *)0)) + return 0; + } + return 1; +} +_Bool hms_to_string(struct hashmultiset *_set_, FILE *fptr) +{ + struct hashmultiset *s_ = _set_; + return 0 <= fprintf(fptr, + "struct %s<%s> " + "at %p { " + "buffer:%p, " + "capacity:%" + "I64u" + ", " + "count:%" + "I64u" + ", " + "cardinality:%" + "I64u" + ", " + "load:%lf, " + "flag:%d, " + "f_val:%p, " + "alloc:%p, " + "callbacks:%p }", + "hashmultiset", "size_t", s_, s_->buffer, s_->capacity, s_->count, s_->cardinality, s_->load, + s_->flag, s_->f_val, s_->alloc, (s_)->callbacks); +} +_Bool hms_print(struct hashmultiset *_set_, FILE *fptr, const char *start, const char *separator, const char *end, + const char *val_mul_sep) +{ + fprintf(fptr, "%s", start); + size_t last = 0; + for (size_t i = _set_->capacity; i > 0; i--) + { + if ((_set_->buffer[i - 1]).state == CMC_ES_FILLED) + { + last = i - 1; + break; + } + } + for (size_t i = 0; i < _set_->capacity; i++) + { + struct hashmultiset_entry *entry = &(_set_->buffer[i]); + if (entry->state == CMC_ES_FILLED) + { + if (!_set_->f_val->str(fptr, entry->value)) + return 0; + fprintf(fptr, "%s", val_mul_sep); + if (fprintf(fptr, + "%" + "I64u" + "", + entry->multiplicity) < 0) + return 0; + if (i + 1 < last) + fprintf(fptr, "%s", separator); + } + } + fprintf(fptr, "%s", end); + return 1; +} diff --git a/tests/src/tst_cmc_hashset.c b/tests/src/tst_cmc_hashset.c index f82410a..1e4764b 100644 --- a/tests/src/tst_cmc_hashset.c +++ b/tests/src/tst_cmc_hashset.c @@ -1,7 +1,773 @@ - #include "tst_cmc_hashset.h" +#include "tst_cmc_hashset.h" - - static struct hashset_entry * hs_impl_get_entry(struct hashset * _set_, size_t value); static size_t hs_impl_calculate_size(size_t required); struct hashset *hs_new(size_t capacity, double load, struct hashset_fval * f_val) { return hs_new_custom(capacity, load, f_val, ((void *)0), ((void *)0)); } struct hashset *hs_new_custom(size_t capacity, double load, struct hashset_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (capacity == 0 || load <= 0 || load >= 1) return ((void *)0); if (capacity >= 0xffffffffffffffffULL * load) return ((void *)0); if (!f_val) return ((void *)0); size_t real_capacity = hs_impl_calculate_size(capacity / load); if (!alloc) alloc = &cmc_alloc_node_default; struct hashset *_set_ = alloc->malloc(sizeof(struct hashset)); if (!_set_) return ((void *)0); _set_->buffer = alloc->calloc(real_capacity, sizeof(struct hashset_entry)); if (!_set_->buffer) { alloc->free(_set_); return ((void *)0); } _set_->count = 0; _set_->capacity = real_capacity; _set_->load = load; _set_->flag = CMC_FLAG_OK; _set_->f_val = f_val; _set_->alloc = alloc; (_set_)->callbacks = callbacks; return _set_; } void hs_clear(struct hashset * _set_) { if (_set_->f_val->free) { for (size_t i = 0; i < _set_->capacity; i++) { struct hashset_entry *entry = &(_set_->buffer[i]); if (entry->state == CMC_ES_FILLED) { _set_->f_val->free(entry->value); } } } memset(_set_->buffer, 0, sizeof(struct hashset_entry) * _set_->capacity); _set_->count = 0; _set_->flag = CMC_FLAG_OK; } void hs_free(struct hashset * _set_) { if (_set_->f_val->free) { for (size_t i = 0; i < _set_->capacity; i++) { struct hashset_entry *entry = &(_set_->buffer[i]); if (entry->state == CMC_ES_FILLED) { _set_->f_val->free(entry->value); } } } _set_->alloc->free(_set_->buffer); _set_->alloc->free(_set_); } void hs_customize(struct hashset * _set_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (!alloc) _set_->alloc = &cmc_alloc_node_default; else _set_->alloc = alloc; (_set_)->callbacks = callbacks; _set_->flag = CMC_FLAG_OK; } _Bool hs_insert(struct hashset * _set_, size_t value) { if (hs_full(_set_)) { if (!hs_resize(_set_, _set_->capacity + 1)) return 0; } if (hs_impl_get_entry(_set_, value) != ((void *)0)) { _set_->flag = CMC_FLAG_DUPLICATE; return 0; } size_t hash = _set_->f_val->hash(value); size_t original_pos = hash % _set_->capacity; size_t pos = original_pos; struct hashset_entry *target = &(_set_->buffer[pos]); if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) { target->value = value; target->dist = 0; target->state = CMC_ES_FILLED; } else { while (1) { pos++; target = &(_set_->buffer[pos % _set_->capacity]); if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) { target->value = value; target->dist = pos - original_pos; target->state = CMC_ES_FILLED; break; } else if (target->dist < pos - original_pos) { size_t tmp = target->value; size_t tmp_dist = target->dist; target->value = value; target->dist = pos - original_pos; value = tmp; original_pos = pos - tmp_dist; } } } _set_->count++; _set_->flag = CMC_FLAG_OK; if ((_set_)->callbacks && (_set_)->callbacks->create) (_set_)->callbacks->create();; return 1; } _Bool hs_remove(struct hashset * _set_, size_t value) { if (hs_empty(_set_)) { _set_->flag = CMC_FLAG_EMPTY; return 0; } struct hashset_entry *result = hs_impl_get_entry(_set_, value); if (result == ((void *)0)) { _set_->flag = CMC_FLAG_NOT_FOUND; return 0; } result->value = (size_t){ 0 }; result->dist = 0; result->state = CMC_ES_DELETED; _set_->count--; _set_->flag = CMC_FLAG_OK; if ((_set_)->callbacks && (_set_)->callbacks->delete) (_set_)->callbacks->delete();; return 1; } _Bool hs_max(struct hashset * _set_, size_t * value) { if (hs_empty(_set_)) { _set_->flag = CMC_FLAG_EMPTY; return 0; } _Bool first = 1; size_t max_val = (size_t){ 0 }; for (size_t i = 0; i < _set_->capacity; i++) { if (_set_->buffer[i].state == CMC_ES_FILLED) { if (first) { max_val = _set_->buffer[i].value; first = 0; } else if (_set_->f_val->cmp(_set_->buffer[i].value, max_val) > 0) { max_val = _set_->buffer[i].value; } } } if (value) *value = max_val; _set_->flag = CMC_FLAG_OK; if ((_set_)->callbacks && (_set_)->callbacks->read) (_set_)->callbacks->read();; return 1; } _Bool hs_min(struct hashset * _set_, size_t * value) { if (hs_empty(_set_)) { _set_->flag = CMC_FLAG_EMPTY; return 0; } _Bool first = 1; size_t min_val = (size_t){ 0 }; for (size_t i = 0; i < _set_->capacity; i++) { if (_set_->buffer[i].state == CMC_ES_FILLED) { if (first) { min_val = _set_->buffer[i].value; first = 0; } else if (_set_->f_val->cmp(_set_->buffer[i].value, min_val) < 0) { min_val = _set_->buffer[i].value; } } } if (value) *value = min_val; _set_->flag = CMC_FLAG_OK; if ((_set_)->callbacks && (_set_)->callbacks->read) (_set_)->callbacks->read();; return 1; } _Bool hs_contains(struct hashset * _set_, size_t value) { _set_->flag = CMC_FLAG_OK; _Bool result = hs_impl_get_entry(_set_, value) != ((void *)0); if ((_set_)->callbacks && (_set_)->callbacks->read) (_set_)->callbacks->read();; return result; } _Bool hs_empty(struct hashset * _set_) { return _set_->count == 0; } _Bool hs_full(struct hashset * _set_) { return (double)_set_->capacity * _set_->load <= (double)_set_->count; } size_t hs_count(struct hashset * _set_) { return _set_->count; } size_t hs_capacity(struct hashset * _set_) { return _set_->capacity; } double hs_load(struct hashset * _set_) { return _set_->load; } int hs_flag(struct hashset * _set_) { return _set_->flag; } _Bool hs_resize(struct hashset * _set_, size_t capacity) { _set_->flag = CMC_FLAG_OK; if (_set_->capacity == capacity) goto success; if (_set_->capacity > capacity / _set_->load) goto success; if (capacity >= 0xffffffffffffffffULL * _set_->load) { _set_->flag = CMC_FLAG_ERROR; return 0; } size_t theoretical_size = hs_impl_calculate_size(capacity); if (theoretical_size < _set_->count / _set_->load) { _set_->flag = CMC_FLAG_INVALID; return 0; } struct hashset *_new_set_ = hs_new_custom(capacity, _set_->load, _set_->f_val, _set_->alloc, ((void *)0)); if (!_new_set_) { _set_->flag = CMC_FLAG_ALLOC; return 0; } for (size_t i = 0; i < _set_->capacity; i++) { if (_set_->buffer[i].state == CMC_ES_FILLED) { size_t value = _set_->buffer[i].value; hs_insert(_new_set_, value); } } if (_set_->count != _new_set_->count) { hs_free(_new_set_); _set_->flag = CMC_FLAG_ERROR; return 0; } struct hashset_entry *tmp_b = _set_->buffer; _set_->buffer = _new_set_->buffer; _new_set_->buffer = tmp_b; size_t tmp_c = _set_->capacity; _set_->capacity = _new_set_->capacity; _new_set_->capacity = tmp_c; _new_set_->f_val = &(struct hashset_fval){ ((void *)0) }; hs_free(_new_set_); success: if ((_set_)->callbacks && (_set_)->callbacks->resize) (_set_)->callbacks->resize();; return 1; } struct hashset *hs_copy_of(struct hashset * _set_) { struct hashset *result = hs_new_custom(_set_->capacity * _set_->load, _set_->load, _set_->f_val, _set_->alloc, ((void *)0)); if (!result) { _set_->flag = CMC_FLAG_ERROR; return ((void *)0); } (result)->callbacks = _set_->callbacks; if (_set_->f_val->cpy) { for (size_t i = 0; i < _set_->capacity; i++) { struct hashset_entry *scan = &(_set_->buffer[i]); if (scan->state != CMC_ES_EMPTY) { struct hashset_entry *target = &(result->buffer[i]); if (scan->state == CMC_ES_DELETED) target->state = CMC_ES_DELETED; else { target->state = scan->state; target->dist = scan->dist; target->value = _set_->f_val->cpy(scan->value); } } } } else memcpy(result->buffer, _set_->buffer, sizeof(struct hashset_entry) * _set_->capacity); result->count = _set_->count; _set_->flag = CMC_FLAG_OK; return result; } _Bool hs_equals(struct hashset * _set1_, struct hashset * _set2_) { _set1_->flag = CMC_FLAG_OK; _set2_->flag = CMC_FLAG_OK; if (_set1_->count != _set2_->count) return 0; struct hashset *_set_a_; struct hashset *_set_b_; _set_a_ = _set1_->capacity < _set2_->capacity ? _set1_ : _set2_; _set_b_ = _set_a_ == _set1_ ? _set2_ : _set1_; for (size_t i = 0; i < _set_a_->capacity; i++) { if (_set_a_->buffer[i].state == CMC_ES_FILLED) { if (!hs_impl_get_entry(_set_b_, _set_a_->buffer[i].value)) return 0; } } return 1; } static struct hashset_entry * hs_impl_get_entry(struct hashset * _set_, size_t value) { size_t hash = _set_->f_val->hash(value); size_t pos = hash % _set_->capacity; struct hashset_entry *target = &(_set_->buffer[pos]); while (target->state == CMC_ES_FILLED || target->state == CMC_ES_DELETED) { if (_set_->f_val->cmp(target->value, value) == 0) return target; pos++; target = &(_set_->buffer[pos % _set_->capacity]); } return ((void *)0); } static size_t hs_impl_calculate_size(size_t required) { const size_t count = sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]); if (cmc_hashtable_primes[count - 1] < required) return required; size_t i = 0; while (cmc_hashtable_primes[i] < required) i++; return cmc_hashtable_primes[i]; } struct hashset_iter hs_iter_start(struct hashset * target) { struct hashset_iter iter; iter.target = target; iter.cursor = 0; iter.index = 0; iter.first = 0; iter.last = 0; iter.start = 1; iter.end = hs_empty(target); if (!hs_empty(target)) { for (size_t i = 0; i < target->capacity; i++) { if (target->buffer[i].state == CMC_ES_FILLED) { iter.first = i; break; } } iter.cursor = iter.first; for (size_t i = target->capacity; i > 0; i--) { if (target->buffer[i - 1].state == CMC_ES_FILLED) { iter.last = i - 1; break; } } } return iter; } struct hashset_iter hs_iter_end(struct hashset * target) { struct hashset_iter iter; iter.target = target; iter.cursor = 0; iter.index = 0; iter.first = 0; iter.last = 0; iter.start = hs_empty(target); iter.end = 1; if (!hs_empty(target)) { for (size_t i = 0; i < target->capacity; i++) { if (target->buffer[i].state == CMC_ES_FILLED) { iter.first = i; break; } } for (size_t i = target->capacity; i > 0; i--) { if (target->buffer[i - 1].state == CMC_ES_FILLED) { iter.last = i - 1; break; } } iter.cursor = iter.last; iter.index = target->count - 1; } return iter; } _Bool hs_iter_at_start(struct hashset_iter * iter) { return hs_empty(iter->target) || iter->start; } _Bool hs_iter_at_end(struct hashset_iter * iter) { return hs_empty(iter->target) || iter->end; } _Bool hs_iter_to_start(struct hashset_iter * iter) { if (!hs_empty(iter->target)) { iter->cursor = iter->first; iter->index = 0; iter->start = 1; iter->end = hs_empty(iter->target); return 1; } return 0; } _Bool hs_iter_to_end(struct hashset_iter * iter) { if (!hs_empty(iter->target)) { iter->cursor = iter->last; iter->index = iter->target->count - 1; iter->start = hs_empty(iter->target); iter->end = 1; return 1; } return 0; } _Bool hs_iter_next(struct hashset_iter * iter) { if (iter->end) return 0; if (iter->index + 1 == iter->target->count) { iter->end = 1; return 0; } iter->start = hs_empty(iter->target); struct hashset_entry *scan = &(iter->target->buffer[iter->cursor]); iter->index++; while (1) { iter->cursor++; scan = &(iter->target->buffer[iter->cursor]); if (scan->state == CMC_ES_FILLED) break; } return 1; } _Bool hs_iter_prev(struct hashset_iter * iter) { if (iter->start) return 0; if (iter->index == 0) { iter->start = 1; return 0; } iter->end = hs_empty(iter->target); struct hashset_entry *scan = &(iter->target->buffer[iter->cursor]); iter->index--; while (1) { iter->cursor--; scan = &(iter->target->buffer[iter->cursor]); if (scan->state == CMC_ES_FILLED) break; } return 1; } _Bool hs_iter_advance(struct hashset_iter * iter, size_t steps) { if (iter->end) return 0; if (iter->index + 1 == iter->target->count) { iter->end = 1; return 0; } if (steps == 0 || iter->index + steps >= iter->target->count) return 0; for (size_t i = 0; i < steps; i++) hs_iter_next(iter); return 1; } _Bool hs_iter_rewind(struct hashset_iter * iter, size_t steps) { if (iter->start) return 0; if (iter->index == 0) { iter->start = 1; return 0; } if (steps == 0 || iter->index < steps) return 0; for (size_t i = 0; i < steps; i++) hs_iter_prev(iter); return 1; } _Bool hs_iter_go_to(struct hashset_iter * iter, size_t index) { if (index >= iter->target->count) return 0; if (iter->index > index) return hs_iter_rewind(iter, iter->index - index); else if (iter->index < index) return hs_iter_advance(iter, index - iter->index); return 1; } size_t hs_iter_value(struct hashset_iter * iter) { if (hs_empty(iter->target)) return (size_t){ 0 }; return iter->target->buffer[iter->cursor].value; } size_t hs_iter_index(struct hashset_iter * iter) { return iter->index; } struct hashset *hs_union(struct hashset * _set1_, struct hashset * _set2_) { struct hashset *_set_r_ = hs_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, ((void *)0)); if (!_set_r_) { _set1_->flag = CMC_FLAG_ALLOC; _set2_->flag = CMC_FLAG_ALLOC; return ((void *)0); } struct hashset_iter iter1 = hs_iter_start(_set1_); struct hashset_iter iter2 = hs_iter_start(_set2_); for (; !hs_iter_at_end(&iter1); hs_iter_next(&iter1)) { hs_insert(_set_r_, hs_iter_value(&iter1)); } for (; !hs_iter_at_end(&iter2); hs_iter_next(&iter2)) { hs_insert(_set_r_, hs_iter_value(&iter2)); } (_set_r_)->callbacks = _set1_->callbacks; return _set_r_; } struct hashset *hs_intersection(struct hashset * _set1_, struct hashset * _set2_) { struct hashset *_set_r_ = hs_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, ((void *)0)); if (!_set_r_) { _set1_->flag = CMC_FLAG_ALLOC; _set2_->flag = CMC_FLAG_ALLOC; return ((void *)0); } struct hashset *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; struct hashset *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; struct hashset_iter iter = hs_iter_start(_set_A_); for (; !hs_iter_at_end(&iter); hs_iter_next(&iter)) { size_t value = hs_iter_value(&iter); if (hs_impl_get_entry(_set_B_, value) != ((void *)0)) hs_insert(_set_r_, value); } (_set_r_)->callbacks = _set1_->callbacks; return _set_r_; } struct hashset *hs_difference(struct hashset * _set1_, struct hashset * _set2_) { struct hashset *_set_r_ = hs_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, ((void *)0)); if (!_set_r_) { _set1_->flag = CMC_FLAG_ALLOC; _set2_->flag = CMC_FLAG_ALLOC; return ((void *)0); } struct hashset_iter iter = hs_iter_start(_set1_); for (; !hs_iter_at_end(&iter); hs_iter_next(&iter)) { size_t value = hs_iter_value(&iter); if (hs_impl_get_entry(_set2_, value) == ((void *)0)) hs_insert(_set_r_, value); } (_set_r_)->callbacks = _set1_->callbacks; return _set_r_; } struct hashset *hs_symmetric_difference(struct hashset * _set1_, struct hashset * _set2_) { struct hashset *_set_r_ = hs_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, ((void *)0)); if (!_set_r_) { _set1_->flag = CMC_FLAG_ALLOC; _set2_->flag = CMC_FLAG_ALLOC; return ((void *)0); } struct hashset_iter iter1 = hs_iter_start(_set1_); struct hashset_iter iter2 = hs_iter_start(_set2_); for (; !hs_iter_at_end(&iter1); hs_iter_next(&iter1)) { size_t value = hs_iter_value(&iter1); if (hs_impl_get_entry(_set2_, value) == ((void *)0)) hs_insert(_set_r_, value); } for (; !hs_iter_at_end(&iter2); hs_iter_next(&iter2)) { size_t value = hs_iter_value(&iter2); if (hs_impl_get_entry(_set1_, value) == ((void *)0)) hs_insert(_set_r_, value); } (_set_r_)->callbacks = _set1_->callbacks; return _set_r_; } _Bool hs_is_subset(struct hashset * _set1_, struct hashset * _set2_) { _set1_->flag = CMC_FLAG_OK; _set2_->flag = CMC_FLAG_OK; if (_set1_->count > _set2_->count) return 0; if (hs_empty(_set1_)) return 1; struct hashset_iter iter = hs_iter_start(_set1_); for (; !hs_iter_at_end(&iter); hs_iter_next(&iter)) { size_t value = hs_iter_value(&iter); if (hs_impl_get_entry(_set2_, value) == ((void *)0)) return 0; } return 1; } _Bool hs_is_superset(struct hashset * _set1_, struct hashset * _set2_) { return hs_is_subset(_set2_, _set1_); } _Bool hs_is_proper_subset(struct hashset * _set1_, struct hashset * _set2_) { _set1_->flag = CMC_FLAG_OK; _set2_->flag = CMC_FLAG_OK; if (_set1_->count >= _set2_->count) return 0; if (hs_empty(_set1_)) { if (!hs_empty(_set2_)) return 1; else return 0; } struct hashset_iter iter = hs_iter_start(_set1_); for (; !hs_iter_at_end(&iter); hs_iter_next(&iter)) { size_t value = hs_iter_value(&iter); if (hs_impl_get_entry(_set2_, value) == ((void *)0)) return 0; } return 1; } _Bool hs_is_proper_superset(struct hashset * _set1_, struct hashset * _set2_) { return hs_is_proper_subset(_set2_, _set1_); } _Bool hs_is_disjointset(struct hashset * _set1_, struct hashset * _set2_) { _set1_->flag = CMC_FLAG_OK; _set2_->flag = CMC_FLAG_OK; if (hs_empty(_set1_)) return 1; struct hashset_iter iter = hs_iter_start(_set1_); for (; !hs_iter_at_end(&iter); hs_iter_next(&iter)) { size_t value = hs_iter_value(&iter); if (hs_impl_get_entry(_set2_, value) != ((void *)0)) return 0; } return 1; } _Bool hs_to_string(struct hashset * _set_, FILE * fptr) { struct hashset *s_ = _set_; return 0 <= fprintf(fptr, "struct %s<%s> " "at %p { " "buffer:%p, " "capacity:%" "I64u" ", " "count:%" "I64u" ", " "load:%lf, " "flag:%d, " "f_val:%p, " "alloc:%p, " "callbacks: %p }", "hashset", "size_t", s_, s_->buffer, s_->capacity, s_->count, s_->load, s_->flag, s_->f_val, s_->alloc, (s_)->callbacks); } _Bool hs_print(struct hashset * _set_, FILE * fptr, const char *start, const char *separator, const char *end) { fprintf(fptr, "%s", start); size_t last = 0; for (size_t i = _set_->capacity; i > 0; i--) { if ((_set_->buffer[i - 1]).state == CMC_ES_FILLED) { last = i - 1; break; } } for (size_t i = 0; i < _set_->capacity; i++) { struct hashset_entry *entry = &(_set_->buffer[i]); if (entry->state == CMC_ES_FILLED) { if (!_set_->f_val->str(fptr, entry->value)) return 0; if (i + 1 < last) fprintf(fptr, "%s", separator); } } fprintf(fptr, "%s", end); return 1; } - - \ No newline at end of file +static struct hashset_entry *hs_impl_get_entry(struct hashset *_set_, size_t value); +static size_t hs_impl_calculate_size(size_t required); +struct hashset *hs_new(size_t capacity, double load, struct hashset_fval *f_val) +{ + return hs_new_custom(capacity, load, f_val, ((void *)0), ((void *)0)); +} +struct hashset *hs_new_custom(size_t capacity, double load, struct hashset_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks) +{ + ; + if (capacity == 0 || load <= 0 || load >= 1) + return ((void *)0); + if (capacity >= 0xffffffffffffffffULL * load) + return ((void *)0); + if (!f_val) + return ((void *)0); + size_t real_capacity = hs_impl_calculate_size(capacity / load); + if (!alloc) + alloc = &cmc_alloc_node_default; + struct hashset *_set_ = alloc->malloc(sizeof(struct hashset)); + if (!_set_) + return ((void *)0); + _set_->buffer = alloc->calloc(real_capacity, sizeof(struct hashset_entry)); + if (!_set_->buffer) + { + alloc->free(_set_); + return ((void *)0); + } + _set_->count = 0; + _set_->capacity = real_capacity; + _set_->load = load; + _set_->flag = CMC_FLAG_OK; + _set_->f_val = f_val; + _set_->alloc = alloc; + (_set_)->callbacks = callbacks; + return _set_; +} +void hs_clear(struct hashset *_set_) +{ + if (_set_->f_val->free) + { + for (size_t i = 0; i < _set_->capacity; i++) + { + struct hashset_entry *entry = &(_set_->buffer[i]); + if (entry->state == CMC_ES_FILLED) + { + _set_->f_val->free(entry->value); + } + } + } + memset(_set_->buffer, 0, sizeof(struct hashset_entry) * _set_->capacity); + _set_->count = 0; + _set_->flag = CMC_FLAG_OK; +} +void hs_free(struct hashset *_set_) +{ + if (_set_->f_val->free) + { + for (size_t i = 0; i < _set_->capacity; i++) + { + struct hashset_entry *entry = &(_set_->buffer[i]); + if (entry->state == CMC_ES_FILLED) + { + _set_->f_val->free(entry->value); + } + } + } + _set_->alloc->free(_set_->buffer); + _set_->alloc->free(_set_); +} +void hs_customize(struct hashset *_set_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks) +{ + ; + if (!alloc) + _set_->alloc = &cmc_alloc_node_default; + else + _set_->alloc = alloc; + (_set_)->callbacks = callbacks; + _set_->flag = CMC_FLAG_OK; +} +_Bool hs_insert(struct hashset *_set_, size_t value) +{ + if (hs_full(_set_)) + { + if (!hs_resize(_set_, _set_->capacity + 1)) + return 0; + } + if (hs_impl_get_entry(_set_, value) != ((void *)0)) + { + _set_->flag = CMC_FLAG_DUPLICATE; + return 0; + } + size_t hash = _set_->f_val->hash(value); + size_t original_pos = hash % _set_->capacity; + size_t pos = original_pos; + struct hashset_entry *target = &(_set_->buffer[pos]); + if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) + { + target->value = value; + target->dist = 0; + target->state = CMC_ES_FILLED; + } + else + { + while (1) + { + pos++; + target = &(_set_->buffer[pos % _set_->capacity]); + if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) + { + target->value = value; + target->dist = pos - original_pos; + target->state = CMC_ES_FILLED; + break; + } + else if (target->dist < pos - original_pos) + { + size_t tmp = target->value; + size_t tmp_dist = target->dist; + target->value = value; + target->dist = pos - original_pos; + value = tmp; + original_pos = pos - tmp_dist; + } + } + } + _set_->count++; + _set_->flag = CMC_FLAG_OK; + if ((_set_)->callbacks && (_set_)->callbacks->create) + (_set_)->callbacks->create(); + ; + return 1; +} +_Bool hs_remove(struct hashset *_set_, size_t value) +{ + if (hs_empty(_set_)) + { + _set_->flag = CMC_FLAG_EMPTY; + return 0; + } + struct hashset_entry *result = hs_impl_get_entry(_set_, value); + if (result == ((void *)0)) + { + _set_->flag = CMC_FLAG_NOT_FOUND; + return 0; + } + result->value = (size_t){ 0 }; + result->dist = 0; + result->state = CMC_ES_DELETED; + _set_->count--; + _set_->flag = CMC_FLAG_OK; + if ((_set_)->callbacks && (_set_)->callbacks->delete) + (_set_)->callbacks->delete (); + ; + return 1; +} +_Bool hs_max(struct hashset *_set_, size_t *value) +{ + if (hs_empty(_set_)) + { + _set_->flag = CMC_FLAG_EMPTY; + return 0; + } + _Bool first = 1; + size_t max_val = (size_t){ 0 }; + for (size_t i = 0; i < _set_->capacity; i++) + { + if (_set_->buffer[i].state == CMC_ES_FILLED) + { + if (first) + { + max_val = _set_->buffer[i].value; + first = 0; + } + else if (_set_->f_val->cmp(_set_->buffer[i].value, max_val) > 0) + { + max_val = _set_->buffer[i].value; + } + } + } + if (value) + *value = max_val; + _set_->flag = CMC_FLAG_OK; + if ((_set_)->callbacks && (_set_)->callbacks->read) + (_set_)->callbacks->read(); + ; + return 1; +} +_Bool hs_min(struct hashset *_set_, size_t *value) +{ + if (hs_empty(_set_)) + { + _set_->flag = CMC_FLAG_EMPTY; + return 0; + } + _Bool first = 1; + size_t min_val = (size_t){ 0 }; + for (size_t i = 0; i < _set_->capacity; i++) + { + if (_set_->buffer[i].state == CMC_ES_FILLED) + { + if (first) + { + min_val = _set_->buffer[i].value; + first = 0; + } + else if (_set_->f_val->cmp(_set_->buffer[i].value, min_val) < 0) + { + min_val = _set_->buffer[i].value; + } + } + } + if (value) + *value = min_val; + _set_->flag = CMC_FLAG_OK; + if ((_set_)->callbacks && (_set_)->callbacks->read) + (_set_)->callbacks->read(); + ; + return 1; +} +_Bool hs_contains(struct hashset *_set_, size_t value) +{ + _set_->flag = CMC_FLAG_OK; + _Bool result = hs_impl_get_entry(_set_, value) != ((void *)0); + if ((_set_)->callbacks && (_set_)->callbacks->read) + (_set_)->callbacks->read(); + ; + return result; +} +_Bool hs_empty(struct hashset *_set_) +{ + return _set_->count == 0; +} +_Bool hs_full(struct hashset *_set_) +{ + return (double)_set_->capacity * _set_->load <= (double)_set_->count; +} +size_t hs_count(struct hashset *_set_) +{ + return _set_->count; +} +size_t hs_capacity(struct hashset *_set_) +{ + return _set_->capacity; +} +double hs_load(struct hashset *_set_) +{ + return _set_->load; +} +int hs_flag(struct hashset *_set_) +{ + return _set_->flag; +} +_Bool hs_resize(struct hashset *_set_, size_t capacity) +{ + _set_->flag = CMC_FLAG_OK; + if (_set_->capacity == capacity) + goto success; + if (_set_->capacity > capacity / _set_->load) + goto success; + if (capacity >= 0xffffffffffffffffULL * _set_->load) + { + _set_->flag = CMC_FLAG_ERROR; + return 0; + } + size_t theoretical_size = hs_impl_calculate_size(capacity); + if (theoretical_size < _set_->count / _set_->load) + { + _set_->flag = CMC_FLAG_INVALID; + return 0; + } + struct hashset *_new_set_ = hs_new_custom(capacity, _set_->load, _set_->f_val, _set_->alloc, ((void *)0)); + if (!_new_set_) + { + _set_->flag = CMC_FLAG_ALLOC; + return 0; + } + for (size_t i = 0; i < _set_->capacity; i++) + { + if (_set_->buffer[i].state == CMC_ES_FILLED) + { + size_t value = _set_->buffer[i].value; + hs_insert(_new_set_, value); + } + } + if (_set_->count != _new_set_->count) + { + hs_free(_new_set_); + _set_->flag = CMC_FLAG_ERROR; + return 0; + } + struct hashset_entry *tmp_b = _set_->buffer; + _set_->buffer = _new_set_->buffer; + _new_set_->buffer = tmp_b; + size_t tmp_c = _set_->capacity; + _set_->capacity = _new_set_->capacity; + _new_set_->capacity = tmp_c; + _new_set_->f_val = &(struct hashset_fval){ ((void *)0) }; + hs_free(_new_set_); +success: + if ((_set_)->callbacks && (_set_)->callbacks->resize) + (_set_)->callbacks->resize(); + ; + return 1; +} +struct hashset *hs_copy_of(struct hashset *_set_) +{ + struct hashset *result = + hs_new_custom(_set_->capacity * _set_->load, _set_->load, _set_->f_val, _set_->alloc, ((void *)0)); + if (!result) + { + _set_->flag = CMC_FLAG_ERROR; + return ((void *)0); + } + (result)->callbacks = _set_->callbacks; + if (_set_->f_val->cpy) + { + for (size_t i = 0; i < _set_->capacity; i++) + { + struct hashset_entry *scan = &(_set_->buffer[i]); + if (scan->state != CMC_ES_EMPTY) + { + struct hashset_entry *target = &(result->buffer[i]); + if (scan->state == CMC_ES_DELETED) + target->state = CMC_ES_DELETED; + else + { + target->state = scan->state; + target->dist = scan->dist; + target->value = _set_->f_val->cpy(scan->value); + } + } + } + } + else + memcpy(result->buffer, _set_->buffer, sizeof(struct hashset_entry) * _set_->capacity); + result->count = _set_->count; + _set_->flag = CMC_FLAG_OK; + return result; +} +_Bool hs_equals(struct hashset *_set1_, struct hashset *_set2_) +{ + _set1_->flag = CMC_FLAG_OK; + _set2_->flag = CMC_FLAG_OK; + if (_set1_->count != _set2_->count) + return 0; + struct hashset *_set_a_; + struct hashset *_set_b_; + _set_a_ = _set1_->capacity < _set2_->capacity ? _set1_ : _set2_; + _set_b_ = _set_a_ == _set1_ ? _set2_ : _set1_; + for (size_t i = 0; i < _set_a_->capacity; i++) + { + if (_set_a_->buffer[i].state == CMC_ES_FILLED) + { + if (!hs_impl_get_entry(_set_b_, _set_a_->buffer[i].value)) + return 0; + } + } + return 1; +} +static struct hashset_entry *hs_impl_get_entry(struct hashset *_set_, size_t value) +{ + size_t hash = _set_->f_val->hash(value); + size_t pos = hash % _set_->capacity; + struct hashset_entry *target = &(_set_->buffer[pos]); + while (target->state == CMC_ES_FILLED || target->state == CMC_ES_DELETED) + { + if (_set_->f_val->cmp(target->value, value) == 0) + return target; + pos++; + target = &(_set_->buffer[pos % _set_->capacity]); + } + return ((void *)0); +} +static size_t hs_impl_calculate_size(size_t required) +{ + const size_t count = sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]); + if (cmc_hashtable_primes[count - 1] < required) + return required; + size_t i = 0; + while (cmc_hashtable_primes[i] < required) + i++; + return cmc_hashtable_primes[i]; +} +struct hashset_iter hs_iter_start(struct hashset *target) +{ + struct hashset_iter iter; + iter.target = target; + iter.cursor = 0; + iter.index = 0; + iter.first = 0; + iter.last = 0; + iter.start = 1; + iter.end = hs_empty(target); + if (!hs_empty(target)) + { + for (size_t i = 0; i < target->capacity; i++) + { + if (target->buffer[i].state == CMC_ES_FILLED) + { + iter.first = i; + break; + } + } + iter.cursor = iter.first; + for (size_t i = target->capacity; i > 0; i--) + { + if (target->buffer[i - 1].state == CMC_ES_FILLED) + { + iter.last = i - 1; + break; + } + } + } + return iter; +} +struct hashset_iter hs_iter_end(struct hashset *target) +{ + struct hashset_iter iter; + iter.target = target; + iter.cursor = 0; + iter.index = 0; + iter.first = 0; + iter.last = 0; + iter.start = hs_empty(target); + iter.end = 1; + if (!hs_empty(target)) + { + for (size_t i = 0; i < target->capacity; i++) + { + if (target->buffer[i].state == CMC_ES_FILLED) + { + iter.first = i; + break; + } + } + for (size_t i = target->capacity; i > 0; i--) + { + if (target->buffer[i - 1].state == CMC_ES_FILLED) + { + iter.last = i - 1; + break; + } + } + iter.cursor = iter.last; + iter.index = target->count - 1; + } + return iter; +} +_Bool hs_iter_at_start(struct hashset_iter *iter) +{ + return hs_empty(iter->target) || iter->start; +} +_Bool hs_iter_at_end(struct hashset_iter *iter) +{ + return hs_empty(iter->target) || iter->end; +} +_Bool hs_iter_to_start(struct hashset_iter *iter) +{ + if (!hs_empty(iter->target)) + { + iter->cursor = iter->first; + iter->index = 0; + iter->start = 1; + iter->end = hs_empty(iter->target); + return 1; + } + return 0; +} +_Bool hs_iter_to_end(struct hashset_iter *iter) +{ + if (!hs_empty(iter->target)) + { + iter->cursor = iter->last; + iter->index = iter->target->count - 1; + iter->start = hs_empty(iter->target); + iter->end = 1; + return 1; + } + return 0; +} +_Bool hs_iter_next(struct hashset_iter *iter) +{ + if (iter->end) + return 0; + if (iter->index + 1 == iter->target->count) + { + iter->end = 1; + return 0; + } + iter->start = hs_empty(iter->target); + struct hashset_entry *scan = &(iter->target->buffer[iter->cursor]); + iter->index++; + while (1) + { + iter->cursor++; + scan = &(iter->target->buffer[iter->cursor]); + if (scan->state == CMC_ES_FILLED) + break; + } + return 1; +} +_Bool hs_iter_prev(struct hashset_iter *iter) +{ + if (iter->start) + return 0; + if (iter->index == 0) + { + iter->start = 1; + return 0; + } + iter->end = hs_empty(iter->target); + struct hashset_entry *scan = &(iter->target->buffer[iter->cursor]); + iter->index--; + while (1) + { + iter->cursor--; + scan = &(iter->target->buffer[iter->cursor]); + if (scan->state == CMC_ES_FILLED) + break; + } + return 1; +} +_Bool hs_iter_advance(struct hashset_iter *iter, size_t steps) +{ + if (iter->end) + return 0; + if (iter->index + 1 == iter->target->count) + { + iter->end = 1; + return 0; + } + if (steps == 0 || iter->index + steps >= iter->target->count) + return 0; + for (size_t i = 0; i < steps; i++) + hs_iter_next(iter); + return 1; +} +_Bool hs_iter_rewind(struct hashset_iter *iter, size_t steps) +{ + if (iter->start) + return 0; + if (iter->index == 0) + { + iter->start = 1; + return 0; + } + if (steps == 0 || iter->index < steps) + return 0; + for (size_t i = 0; i < steps; i++) + hs_iter_prev(iter); + return 1; +} +_Bool hs_iter_go_to(struct hashset_iter *iter, size_t index) +{ + if (index >= iter->target->count) + return 0; + if (iter->index > index) + return hs_iter_rewind(iter, iter->index - index); + else if (iter->index < index) + return hs_iter_advance(iter, index - iter->index); + return 1; +} +size_t hs_iter_value(struct hashset_iter *iter) +{ + if (hs_empty(iter->target)) + return (size_t){ 0 }; + return iter->target->buffer[iter->cursor].value; +} +size_t hs_iter_index(struct hashset_iter *iter) +{ + return iter->index; +} +struct hashset *hs_union(struct hashset *_set1_, struct hashset *_set2_) +{ + struct hashset *_set_r_ = hs_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, ((void *)0)); + if (!_set_r_) + { + _set1_->flag = CMC_FLAG_ALLOC; + _set2_->flag = CMC_FLAG_ALLOC; + return ((void *)0); + } + struct hashset_iter iter1 = hs_iter_start(_set1_); + struct hashset_iter iter2 = hs_iter_start(_set2_); + for (; !hs_iter_at_end(&iter1); hs_iter_next(&iter1)) + { + hs_insert(_set_r_, hs_iter_value(&iter1)); + } + for (; !hs_iter_at_end(&iter2); hs_iter_next(&iter2)) + { + hs_insert(_set_r_, hs_iter_value(&iter2)); + } + (_set_r_)->callbacks = _set1_->callbacks; + return _set_r_; +} +struct hashset *hs_intersection(struct hashset *_set1_, struct hashset *_set2_) +{ + struct hashset *_set_r_ = hs_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, ((void *)0)); + if (!_set_r_) + { + _set1_->flag = CMC_FLAG_ALLOC; + _set2_->flag = CMC_FLAG_ALLOC; + return ((void *)0); + } + struct hashset *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; + struct hashset *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; + struct hashset_iter iter = hs_iter_start(_set_A_); + for (; !hs_iter_at_end(&iter); hs_iter_next(&iter)) + { + size_t value = hs_iter_value(&iter); + if (hs_impl_get_entry(_set_B_, value) != ((void *)0)) + hs_insert(_set_r_, value); + } + (_set_r_)->callbacks = _set1_->callbacks; + return _set_r_; +} +struct hashset *hs_difference(struct hashset *_set1_, struct hashset *_set2_) +{ + struct hashset *_set_r_ = hs_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, ((void *)0)); + if (!_set_r_) + { + _set1_->flag = CMC_FLAG_ALLOC; + _set2_->flag = CMC_FLAG_ALLOC; + return ((void *)0); + } + struct hashset_iter iter = hs_iter_start(_set1_); + for (; !hs_iter_at_end(&iter); hs_iter_next(&iter)) + { + size_t value = hs_iter_value(&iter); + if (hs_impl_get_entry(_set2_, value) == ((void *)0)) + hs_insert(_set_r_, value); + } + (_set_r_)->callbacks = _set1_->callbacks; + return _set_r_; +} +struct hashset *hs_symmetric_difference(struct hashset *_set1_, struct hashset *_set2_) +{ + struct hashset *_set_r_ = hs_new_custom(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, ((void *)0)); + if (!_set_r_) + { + _set1_->flag = CMC_FLAG_ALLOC; + _set2_->flag = CMC_FLAG_ALLOC; + return ((void *)0); + } + struct hashset_iter iter1 = hs_iter_start(_set1_); + struct hashset_iter iter2 = hs_iter_start(_set2_); + for (; !hs_iter_at_end(&iter1); hs_iter_next(&iter1)) + { + size_t value = hs_iter_value(&iter1); + if (hs_impl_get_entry(_set2_, value) == ((void *)0)) + hs_insert(_set_r_, value); + } + for (; !hs_iter_at_end(&iter2); hs_iter_next(&iter2)) + { + size_t value = hs_iter_value(&iter2); + if (hs_impl_get_entry(_set1_, value) == ((void *)0)) + hs_insert(_set_r_, value); + } + (_set_r_)->callbacks = _set1_->callbacks; + return _set_r_; +} +_Bool hs_is_subset(struct hashset *_set1_, struct hashset *_set2_) +{ + _set1_->flag = CMC_FLAG_OK; + _set2_->flag = CMC_FLAG_OK; + if (_set1_->count > _set2_->count) + return 0; + if (hs_empty(_set1_)) + return 1; + struct hashset_iter iter = hs_iter_start(_set1_); + for (; !hs_iter_at_end(&iter); hs_iter_next(&iter)) + { + size_t value = hs_iter_value(&iter); + if (hs_impl_get_entry(_set2_, value) == ((void *)0)) + return 0; + } + return 1; +} +_Bool hs_is_superset(struct hashset *_set1_, struct hashset *_set2_) +{ + return hs_is_subset(_set2_, _set1_); +} +_Bool hs_is_proper_subset(struct hashset *_set1_, struct hashset *_set2_) +{ + _set1_->flag = CMC_FLAG_OK; + _set2_->flag = CMC_FLAG_OK; + if (_set1_->count >= _set2_->count) + return 0; + if (hs_empty(_set1_)) + { + if (!hs_empty(_set2_)) + return 1; + else + return 0; + } + struct hashset_iter iter = hs_iter_start(_set1_); + for (; !hs_iter_at_end(&iter); hs_iter_next(&iter)) + { + size_t value = hs_iter_value(&iter); + if (hs_impl_get_entry(_set2_, value) == ((void *)0)) + return 0; + } + return 1; +} +_Bool hs_is_proper_superset(struct hashset *_set1_, struct hashset *_set2_) +{ + return hs_is_proper_subset(_set2_, _set1_); +} +_Bool hs_is_disjointset(struct hashset *_set1_, struct hashset *_set2_) +{ + _set1_->flag = CMC_FLAG_OK; + _set2_->flag = CMC_FLAG_OK; + if (hs_empty(_set1_)) + return 1; + struct hashset_iter iter = hs_iter_start(_set1_); + for (; !hs_iter_at_end(&iter); hs_iter_next(&iter)) + { + size_t value = hs_iter_value(&iter); + if (hs_impl_get_entry(_set2_, value) != ((void *)0)) + return 0; + } + return 1; +} +_Bool hs_to_string(struct hashset *_set_, FILE *fptr) +{ + struct hashset *s_ = _set_; + return 0 <= fprintf(fptr, + "struct %s<%s> " + "at %p { " + "buffer:%p, " + "capacity:%" + "I64u" + ", " + "count:%" + "I64u" + ", " + "load:%lf, " + "flag:%d, " + "f_val:%p, " + "alloc:%p, " + "callbacks: %p }", + "hashset", "size_t", s_, s_->buffer, s_->capacity, s_->count, s_->load, s_->flag, s_->f_val, + s_->alloc, (s_)->callbacks); +} +_Bool hs_print(struct hashset *_set_, FILE *fptr, const char *start, const char *separator, const char *end) +{ + fprintf(fptr, "%s", start); + size_t last = 0; + for (size_t i = _set_->capacity; i > 0; i--) + { + if ((_set_->buffer[i - 1]).state == CMC_ES_FILLED) + { + last = i - 1; + break; + } + } + for (size_t i = 0; i < _set_->capacity; i++) + { + struct hashset_entry *entry = &(_set_->buffer[i]); + if (entry->state == CMC_ES_FILLED) + { + if (!_set_->f_val->str(fptr, entry->value)) + return 0; + if (i + 1 < last) + fprintf(fptr, "%s", separator); + } + } + fprintf(fptr, "%s", end); + return 1; +} diff --git a/tests/src/tst_cmc_heap.c b/tests/src/tst_cmc_heap.c index 583a76e..f9af692 100644 --- a/tests/src/tst_cmc_heap.c +++ b/tests/src/tst_cmc_heap.c @@ -1,7 +1,424 @@ - #include "tst_cmc_heap.h" +#include "tst_cmc_heap.h" - - static void h_impl_float_up(struct heap * _heap_, size_t index); static void h_impl_float_down(struct heap * _heap_, size_t index); struct heap *h_new(size_t capacity, enum cmc_heap_order HO, struct heap_fval * f_val) { return h_new_custom(capacity, HO, f_val, ((void *)0), ((void *)0)); } struct heap *h_new_custom(size_t capacity, enum cmc_heap_order HO, struct heap_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (capacity < 1) return ((void *)0); if (HO != CMC_MIN_HEAP && HO != CMC_MAX_HEAP) return ((void *)0); if (!f_val) return ((void *)0); if (!alloc) alloc = &cmc_alloc_node_default; struct heap *_heap_ = alloc->malloc(sizeof(struct heap)); if (!_heap_) return ((void *)0); _heap_->buffer = alloc->calloc(capacity, sizeof(size_t)); if (!_heap_->buffer) { alloc->free(_heap_); return ((void *)0); } _heap_->capacity = capacity; _heap_->count = 0; _heap_->HO = HO; _heap_->flag = CMC_FLAG_OK; _heap_->f_val = f_val; _heap_->alloc = alloc; (_heap_)->callbacks = callbacks; return _heap_; } void h_clear(struct heap * _heap_) { if (_heap_->f_val->free) { for (size_t i = 0; i < _heap_->count; i++) { _heap_->f_val->free(_heap_->buffer[i]); } } memset(_heap_->buffer, 0, sizeof(size_t) * _heap_->capacity); _heap_->count = 0; _heap_->flag = CMC_FLAG_OK; } void h_free(struct heap * _heap_) { if (_heap_->f_val->free) { for (size_t i = 0; i < _heap_->count; i++) { _heap_->f_val->free(_heap_->buffer[i]); } } _heap_->alloc->free(_heap_->buffer); _heap_->alloc->free(_heap_); } void h_customize(struct heap * _heap_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (!alloc) _heap_->alloc = &cmc_alloc_node_default; else _heap_->alloc = alloc; (_heap_)->callbacks = callbacks; _heap_->flag = CMC_FLAG_OK; } _Bool h_insert(struct heap * _heap_, size_t value) { if (h_full(_heap_)) { if (!h_resize(_heap_, _heap_->count * 2)) return 0; } _heap_->buffer[_heap_->count++] = value; if (_heap_->count > 1) { h_impl_float_up(_heap_, _heap_->count - 1); } _heap_->flag = CMC_FLAG_OK; if ((_heap_)->callbacks && (_heap_)->callbacks->create) (_heap_)->callbacks->create();; return 1; } _Bool h_remove(struct heap * _heap_) { if (h_empty(_heap_)) { _heap_->flag = CMC_FLAG_EMPTY; return 0; } _heap_->buffer[0] = _heap_->buffer[_heap_->count - 1]; _heap_->buffer[_heap_->count - 1] = (size_t){ 0 }; _heap_->count--; h_impl_float_down(_heap_, 0); _heap_->flag = CMC_FLAG_OK; if ((_heap_)->callbacks && (_heap_)->callbacks->delete) (_heap_)->callbacks->delete();; return 1; } size_t h_peek(struct heap * _heap_) { if (h_empty(_heap_)) { _heap_->flag = CMC_FLAG_EMPTY; return (size_t){ 0 }; } _heap_->flag = CMC_FLAG_OK; if ((_heap_)->callbacks && (_heap_)->callbacks->read) (_heap_)->callbacks->read();; return _heap_->buffer[0]; } _Bool h_contains(struct heap * _heap_, size_t value) { _heap_->flag = CMC_FLAG_OK; _Bool result = 0; for (size_t i = 0; i < _heap_->count; i++) { if (_heap_->f_val->cmp(_heap_->buffer[i], value) == 0) { result = 1; break; } } if ((_heap_)->callbacks && (_heap_)->callbacks->read) (_heap_)->callbacks->read();; return result; } _Bool h_empty(struct heap * _heap_) { return _heap_->count == 0; } _Bool h_full(struct heap * _heap_) { return _heap_->count >= _heap_->capacity; } size_t h_count(struct heap * _heap_) { return _heap_->count; } size_t h_capacity(struct heap * _heap_) { return _heap_->capacity; } int h_flag(struct heap * _heap_) { return _heap_->flag; } _Bool h_resize(struct heap * _heap_, size_t capacity) { _heap_->flag = CMC_FLAG_OK; if (_heap_->capacity == capacity) goto success; if (capacity < _heap_->count) { _heap_->flag = CMC_FLAG_INVALID; return 0; } size_t *new_buffer = _heap_->alloc->realloc(_heap_->buffer, sizeof(size_t) * capacity); if (!new_buffer) { _heap_->flag = CMC_FLAG_ALLOC; return 0; } _heap_->buffer = new_buffer; _heap_->capacity = capacity; success: if ((_heap_)->callbacks && (_heap_)->callbacks->resize) (_heap_)->callbacks->resize();; return 1; } struct heap *h_copy_of(struct heap * _heap_) { struct heap *result = h_new_custom(_heap_->capacity, _heap_->HO, _heap_->f_val, _heap_->alloc, ((void *)0)); if (!result) { _heap_->flag = CMC_FLAG_ERROR; return ((void *)0); } (result)->callbacks = _heap_->callbacks; if (_heap_->f_val->cpy) { for (size_t i = 0; i < _heap_->count; i++) result->buffer[i] = _heap_->f_val->cpy(_heap_->buffer[i]); } else memcpy(result->buffer, _heap_->buffer, sizeof(size_t) * _heap_->count); result->count = _heap_->count; _heap_->flag = CMC_FLAG_OK; return result; } _Bool h_equals(struct heap * _heap1_, struct heap * _heap2_) { _heap1_->flag = CMC_FLAG_OK; _heap2_->flag = CMC_FLAG_OK; if (_heap1_->count != _heap2_->count) return 0; for (size_t i = 0; i < _heap1_->count; i++) { if (_heap1_->f_val->cmp(_heap1_->buffer[i], _heap2_->buffer[i]) != 0) return 0; } return 1; } static void h_impl_float_up(struct heap * _heap_, size_t index) { size_t C = index; size_t child = _heap_->buffer[C]; size_t parent = _heap_->buffer[(index - 1) / 2]; int mod = _heap_->HO; while (C > 0 && _heap_->f_val->cmp(child, parent) * mod > 0) { size_t tmp = _heap_->buffer[C]; _heap_->buffer[C] = _heap_->buffer[(C - 1) / 2]; _heap_->buffer[(C - 1) / 2] = tmp; C = (C - 1) / 2; if (C == 0) break; child = _heap_->buffer[C]; parent = _heap_->buffer[(C - 1) / 2]; } } static void h_impl_float_down(struct heap * _heap_, size_t index) { int mod = _heap_->HO; while (index < _heap_->count) { size_t L = 2 * index + 1; size_t R = 2 * index + 2; size_t C = index; if (L < _heap_->count && _heap_->f_val->cmp(_heap_->buffer[L], _heap_->buffer[C]) * mod > 0) { C = L; } if (R < _heap_->count && _heap_->f_val->cmp(_heap_->buffer[R], _heap_->buffer[C]) * mod > 0) { C = R; } if (C != index) { size_t tmp = _heap_->buffer[index]; _heap_->buffer[index] = _heap_->buffer[C]; _heap_->buffer[C] = tmp; index = C; } else break; } } struct heap_iter h_iter_start(struct heap * target) { struct heap_iter iter; iter.target = target; iter.cursor = 0; iter.start = 1; iter.end = h_empty(target); return iter; } struct heap_iter h_iter_end(struct heap * target) { struct heap_iter iter; iter.target = target; iter.cursor = 0; iter.start = h_empty(target); iter.end = 1; if (!h_empty(target)) iter.cursor = target->count - 1; return iter; } _Bool h_iter_at_start(struct heap_iter * iter) { return h_empty(iter->target) || iter->start; } _Bool h_iter_at_end(struct heap_iter * iter) { return h_empty(iter->target) || iter->end; } _Bool h_iter_to_start(struct heap_iter * iter) { if (!h_empty(iter->target)) { iter->cursor = 0; iter->start = 1; iter->end = h_empty(iter->target); return 1; } return 0; } _Bool h_iter_to_end(struct heap_iter * iter) { if (!h_empty(iter->target)) { iter->cursor = iter->target->count - 1; iter->start = h_empty(iter->target); iter->end = 1; return 1; } return 0; } _Bool h_iter_next(struct heap_iter * iter) { if (iter->end) return 0; if (iter->cursor + 1 == iter->target->count) { iter->end = 1; return 0; } iter->start = h_empty(iter->target); iter->cursor++; return 1; } _Bool h_iter_prev(struct heap_iter * iter) { if (iter->start) return 0; if (iter->cursor == 0) { iter->start = 1; return 0; } iter->end = h_empty(iter->target); iter->cursor--; return 1; } _Bool h_iter_advance(struct heap_iter * iter, size_t steps) { if (iter->end) return 0; if (iter->cursor + 1 == iter->target->count) { iter->end = 1; return 0; } if (steps == 0 || iter->cursor + steps >= iter->target->count) return 0; if (iter->end) return 0; iter->start = h_empty(iter->target); iter->cursor += steps; return 1; } _Bool h_iter_rewind(struct heap_iter * iter, size_t steps) { if (iter->start) return 0; if (iter->cursor == 0) { iter->start = 1; return 0; } if (steps == 0 || iter->cursor < steps) return 0; iter->end = h_empty(iter->target); iter->cursor -= steps; return 1; } _Bool h_iter_go_to(struct heap_iter * iter, size_t index) { if (index >= iter->target->count) return 0; if (iter->cursor > index) return h_iter_rewind(iter, iter->cursor - index); else if (iter->cursor < index) return h_iter_advance(iter, index - iter->cursor); return 1; } size_t h_iter_value(struct heap_iter * iter) { if (h_empty(iter->target)) return (size_t){ 0 }; return iter->target->buffer[iter->cursor]; } size_t h_iter_index(struct heap_iter * iter) { return iter->cursor; } _Bool h_to_string(struct heap * _heap_, FILE * fptr) { struct heap *h_ = _heap_; const char *t = h_->HO == 1 ? "MaxHeap" : "MinHeap"; return 0 <= fprintf(fptr, "struct %s<%s> " "at %p { " "buffer:%p, " "capacity:%" "I64u" ", " "count:%" "I64u" ", " "type:%s, " "flag:%d, " "f_val:%p, " "alloc:%p, " "callbacks: %p}", "heap", "size_t", h_, h_->buffer, h_->capacity, h_->count, t, h_->flag, h_->f_val, h_->alloc, (h_)->callbacks); } _Bool h_print(struct heap * _heap_, FILE * fptr, const char *start, const char *separator, const char *end) { fprintf(fptr, "%s", start); for (size_t i = 0; i < _heap_->count; i++) { if (!_heap_->f_val->str(fptr, _heap_->buffer[i])) return 0; if (i + 1 < _heap_->count) fprintf(fptr, "%s", separator); } fprintf(fptr, "%s", end); return 1; } - - \ No newline at end of file +static void h_impl_float_up(struct heap *_heap_, size_t index); +static void h_impl_float_down(struct heap *_heap_, size_t index); +struct heap *h_new(size_t capacity, enum cmc_heap_order HO, struct heap_fval *f_val) +{ + return h_new_custom(capacity, HO, f_val, ((void *)0), ((void *)0)); +} +struct heap *h_new_custom(size_t capacity, enum cmc_heap_order HO, struct heap_fval *f_val, + struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks) +{ + ; + if (capacity < 1) + return ((void *)0); + if (HO != CMC_MIN_HEAP && HO != CMC_MAX_HEAP) + return ((void *)0); + if (!f_val) + return ((void *)0); + if (!alloc) + alloc = &cmc_alloc_node_default; + struct heap *_heap_ = alloc->malloc(sizeof(struct heap)); + if (!_heap_) + return ((void *)0); + _heap_->buffer = alloc->calloc(capacity, sizeof(size_t)); + if (!_heap_->buffer) + { + alloc->free(_heap_); + return ((void *)0); + } + _heap_->capacity = capacity; + _heap_->count = 0; + _heap_->HO = HO; + _heap_->flag = CMC_FLAG_OK; + _heap_->f_val = f_val; + _heap_->alloc = alloc; + (_heap_)->callbacks = callbacks; + return _heap_; +} +void h_clear(struct heap *_heap_) +{ + if (_heap_->f_val->free) + { + for (size_t i = 0; i < _heap_->count; i++) + { + _heap_->f_val->free(_heap_->buffer[i]); + } + } + memset(_heap_->buffer, 0, sizeof(size_t) * _heap_->capacity); + _heap_->count = 0; + _heap_->flag = CMC_FLAG_OK; +} +void h_free(struct heap *_heap_) +{ + if (_heap_->f_val->free) + { + for (size_t i = 0; i < _heap_->count; i++) + { + _heap_->f_val->free(_heap_->buffer[i]); + } + } + _heap_->alloc->free(_heap_->buffer); + _heap_->alloc->free(_heap_); +} +void h_customize(struct heap *_heap_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks) +{ + ; + if (!alloc) + _heap_->alloc = &cmc_alloc_node_default; + else + _heap_->alloc = alloc; + (_heap_)->callbacks = callbacks; + _heap_->flag = CMC_FLAG_OK; +} +_Bool h_insert(struct heap *_heap_, size_t value) +{ + if (h_full(_heap_)) + { + if (!h_resize(_heap_, _heap_->count * 2)) + return 0; + } + _heap_->buffer[_heap_->count++] = value; + if (_heap_->count > 1) + { + h_impl_float_up(_heap_, _heap_->count - 1); + } + _heap_->flag = CMC_FLAG_OK; + if ((_heap_)->callbacks && (_heap_)->callbacks->create) + (_heap_)->callbacks->create(); + ; + return 1; +} +_Bool h_remove(struct heap *_heap_) +{ + if (h_empty(_heap_)) + { + _heap_->flag = CMC_FLAG_EMPTY; + return 0; + } + _heap_->buffer[0] = _heap_->buffer[_heap_->count - 1]; + _heap_->buffer[_heap_->count - 1] = (size_t){ 0 }; + _heap_->count--; + h_impl_float_down(_heap_, 0); + _heap_->flag = CMC_FLAG_OK; + if ((_heap_)->callbacks && (_heap_)->callbacks->delete) + (_heap_)->callbacks->delete (); + ; + return 1; +} +size_t h_peek(struct heap *_heap_) +{ + if (h_empty(_heap_)) + { + _heap_->flag = CMC_FLAG_EMPTY; + return (size_t){ 0 }; + } + _heap_->flag = CMC_FLAG_OK; + if ((_heap_)->callbacks && (_heap_)->callbacks->read) + (_heap_)->callbacks->read(); + ; + return _heap_->buffer[0]; +} +_Bool h_contains(struct heap *_heap_, size_t value) +{ + _heap_->flag = CMC_FLAG_OK; + _Bool result = 0; + for (size_t i = 0; i < _heap_->count; i++) + { + if (_heap_->f_val->cmp(_heap_->buffer[i], value) == 0) + { + result = 1; + break; + } + } + if ((_heap_)->callbacks && (_heap_)->callbacks->read) + (_heap_)->callbacks->read(); + ; + return result; +} +_Bool h_empty(struct heap *_heap_) +{ + return _heap_->count == 0; +} +_Bool h_full(struct heap *_heap_) +{ + return _heap_->count >= _heap_->capacity; +} +size_t h_count(struct heap *_heap_) +{ + return _heap_->count; +} +size_t h_capacity(struct heap *_heap_) +{ + return _heap_->capacity; +} +int h_flag(struct heap *_heap_) +{ + return _heap_->flag; +} +_Bool h_resize(struct heap *_heap_, size_t capacity) +{ + _heap_->flag = CMC_FLAG_OK; + if (_heap_->capacity == capacity) + goto success; + if (capacity < _heap_->count) + { + _heap_->flag = CMC_FLAG_INVALID; + return 0; + } + size_t *new_buffer = _heap_->alloc->realloc(_heap_->buffer, sizeof(size_t) * capacity); + if (!new_buffer) + { + _heap_->flag = CMC_FLAG_ALLOC; + return 0; + } + _heap_->buffer = new_buffer; + _heap_->capacity = capacity; +success: + if ((_heap_)->callbacks && (_heap_)->callbacks->resize) + (_heap_)->callbacks->resize(); + ; + return 1; +} +struct heap *h_copy_of(struct heap *_heap_) +{ + struct heap *result = h_new_custom(_heap_->capacity, _heap_->HO, _heap_->f_val, _heap_->alloc, ((void *)0)); + if (!result) + { + _heap_->flag = CMC_FLAG_ERROR; + return ((void *)0); + } + (result)->callbacks = _heap_->callbacks; + if (_heap_->f_val->cpy) + { + for (size_t i = 0; i < _heap_->count; i++) + result->buffer[i] = _heap_->f_val->cpy(_heap_->buffer[i]); + } + else + memcpy(result->buffer, _heap_->buffer, sizeof(size_t) * _heap_->count); + result->count = _heap_->count; + _heap_->flag = CMC_FLAG_OK; + return result; +} +_Bool h_equals(struct heap *_heap1_, struct heap *_heap2_) +{ + _heap1_->flag = CMC_FLAG_OK; + _heap2_->flag = CMC_FLAG_OK; + if (_heap1_->count != _heap2_->count) + return 0; + for (size_t i = 0; i < _heap1_->count; i++) + { + if (_heap1_->f_val->cmp(_heap1_->buffer[i], _heap2_->buffer[i]) != 0) + return 0; + } + return 1; +} +static void h_impl_float_up(struct heap *_heap_, size_t index) +{ + size_t C = index; + size_t child = _heap_->buffer[C]; + size_t parent = _heap_->buffer[(index - 1) / 2]; + int mod = _heap_->HO; + while (C > 0 && _heap_->f_val->cmp(child, parent) * mod > 0) + { + size_t tmp = _heap_->buffer[C]; + _heap_->buffer[C] = _heap_->buffer[(C - 1) / 2]; + _heap_->buffer[(C - 1) / 2] = tmp; + C = (C - 1) / 2; + if (C == 0) + break; + child = _heap_->buffer[C]; + parent = _heap_->buffer[(C - 1) / 2]; + } +} +static void h_impl_float_down(struct heap *_heap_, size_t index) +{ + int mod = _heap_->HO; + while (index < _heap_->count) + { + size_t L = 2 * index + 1; + size_t R = 2 * index + 2; + size_t C = index; + if (L < _heap_->count && _heap_->f_val->cmp(_heap_->buffer[L], _heap_->buffer[C]) * mod > 0) + { + C = L; + } + if (R < _heap_->count && _heap_->f_val->cmp(_heap_->buffer[R], _heap_->buffer[C]) * mod > 0) + { + C = R; + } + if (C != index) + { + size_t tmp = _heap_->buffer[index]; + _heap_->buffer[index] = _heap_->buffer[C]; + _heap_->buffer[C] = tmp; + index = C; + } + else + break; + } +} +struct heap_iter h_iter_start(struct heap *target) +{ + struct heap_iter iter; + iter.target = target; + iter.cursor = 0; + iter.start = 1; + iter.end = h_empty(target); + return iter; +} +struct heap_iter h_iter_end(struct heap *target) +{ + struct heap_iter iter; + iter.target = target; + iter.cursor = 0; + iter.start = h_empty(target); + iter.end = 1; + if (!h_empty(target)) + iter.cursor = target->count - 1; + return iter; +} +_Bool h_iter_at_start(struct heap_iter *iter) +{ + return h_empty(iter->target) || iter->start; +} +_Bool h_iter_at_end(struct heap_iter *iter) +{ + return h_empty(iter->target) || iter->end; +} +_Bool h_iter_to_start(struct heap_iter *iter) +{ + if (!h_empty(iter->target)) + { + iter->cursor = 0; + iter->start = 1; + iter->end = h_empty(iter->target); + return 1; + } + return 0; +} +_Bool h_iter_to_end(struct heap_iter *iter) +{ + if (!h_empty(iter->target)) + { + iter->cursor = iter->target->count - 1; + iter->start = h_empty(iter->target); + iter->end = 1; + return 1; + } + return 0; +} +_Bool h_iter_next(struct heap_iter *iter) +{ + if (iter->end) + return 0; + if (iter->cursor + 1 == iter->target->count) + { + iter->end = 1; + return 0; + } + iter->start = h_empty(iter->target); + iter->cursor++; + return 1; +} +_Bool h_iter_prev(struct heap_iter *iter) +{ + if (iter->start) + return 0; + if (iter->cursor == 0) + { + iter->start = 1; + return 0; + } + iter->end = h_empty(iter->target); + iter->cursor--; + return 1; +} +_Bool h_iter_advance(struct heap_iter *iter, size_t steps) +{ + if (iter->end) + return 0; + if (iter->cursor + 1 == iter->target->count) + { + iter->end = 1; + return 0; + } + if (steps == 0 || iter->cursor + steps >= iter->target->count) + return 0; + if (iter->end) + return 0; + iter->start = h_empty(iter->target); + iter->cursor += steps; + return 1; +} +_Bool h_iter_rewind(struct heap_iter *iter, size_t steps) +{ + if (iter->start) + return 0; + if (iter->cursor == 0) + { + iter->start = 1; + return 0; + } + if (steps == 0 || iter->cursor < steps) + return 0; + iter->end = h_empty(iter->target); + iter->cursor -= steps; + return 1; +} +_Bool h_iter_go_to(struct heap_iter *iter, size_t index) +{ + if (index >= iter->target->count) + return 0; + if (iter->cursor > index) + return h_iter_rewind(iter, iter->cursor - index); + else if (iter->cursor < index) + return h_iter_advance(iter, index - iter->cursor); + return 1; +} +size_t h_iter_value(struct heap_iter *iter) +{ + if (h_empty(iter->target)) + return (size_t){ 0 }; + return iter->target->buffer[iter->cursor]; +} +size_t h_iter_index(struct heap_iter *iter) +{ + return iter->cursor; +} +_Bool h_to_string(struct heap *_heap_, FILE *fptr) +{ + struct heap *h_ = _heap_; + const char *t = h_->HO == 1 ? "MaxHeap" : "MinHeap"; + return 0 <= fprintf(fptr, + "struct %s<%s> " + "at %p { " + "buffer:%p, " + "capacity:%" + "I64u" + ", " + "count:%" + "I64u" + ", " + "type:%s, " + "flag:%d, " + "f_val:%p, " + "alloc:%p, " + "callbacks: %p}", + "heap", "size_t", h_, h_->buffer, h_->capacity, h_->count, t, h_->flag, h_->f_val, h_->alloc, + (h_)->callbacks); +} +_Bool h_print(struct heap *_heap_, FILE *fptr, const char *start, const char *separator, const char *end) +{ + fprintf(fptr, "%s", start); + for (size_t i = 0; i < _heap_->count; i++) + { + if (!_heap_->f_val->str(fptr, _heap_->buffer[i])) + return 0; + if (i + 1 < _heap_->count) + fprintf(fptr, "%s", separator); + } + fprintf(fptr, "%s", end); + return 1; +} diff --git a/tests/src/tst_cmc_intervalheap.c b/tests/src/tst_cmc_intervalheap.c index 38d680c..e83970e 100644 --- a/tests/src/tst_cmc_intervalheap.c +++ b/tests/src/tst_cmc_intervalheap.c @@ -1,7 +1,686 @@ - #include "tst_cmc_intervalheap.h" +#include "tst_cmc_intervalheap.h" - - static void ih_impl_float_up_max(struct intervalheap * _heap_); static void ih_impl_float_up_min(struct intervalheap * _heap_); static void ih_impl_float_down_max(struct intervalheap * _heap_); static void ih_impl_float_down_min(struct intervalheap * _heap_); struct intervalheap *ih_new(size_t capacity, struct intervalheap_fval * f_val) { return ih_new_custom(capacity, f_val, ((void *)0), ((void *)0)); } struct intervalheap *ih_new_custom(size_t capacity, struct intervalheap_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (capacity == 0 || capacity == 0xffffffffffffffffULL) return ((void *)0); if (!f_val) return ((void *)0); if (!alloc) alloc = &cmc_alloc_node_default; struct intervalheap *_heap_ = alloc->malloc(sizeof(struct intervalheap)); if (!_heap_) return ((void *)0); capacity = (capacity + capacity % 2) / 2; _heap_->buffer = alloc->calloc(capacity, sizeof(size_t[2])); if (!_heap_->buffer) { alloc->free(_heap_); return ((void *)0); } _heap_->capacity = capacity; _heap_->size = 0; _heap_->count = 0; _heap_->flag = CMC_FLAG_OK; _heap_->f_val = f_val; _heap_->alloc = alloc; (_heap_)->callbacks = callbacks; return _heap_; } void ih_clear(struct intervalheap * _heap_) { if (_heap_->f_val->free) { for (size_t i = 0; i < _heap_->count; i++) { _heap_->f_val->free(_heap_->buffer[i / 2][i % 2]); } } memset(_heap_->buffer, 0, sizeof(size_t[2]) * _heap_->capacity); _heap_->size = 0; _heap_->count = 0; _heap_->flag = CMC_FLAG_OK; } void ih_free(struct intervalheap * _heap_) { if (_heap_->f_val->free) { for (size_t i = 0; i < _heap_->count; i++) { _heap_->f_val->free(_heap_->buffer[i / 2][i % 2]); } } _heap_->alloc->free(_heap_->buffer); _heap_->alloc->free(_heap_); } void ih_customize(struct intervalheap * _heap_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (!alloc) _heap_->alloc = &cmc_alloc_node_default; else _heap_->alloc = alloc; (_heap_)->callbacks = callbacks; _heap_->flag = CMC_FLAG_OK; } _Bool ih_insert(struct intervalheap * _heap_, size_t value) { if (ih_full(_heap_)) { if (!ih_resize(_heap_, _heap_->capacity * 4)) return 0; } if (_heap_->count % 2 == 0) { _heap_->buffer[_heap_->size][0] = value; _heap_->buffer[_heap_->size][1] = (size_t){ 0 }; _heap_->size++; } else { size_t(*node)[2] = &(_heap_->buffer[_heap_->size - 1]); if (_heap_->f_val->cmp((*node)[0], value) > 0) { (*node)[1] = (*node)[0]; (*node)[0] = value; } else { (*node)[1] = value; } } _heap_->count++; _heap_->flag = CMC_FLAG_OK; if (_heap_->count > 2) { size_t(*parent)[2] = &(_heap_->buffer[(_heap_->size - 2) / 2]); if (_heap_->f_val->cmp((*parent)[0], value) > 0) ih_impl_float_up_min(_heap_); else if (_heap_->f_val->cmp((*parent)[1], value) < 0) ih_impl_float_up_max(_heap_); } if ((_heap_)->callbacks && (_heap_)->callbacks->create) (_heap_)->callbacks->create();; return 1; } _Bool ih_remove_max(struct intervalheap * _heap_) { if (ih_empty(_heap_)) { _heap_->flag = CMC_FLAG_EMPTY; return 0; } if (_heap_->count == 1) { _heap_->buffer[0][0] = (size_t){ 0 }; _heap_->count--; _heap_->size--; goto success; } size_t(*last_node)[2] = &(_heap_->buffer[_heap_->size - 1]); if (_heap_->count % 2 == 1) { _heap_->buffer[0][1] = (*last_node)[0]; (*last_node)[0] = (size_t){ 0 }; _heap_->size--; } else { _heap_->buffer[0][1] = (*last_node)[1]; (*last_node)[1] = (size_t){ 0 }; } _heap_->count--; ih_impl_float_down_max(_heap_); success: _heap_->flag = CMC_FLAG_OK; if ((_heap_)->callbacks && (_heap_)->callbacks->delete) (_heap_)->callbacks->delete();; return 1; } _Bool ih_remove_min(struct intervalheap * _heap_) { if (ih_empty(_heap_)) { _heap_->flag = CMC_FLAG_EMPTY; return 0; } if (_heap_->count == 1) { _heap_->buffer[0][0] = (size_t){ 0 }; _heap_->count--; _heap_->size--; goto success; } size_t(*last_node)[2] = &(_heap_->buffer[_heap_->size - 1]); _heap_->buffer[0][0] = (*last_node)[0]; if (_heap_->count % 2 == 1) { (*last_node)[0] = (size_t){ 0 }; _heap_->size--; } else { (*last_node)[0] = (*last_node)[1]; (*last_node)[1] = (size_t){ 0 }; } _heap_->count--; ih_impl_float_down_min(_heap_); success: _heap_->flag = CMC_FLAG_OK; if ((_heap_)->callbacks && (_heap_)->callbacks->delete) (_heap_)->callbacks->delete();; return 1; } _Bool ih_update_max(struct intervalheap * _heap_, size_t value) { if (ih_empty(_heap_)) { _heap_->flag = CMC_FLAG_EMPTY; return 0; } if (_heap_->count == 1) { _heap_->buffer[0][0] = value; } else if (_heap_->f_val->cmp(value, _heap_->buffer[0][0]) < 0) { _heap_->buffer[0][1] = _heap_->buffer[0][0]; _heap_->buffer[0][0] = value; ih_impl_float_down_max(_heap_); } else { _heap_->buffer[0][1] = value; ih_impl_float_down_max(_heap_); } _heap_->flag = CMC_FLAG_OK; if ((_heap_)->callbacks && (_heap_)->callbacks->update) (_heap_)->callbacks->update();; return 1; } _Bool ih_update_min(struct intervalheap * _heap_, size_t value) { if (ih_empty(_heap_)) { _heap_->flag = CMC_FLAG_EMPTY; return 0; } if (_heap_->count == 1) { _heap_->buffer[0][0] = value; } else if (_heap_->f_val->cmp(value, _heap_->buffer[0][1]) > 0) { _heap_->buffer[0][0] = _heap_->buffer[0][1]; _heap_->buffer[0][1] = value; ih_impl_float_down_min(_heap_); } else { _heap_->buffer[0][0] = value; ih_impl_float_down_min(_heap_); } _heap_->flag = CMC_FLAG_OK; if ((_heap_)->callbacks && (_heap_)->callbacks->update) (_heap_)->callbacks->update();; return 1; } size_t ih_max(struct intervalheap * _heap_) { if (ih_empty(_heap_)) { _heap_->flag = CMC_FLAG_EMPTY; return (size_t){ 0 }; } _heap_->flag = CMC_FLAG_OK; if ((_heap_)->callbacks && (_heap_)->callbacks->read) (_heap_)->callbacks->read();; if (_heap_->count == 1) return _heap_->buffer[0][0]; return _heap_->buffer[0][1]; } size_t ih_min(struct intervalheap * _heap_) { if (ih_empty(_heap_)) { _heap_->flag = CMC_FLAG_EMPTY; return (size_t){ 0 }; } _heap_->flag = CMC_FLAG_OK; if ((_heap_)->callbacks && (_heap_)->callbacks->read) (_heap_)->callbacks->read();; return _heap_->buffer[0][0]; } _Bool ih_contains(struct intervalheap * _heap_, size_t value) { _heap_->flag = CMC_FLAG_OK; _Bool result = 0; for (size_t i = 0; i < _heap_->count; i++) { if (_heap_->f_val->cmp(_heap_->buffer[i / 2][i % 2], value) == 0) { result = 1; break; } } if ((_heap_)->callbacks && (_heap_)->callbacks->read) (_heap_)->callbacks->read();; return result; } _Bool ih_empty(struct intervalheap * _heap_) { return _heap_->count == 0; } _Bool ih_full(struct intervalheap * _heap_) { return _heap_->size >= _heap_->capacity && _heap_->count % 2 == 0; } size_t ih_count(struct intervalheap * _heap_) { return _heap_->count; } size_t ih_capacity(struct intervalheap * _heap_) { return _heap_->capacity; } int ih_flag(struct intervalheap * _heap_) { return _heap_->flag; } _Bool ih_resize(struct intervalheap * _heap_, size_t capacity) { if (_heap_->capacity == capacity) goto success; if (capacity < _heap_->count) { _heap_->flag = CMC_FLAG_INVALID; return 0; } if (capacity == 0xffffffffffffffffULL) { _heap_->flag = CMC_FLAG_ERROR; return 0; } capacity += capacity % 2; size_t(*new_buffer)[2] = _heap_->alloc->realloc(_heap_->buffer, sizeof(size_t[2]) * capacity); if (!new_buffer) { _heap_->flag = CMC_FLAG_ALLOC; return 0; } if (capacity > _heap_->capacity) { memset(new_buffer + _heap_->capacity, 0, sizeof(size_t[2]) * (capacity - _heap_->capacity)); } _heap_->buffer = new_buffer; _heap_->capacity = capacity; success: _heap_->flag = CMC_FLAG_OK; if ((_heap_)->callbacks && (_heap_)->callbacks->resize) (_heap_)->callbacks->resize();; return 1; } struct intervalheap *ih_copy_of(struct intervalheap * _heap_) { struct intervalheap *result = _heap_->alloc->malloc(sizeof(struct intervalheap)); if (!result) { _heap_->flag = CMC_FLAG_ALLOC; return ((void *)0); } memcpy(result, _heap_, sizeof(struct intervalheap)); result->buffer = _heap_->alloc->malloc(sizeof(size_t[2]) * _heap_->capacity); if (!result->buffer) { _heap_->alloc->free(result); _heap_->flag = CMC_FLAG_ALLOC; return ((void *)0); } if (_heap_->f_val->cpy) { for (size_t i = 0; i < _heap_->count; i++) result->buffer[i / 2][i % 2] = _heap_->f_val->cpy(_heap_->buffer[i / 2][i % 2]); } else memcpy(result->buffer, _heap_->buffer, sizeof(size_t[2]) * _heap_->capacity); result->capacity = _heap_->capacity; result->size = _heap_->size; result->count = _heap_->count; result->flag = CMC_FLAG_OK; result->f_val = _heap_->f_val; result->alloc = _heap_->alloc; (result)->callbacks = _heap_->callbacks; _heap_->flag = CMC_FLAG_OK; return result; } _Bool ih_equals(struct intervalheap * _heap1_, struct intervalheap * _heap2_) { _heap1_->flag = CMC_FLAG_OK; _heap2_->flag = CMC_FLAG_OK; if (_heap1_->count != _heap2_->count) return 0; for (size_t i = 0; i < _heap1_->count; i++) { size_t value1 = _heap1_->buffer[i / 2][i % 2]; size_t value2 = _heap2_->buffer[i / 2][i % 2]; if (_heap1_->f_val->cmp(value1, value2) != 0) return 0; } return 1; } static void ih_impl_float_up_max(struct intervalheap * _heap_) { size_t index = _heap_->size - 1; size_t(*curr_node)[2] = &(_heap_->buffer[index]); while (index > 0) { size_t P_index = (index - 1) / 2; size_t(*parent)[2] = &(_heap_->buffer[P_index]); if (index == _heap_->size - 1 && _heap_->count % 2 != 0) { if (_heap_->f_val->cmp((*curr_node)[0], (*parent)[1]) < 0) break; size_t tmp = (*curr_node)[0]; (*curr_node)[0] = (*parent)[1]; (*parent)[1] = tmp; } else { if (_heap_->f_val->cmp((*curr_node)[1], (*parent)[1]) < 0) break; size_t tmp = (*curr_node)[1]; (*curr_node)[1] = (*parent)[1]; (*parent)[1] = tmp; } index = P_index; curr_node = parent; } } static void ih_impl_float_up_min(struct intervalheap * _heap_) { size_t index = _heap_->size - 1; size_t(*curr_node)[2] = &(_heap_->buffer[index]); while (index > 0) { size_t P_index = (index - 1) / 2; size_t(*parent)[2] = &(_heap_->buffer[P_index]); if (_heap_->f_val->cmp((*curr_node)[0], (*parent)[0]) >= 0) break; size_t tmp = (*curr_node)[0]; (*curr_node)[0] = (*parent)[0]; (*parent)[0] = tmp; index = P_index; curr_node = parent; } } static void ih_impl_float_down_max(struct intervalheap * _heap_) { size_t index = 0; size_t(*curr_node)[2] = &(_heap_->buffer[index]); while (1) { if (2 * index + 1 >= _heap_->size) break; size_t child; size_t L_index = index * 2 + 1; size_t R_index = index * 2 + 2; if (R_index < _heap_->size) { size_t(*L)[2] = &(_heap_->buffer[L_index]); size_t(*R)[2] = &(_heap_->buffer[R_index]); if (R_index == _heap_->size - 1 && _heap_->count % 2 != 0) child = _heap_->f_val->cmp((*L)[1], (*R)[0]) > 0 ? L_index : R_index; else child = _heap_->f_val->cmp((*L)[1], (*R)[1]) > 0 ? L_index : R_index; } else child = L_index; size_t(*child_node)[2] = &(_heap_->buffer[child]); if (child == _heap_->size - 1 && _heap_->count % 2 != 0) { if (_heap_->f_val->cmp((*curr_node)[1], (*child_node)[0]) >= 0) break; size_t tmp = (*child_node)[0]; (*child_node)[0] = (*curr_node)[1]; (*curr_node)[1] = tmp; } else { if (_heap_->f_val->cmp((*curr_node)[1], (*child_node)[1]) >= 0) break; size_t tmp = (*child_node)[1]; (*child_node)[1] = (*curr_node)[1]; (*curr_node)[1] = tmp; if (_heap_->f_val->cmp((*child_node)[0], (*child_node)[1]) > 0) { tmp = (*child_node)[0]; (*child_node)[0] = (*child_node)[1]; (*child_node)[1] = tmp; } } index = child; curr_node = child_node; } } static void ih_impl_float_down_min(struct intervalheap * _heap_) { size_t index = 0; size_t(*curr_node)[2] = &(_heap_->buffer[index]); while (1) { if (2 * index + 1 >= _heap_->size) break; size_t child; size_t L_index = index * 2 + 1; size_t R_index = index * 2 + 2; if (R_index < _heap_->size) { size_t(*L)[2] = &(_heap_->buffer[L_index]); size_t(*R)[2] = &(_heap_->buffer[R_index]); child = _heap_->f_val->cmp((*L)[0], (*R)[0]) < 0 ? L_index : R_index; } else child = L_index; size_t(*child_node)[2] = &(_heap_->buffer[child]); if (_heap_->f_val->cmp((*curr_node)[0], (*child_node)[0]) < 0) break; size_t tmp = (*child_node)[0]; (*child_node)[0] = (*curr_node)[0]; (*curr_node)[0] = tmp; if (child != _heap_->size - 1 || _heap_->count % 2 == 0) { if (_heap_->f_val->cmp((*child_node)[0], (*child_node)[1]) > 0) { tmp = (*child_node)[0]; (*child_node)[0] = (*child_node)[1]; (*child_node)[1] = tmp; } } index = child; curr_node = child_node; } } struct intervalheap_iter ih_iter_start(struct intervalheap * target) { struct intervalheap_iter iter; iter.target = target; iter.cursor = 0; iter.start = 1; iter.end = ih_empty(target); return iter; } struct intervalheap_iter ih_iter_end(struct intervalheap * target) { struct intervalheap_iter iter; iter.target = target; iter.cursor = 0; iter.start = ih_empty(target); iter.end = 1; if (!ih_empty(target)) iter.cursor = target->count - 1; return iter; } _Bool ih_iter_at_start(struct intervalheap_iter * iter) { return ih_empty(iter->target) || iter->start; } _Bool ih_iter_at_end(struct intervalheap_iter * iter) { return ih_empty(iter->target) || iter->end; } _Bool ih_iter_to_start(struct intervalheap_iter * iter) { if (!ih_empty(iter->target)) { iter->cursor = 0; iter->start = 1; iter->end = ih_empty(iter->target); return 1; } return 0; } _Bool ih_iter_to_end(struct intervalheap_iter * iter) { if (!ih_empty(iter->target)) { iter->cursor = iter->target->count - 1; iter->start = ih_empty(iter->target); iter->end = 1; return 1; } return 0; } _Bool ih_iter_next(struct intervalheap_iter * iter) { if (iter->end) return 0; if (iter->cursor + 1 == iter->target->count) { iter->end = 1; return 0; } iter->start = ih_empty(iter->target); iter->cursor++; return 1; } _Bool ih_iter_prev(struct intervalheap_iter * iter) { if (iter->start) return 0; if (iter->cursor == 0) { iter->start = 1; return 0; } iter->end = ih_empty(iter->target); iter->cursor--; return 1; } _Bool ih_iter_advance(struct intervalheap_iter * iter, size_t steps) { if (iter->end) return 0; if (iter->cursor + 1 == iter->target->count) { iter->end = 1; return 0; } if (steps == 0 || iter->cursor + steps >= iter->target->count) return 0; if (iter->end) return 0; iter->start = ih_empty(iter->target); iter->cursor += steps; return 1; } _Bool ih_iter_rewind(struct intervalheap_iter * iter, size_t steps) { if (iter->start) return 0; if (iter->cursor == 0) { iter->start = 1; return 0; } if (steps == 0 || iter->cursor < steps) return 0; iter->end = ih_empty(iter->target); iter->cursor -= steps; return 1; } _Bool ih_iter_go_to(struct intervalheap_iter * iter, size_t index) { if (index >= iter->target->count) return 0; if (iter->cursor > index) return ih_iter_rewind(iter, iter->cursor - index); else if (iter->cursor < index) return ih_iter_advance(iter, index - iter->cursor); return 1; } size_t ih_iter_value(struct intervalheap_iter * iter) { if (ih_empty(iter->target)) return (size_t){ 0 }; return iter->target->buffer[iter->cursor / 2][iter->cursor % 2]; } size_t ih_iter_index(struct intervalheap_iter * iter) { return iter->cursor; } _Bool ih_to_string(struct intervalheap * _heap_, FILE * fptr) { struct intervalheap *h_ = _heap_; return 0 <= fprintf(fptr, "struct %s<%s> " "at %p { " "buffer:%p, " "capacity:%" "I64u" ", " "size:%" "I64u" ", " "count:%" "I64u" ", " "flag:%d, " "f_val:%p, " "alloc:%p, " "callbacks:%p }", "intervalheap", "size_t", h_, h_->buffer, h_->capacity, h_->size, h_->count, h_->flag, h_->f_val, h_->alloc, (h_)->callbacks); } _Bool ih_print(struct intervalheap * _heap_, FILE * fptr, const char *start, const char *separator, const char *end) { fprintf(fptr, "%s", start); for (size_t i = 0; i < _heap_->count; i++) { if (!_heap_->f_val->str(fptr, _heap_->buffer[i / 2][i % 2])) return 0; if (i + 1 < _heap_->count) fprintf(fptr, "%s", separator); } fprintf(fptr, "%s", end); return 1; } - - \ No newline at end of file +static void ih_impl_float_up_max(struct intervalheap *_heap_); +static void ih_impl_float_up_min(struct intervalheap *_heap_); +static void ih_impl_float_down_max(struct intervalheap *_heap_); +static void ih_impl_float_down_min(struct intervalheap *_heap_); +struct intervalheap *ih_new(size_t capacity, struct intervalheap_fval *f_val) +{ + return ih_new_custom(capacity, f_val, ((void *)0), ((void *)0)); +} +struct intervalheap *ih_new_custom(size_t capacity, struct intervalheap_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks) +{ + ; + if (capacity == 0 || capacity == 0xffffffffffffffffULL) + return ((void *)0); + if (!f_val) + return ((void *)0); + if (!alloc) + alloc = &cmc_alloc_node_default; + struct intervalheap *_heap_ = alloc->malloc(sizeof(struct intervalheap)); + if (!_heap_) + return ((void *)0); + capacity = (capacity + capacity % 2) / 2; + _heap_->buffer = alloc->calloc(capacity, sizeof(size_t[2])); + if (!_heap_->buffer) + { + alloc->free(_heap_); + return ((void *)0); + } + _heap_->capacity = capacity; + _heap_->size = 0; + _heap_->count = 0; + _heap_->flag = CMC_FLAG_OK; + _heap_->f_val = f_val; + _heap_->alloc = alloc; + (_heap_)->callbacks = callbacks; + return _heap_; +} +void ih_clear(struct intervalheap *_heap_) +{ + if (_heap_->f_val->free) + { + for (size_t i = 0; i < _heap_->count; i++) + { + _heap_->f_val->free(_heap_->buffer[i / 2][i % 2]); + } + } + memset(_heap_->buffer, 0, sizeof(size_t[2]) * _heap_->capacity); + _heap_->size = 0; + _heap_->count = 0; + _heap_->flag = CMC_FLAG_OK; +} +void ih_free(struct intervalheap *_heap_) +{ + if (_heap_->f_val->free) + { + for (size_t i = 0; i < _heap_->count; i++) + { + _heap_->f_val->free(_heap_->buffer[i / 2][i % 2]); + } + } + _heap_->alloc->free(_heap_->buffer); + _heap_->alloc->free(_heap_); +} +void ih_customize(struct intervalheap *_heap_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks) +{ + ; + if (!alloc) + _heap_->alloc = &cmc_alloc_node_default; + else + _heap_->alloc = alloc; + (_heap_)->callbacks = callbacks; + _heap_->flag = CMC_FLAG_OK; +} +_Bool ih_insert(struct intervalheap *_heap_, size_t value) +{ + if (ih_full(_heap_)) + { + if (!ih_resize(_heap_, _heap_->capacity * 4)) + return 0; + } + if (_heap_->count % 2 == 0) + { + _heap_->buffer[_heap_->size][0] = value; + _heap_->buffer[_heap_->size][1] = (size_t){ 0 }; + _heap_->size++; + } + else + { + size_t(*node)[2] = &(_heap_->buffer[_heap_->size - 1]); + if (_heap_->f_val->cmp((*node)[0], value) > 0) + { + (*node)[1] = (*node)[0]; + (*node)[0] = value; + } + else + { + (*node)[1] = value; + } + } + _heap_->count++; + _heap_->flag = CMC_FLAG_OK; + if (_heap_->count > 2) + { + size_t(*parent)[2] = &(_heap_->buffer[(_heap_->size - 2) / 2]); + if (_heap_->f_val->cmp((*parent)[0], value) > 0) + ih_impl_float_up_min(_heap_); + else if (_heap_->f_val->cmp((*parent)[1], value) < 0) + ih_impl_float_up_max(_heap_); + } + if ((_heap_)->callbacks && (_heap_)->callbacks->create) + (_heap_)->callbacks->create(); + ; + return 1; +} +_Bool ih_remove_max(struct intervalheap *_heap_) +{ + if (ih_empty(_heap_)) + { + _heap_->flag = CMC_FLAG_EMPTY; + return 0; + } + if (_heap_->count == 1) + { + _heap_->buffer[0][0] = (size_t){ 0 }; + _heap_->count--; + _heap_->size--; + goto success; + } + size_t(*last_node)[2] = &(_heap_->buffer[_heap_->size - 1]); + if (_heap_->count % 2 == 1) + { + _heap_->buffer[0][1] = (*last_node)[0]; + (*last_node)[0] = (size_t){ 0 }; + _heap_->size--; + } + else + { + _heap_->buffer[0][1] = (*last_node)[1]; + (*last_node)[1] = (size_t){ 0 }; + } + _heap_->count--; + ih_impl_float_down_max(_heap_); +success: + _heap_->flag = CMC_FLAG_OK; + if ((_heap_)->callbacks && (_heap_)->callbacks->delete) + (_heap_)->callbacks->delete (); + ; + return 1; +} +_Bool ih_remove_min(struct intervalheap *_heap_) +{ + if (ih_empty(_heap_)) + { + _heap_->flag = CMC_FLAG_EMPTY; + return 0; + } + if (_heap_->count == 1) + { + _heap_->buffer[0][0] = (size_t){ 0 }; + _heap_->count--; + _heap_->size--; + goto success; + } + size_t(*last_node)[2] = &(_heap_->buffer[_heap_->size - 1]); + _heap_->buffer[0][0] = (*last_node)[0]; + if (_heap_->count % 2 == 1) + { + (*last_node)[0] = (size_t){ 0 }; + _heap_->size--; + } + else + { + (*last_node)[0] = (*last_node)[1]; + (*last_node)[1] = (size_t){ 0 }; + } + _heap_->count--; + ih_impl_float_down_min(_heap_); +success: + _heap_->flag = CMC_FLAG_OK; + if ((_heap_)->callbacks && (_heap_)->callbacks->delete) + (_heap_)->callbacks->delete (); + ; + return 1; +} +_Bool ih_update_max(struct intervalheap *_heap_, size_t value) +{ + if (ih_empty(_heap_)) + { + _heap_->flag = CMC_FLAG_EMPTY; + return 0; + } + if (_heap_->count == 1) + { + _heap_->buffer[0][0] = value; + } + else if (_heap_->f_val->cmp(value, _heap_->buffer[0][0]) < 0) + { + _heap_->buffer[0][1] = _heap_->buffer[0][0]; + _heap_->buffer[0][0] = value; + ih_impl_float_down_max(_heap_); + } + else + { + _heap_->buffer[0][1] = value; + ih_impl_float_down_max(_heap_); + } + _heap_->flag = CMC_FLAG_OK; + if ((_heap_)->callbacks && (_heap_)->callbacks->update) + (_heap_)->callbacks->update(); + ; + return 1; +} +_Bool ih_update_min(struct intervalheap *_heap_, size_t value) +{ + if (ih_empty(_heap_)) + { + _heap_->flag = CMC_FLAG_EMPTY; + return 0; + } + if (_heap_->count == 1) + { + _heap_->buffer[0][0] = value; + } + else if (_heap_->f_val->cmp(value, _heap_->buffer[0][1]) > 0) + { + _heap_->buffer[0][0] = _heap_->buffer[0][1]; + _heap_->buffer[0][1] = value; + ih_impl_float_down_min(_heap_); + } + else + { + _heap_->buffer[0][0] = value; + ih_impl_float_down_min(_heap_); + } + _heap_->flag = CMC_FLAG_OK; + if ((_heap_)->callbacks && (_heap_)->callbacks->update) + (_heap_)->callbacks->update(); + ; + return 1; +} +size_t ih_max(struct intervalheap *_heap_) +{ + if (ih_empty(_heap_)) + { + _heap_->flag = CMC_FLAG_EMPTY; + return (size_t){ 0 }; + } + _heap_->flag = CMC_FLAG_OK; + if ((_heap_)->callbacks && (_heap_)->callbacks->read) + (_heap_)->callbacks->read(); + ; + if (_heap_->count == 1) + return _heap_->buffer[0][0]; + return _heap_->buffer[0][1]; +} +size_t ih_min(struct intervalheap *_heap_) +{ + if (ih_empty(_heap_)) + { + _heap_->flag = CMC_FLAG_EMPTY; + return (size_t){ 0 }; + } + _heap_->flag = CMC_FLAG_OK; + if ((_heap_)->callbacks && (_heap_)->callbacks->read) + (_heap_)->callbacks->read(); + ; + return _heap_->buffer[0][0]; +} +_Bool ih_contains(struct intervalheap *_heap_, size_t value) +{ + _heap_->flag = CMC_FLAG_OK; + _Bool result = 0; + for (size_t i = 0; i < _heap_->count; i++) + { + if (_heap_->f_val->cmp(_heap_->buffer[i / 2][i % 2], value) == 0) + { + result = 1; + break; + } + } + if ((_heap_)->callbacks && (_heap_)->callbacks->read) + (_heap_)->callbacks->read(); + ; + return result; +} +_Bool ih_empty(struct intervalheap *_heap_) +{ + return _heap_->count == 0; +} +_Bool ih_full(struct intervalheap *_heap_) +{ + return _heap_->size >= _heap_->capacity && _heap_->count % 2 == 0; +} +size_t ih_count(struct intervalheap *_heap_) +{ + return _heap_->count; +} +size_t ih_capacity(struct intervalheap *_heap_) +{ + return _heap_->capacity; +} +int ih_flag(struct intervalheap *_heap_) +{ + return _heap_->flag; +} +_Bool ih_resize(struct intervalheap *_heap_, size_t capacity) +{ + if (_heap_->capacity == capacity) + goto success; + if (capacity < _heap_->count) + { + _heap_->flag = CMC_FLAG_INVALID; + return 0; + } + if (capacity == 0xffffffffffffffffULL) + { + _heap_->flag = CMC_FLAG_ERROR; + return 0; + } + capacity += capacity % 2; + size_t(*new_buffer)[2] = _heap_->alloc->realloc(_heap_->buffer, sizeof(size_t[2]) * capacity); + if (!new_buffer) + { + _heap_->flag = CMC_FLAG_ALLOC; + return 0; + } + if (capacity > _heap_->capacity) + { + memset(new_buffer + _heap_->capacity, 0, sizeof(size_t[2]) * (capacity - _heap_->capacity)); + } + _heap_->buffer = new_buffer; + _heap_->capacity = capacity; +success: + _heap_->flag = CMC_FLAG_OK; + if ((_heap_)->callbacks && (_heap_)->callbacks->resize) + (_heap_)->callbacks->resize(); + ; + return 1; +} +struct intervalheap *ih_copy_of(struct intervalheap *_heap_) +{ + struct intervalheap *result = _heap_->alloc->malloc(sizeof(struct intervalheap)); + if (!result) + { + _heap_->flag = CMC_FLAG_ALLOC; + return ((void *)0); + } + memcpy(result, _heap_, sizeof(struct intervalheap)); + result->buffer = _heap_->alloc->malloc(sizeof(size_t[2]) * _heap_->capacity); + if (!result->buffer) + { + _heap_->alloc->free(result); + _heap_->flag = CMC_FLAG_ALLOC; + return ((void *)0); + } + if (_heap_->f_val->cpy) + { + for (size_t i = 0; i < _heap_->count; i++) + result->buffer[i / 2][i % 2] = _heap_->f_val->cpy(_heap_->buffer[i / 2][i % 2]); + } + else + memcpy(result->buffer, _heap_->buffer, sizeof(size_t[2]) * _heap_->capacity); + result->capacity = _heap_->capacity; + result->size = _heap_->size; + result->count = _heap_->count; + result->flag = CMC_FLAG_OK; + result->f_val = _heap_->f_val; + result->alloc = _heap_->alloc; + (result)->callbacks = _heap_->callbacks; + _heap_->flag = CMC_FLAG_OK; + return result; +} +_Bool ih_equals(struct intervalheap *_heap1_, struct intervalheap *_heap2_) +{ + _heap1_->flag = CMC_FLAG_OK; + _heap2_->flag = CMC_FLAG_OK; + if (_heap1_->count != _heap2_->count) + return 0; + for (size_t i = 0; i < _heap1_->count; i++) + { + size_t value1 = _heap1_->buffer[i / 2][i % 2]; + size_t value2 = _heap2_->buffer[i / 2][i % 2]; + if (_heap1_->f_val->cmp(value1, value2) != 0) + return 0; + } + return 1; +} +static void ih_impl_float_up_max(struct intervalheap *_heap_) +{ + size_t index = _heap_->size - 1; + size_t(*curr_node)[2] = &(_heap_->buffer[index]); + while (index > 0) + { + size_t P_index = (index - 1) / 2; + size_t(*parent)[2] = &(_heap_->buffer[P_index]); + if (index == _heap_->size - 1 && _heap_->count % 2 != 0) + { + if (_heap_->f_val->cmp((*curr_node)[0], (*parent)[1]) < 0) + break; + size_t tmp = (*curr_node)[0]; + (*curr_node)[0] = (*parent)[1]; + (*parent)[1] = tmp; + } + else + { + if (_heap_->f_val->cmp((*curr_node)[1], (*parent)[1]) < 0) + break; + size_t tmp = (*curr_node)[1]; + (*curr_node)[1] = (*parent)[1]; + (*parent)[1] = tmp; + } + index = P_index; + curr_node = parent; + } +} +static void ih_impl_float_up_min(struct intervalheap *_heap_) +{ + size_t index = _heap_->size - 1; + size_t(*curr_node)[2] = &(_heap_->buffer[index]); + while (index > 0) + { + size_t P_index = (index - 1) / 2; + size_t(*parent)[2] = &(_heap_->buffer[P_index]); + if (_heap_->f_val->cmp((*curr_node)[0], (*parent)[0]) >= 0) + break; + size_t tmp = (*curr_node)[0]; + (*curr_node)[0] = (*parent)[0]; + (*parent)[0] = tmp; + index = P_index; + curr_node = parent; + } +} +static void ih_impl_float_down_max(struct intervalheap *_heap_) +{ + size_t index = 0; + size_t(*curr_node)[2] = &(_heap_->buffer[index]); + while (1) + { + if (2 * index + 1 >= _heap_->size) + break; + size_t child; + size_t L_index = index * 2 + 1; + size_t R_index = index * 2 + 2; + if (R_index < _heap_->size) + { + size_t(*L)[2] = &(_heap_->buffer[L_index]); + size_t(*R)[2] = &(_heap_->buffer[R_index]); + if (R_index == _heap_->size - 1 && _heap_->count % 2 != 0) + child = _heap_->f_val->cmp((*L)[1], (*R)[0]) > 0 ? L_index : R_index; + else + child = _heap_->f_val->cmp((*L)[1], (*R)[1]) > 0 ? L_index : R_index; + } + else + child = L_index; + size_t(*child_node)[2] = &(_heap_->buffer[child]); + if (child == _heap_->size - 1 && _heap_->count % 2 != 0) + { + if (_heap_->f_val->cmp((*curr_node)[1], (*child_node)[0]) >= 0) + break; + size_t tmp = (*child_node)[0]; + (*child_node)[0] = (*curr_node)[1]; + (*curr_node)[1] = tmp; + } + else + { + if (_heap_->f_val->cmp((*curr_node)[1], (*child_node)[1]) >= 0) + break; + size_t tmp = (*child_node)[1]; + (*child_node)[1] = (*curr_node)[1]; + (*curr_node)[1] = tmp; + if (_heap_->f_val->cmp((*child_node)[0], (*child_node)[1]) > 0) + { + tmp = (*child_node)[0]; + (*child_node)[0] = (*child_node)[1]; + (*child_node)[1] = tmp; + } + } + index = child; + curr_node = child_node; + } +} +static void ih_impl_float_down_min(struct intervalheap *_heap_) +{ + size_t index = 0; + size_t(*curr_node)[2] = &(_heap_->buffer[index]); + while (1) + { + if (2 * index + 1 >= _heap_->size) + break; + size_t child; + size_t L_index = index * 2 + 1; + size_t R_index = index * 2 + 2; + if (R_index < _heap_->size) + { + size_t(*L)[2] = &(_heap_->buffer[L_index]); + size_t(*R)[2] = &(_heap_->buffer[R_index]); + child = _heap_->f_val->cmp((*L)[0], (*R)[0]) < 0 ? L_index : R_index; + } + else + child = L_index; + size_t(*child_node)[2] = &(_heap_->buffer[child]); + if (_heap_->f_val->cmp((*curr_node)[0], (*child_node)[0]) < 0) + break; + size_t tmp = (*child_node)[0]; + (*child_node)[0] = (*curr_node)[0]; + (*curr_node)[0] = tmp; + if (child != _heap_->size - 1 || _heap_->count % 2 == 0) + { + if (_heap_->f_val->cmp((*child_node)[0], (*child_node)[1]) > 0) + { + tmp = (*child_node)[0]; + (*child_node)[0] = (*child_node)[1]; + (*child_node)[1] = tmp; + } + } + index = child; + curr_node = child_node; + } +} +struct intervalheap_iter ih_iter_start(struct intervalheap *target) +{ + struct intervalheap_iter iter; + iter.target = target; + iter.cursor = 0; + iter.start = 1; + iter.end = ih_empty(target); + return iter; +} +struct intervalheap_iter ih_iter_end(struct intervalheap *target) +{ + struct intervalheap_iter iter; + iter.target = target; + iter.cursor = 0; + iter.start = ih_empty(target); + iter.end = 1; + if (!ih_empty(target)) + iter.cursor = target->count - 1; + return iter; +} +_Bool ih_iter_at_start(struct intervalheap_iter *iter) +{ + return ih_empty(iter->target) || iter->start; +} +_Bool ih_iter_at_end(struct intervalheap_iter *iter) +{ + return ih_empty(iter->target) || iter->end; +} +_Bool ih_iter_to_start(struct intervalheap_iter *iter) +{ + if (!ih_empty(iter->target)) + { + iter->cursor = 0; + iter->start = 1; + iter->end = ih_empty(iter->target); + return 1; + } + return 0; +} +_Bool ih_iter_to_end(struct intervalheap_iter *iter) +{ + if (!ih_empty(iter->target)) + { + iter->cursor = iter->target->count - 1; + iter->start = ih_empty(iter->target); + iter->end = 1; + return 1; + } + return 0; +} +_Bool ih_iter_next(struct intervalheap_iter *iter) +{ + if (iter->end) + return 0; + if (iter->cursor + 1 == iter->target->count) + { + iter->end = 1; + return 0; + } + iter->start = ih_empty(iter->target); + iter->cursor++; + return 1; +} +_Bool ih_iter_prev(struct intervalheap_iter *iter) +{ + if (iter->start) + return 0; + if (iter->cursor == 0) + { + iter->start = 1; + return 0; + } + iter->end = ih_empty(iter->target); + iter->cursor--; + return 1; +} +_Bool ih_iter_advance(struct intervalheap_iter *iter, size_t steps) +{ + if (iter->end) + return 0; + if (iter->cursor + 1 == iter->target->count) + { + iter->end = 1; + return 0; + } + if (steps == 0 || iter->cursor + steps >= iter->target->count) + return 0; + if (iter->end) + return 0; + iter->start = ih_empty(iter->target); + iter->cursor += steps; + return 1; +} +_Bool ih_iter_rewind(struct intervalheap_iter *iter, size_t steps) +{ + if (iter->start) + return 0; + if (iter->cursor == 0) + { + iter->start = 1; + return 0; + } + if (steps == 0 || iter->cursor < steps) + return 0; + iter->end = ih_empty(iter->target); + iter->cursor -= steps; + return 1; +} +_Bool ih_iter_go_to(struct intervalheap_iter *iter, size_t index) +{ + if (index >= iter->target->count) + return 0; + if (iter->cursor > index) + return ih_iter_rewind(iter, iter->cursor - index); + else if (iter->cursor < index) + return ih_iter_advance(iter, index - iter->cursor); + return 1; +} +size_t ih_iter_value(struct intervalheap_iter *iter) +{ + if (ih_empty(iter->target)) + return (size_t){ 0 }; + return iter->target->buffer[iter->cursor / 2][iter->cursor % 2]; +} +size_t ih_iter_index(struct intervalheap_iter *iter) +{ + return iter->cursor; +} +_Bool ih_to_string(struct intervalheap *_heap_, FILE *fptr) +{ + struct intervalheap *h_ = _heap_; + return 0 <= fprintf(fptr, + "struct %s<%s> " + "at %p { " + "buffer:%p, " + "capacity:%" + "I64u" + ", " + "size:%" + "I64u" + ", " + "count:%" + "I64u" + ", " + "flag:%d, " + "f_val:%p, " + "alloc:%p, " + "callbacks:%p }", + "intervalheap", "size_t", h_, h_->buffer, h_->capacity, h_->size, h_->count, h_->flag, + h_->f_val, h_->alloc, (h_)->callbacks); +} +_Bool ih_print(struct intervalheap *_heap_, FILE *fptr, const char *start, const char *separator, const char *end) +{ + fprintf(fptr, "%s", start); + for (size_t i = 0; i < _heap_->count; i++) + { + if (!_heap_->f_val->str(fptr, _heap_->buffer[i / 2][i % 2])) + return 0; + if (i + 1 < _heap_->count) + fprintf(fptr, "%s", separator); + } + fprintf(fptr, "%s", end); + return 1; +} diff --git a/tests/src/tst_cmc_linkedlist.c b/tests/src/tst_cmc_linkedlist.c index cbf5a65..2587108 100644 --- a/tests/src/tst_cmc_linkedlist.c +++ b/tests/src/tst_cmc_linkedlist.c @@ -1,7 +1,683 @@ - #include "tst_cmc_linkedlist.h" +#include "tst_cmc_linkedlist.h" - - struct linkedlist *ll_new(struct linkedlist_fval * f_val) { return ll_new_custom(f_val, ((void *)0), ((void *)0)); } struct linkedlist *ll_new_custom(struct linkedlist_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (!f_val) return ((void *)0); if (!alloc) alloc = &cmc_alloc_node_default; struct linkedlist *_list_ = alloc->malloc(sizeof(struct linkedlist)); if (!_list_) return ((void *)0); _list_->count = 0; _list_->head = ((void *)0); _list_->tail = ((void *)0); _list_->flag = CMC_FLAG_OK; _list_->f_val = f_val; _list_->alloc = alloc; (_list_)->callbacks = callbacks; return _list_; } void ll_clear(struct linkedlist * _list_) { struct linkedlist_node *scan = _list_->head; while (_list_->head != ((void *)0)) { _list_->head = _list_->head->next; if (_list_->f_val->free) { _list_->f_val->free(scan->value); } _list_->alloc->free(scan); scan = _list_->head; } _list_->count = 0; _list_->head = ((void *)0); _list_->tail = ((void *)0); _list_->flag = CMC_FLAG_OK; } void ll_free(struct linkedlist * _list_) { ll_clear(_list_); _list_->alloc->free(_list_); } void ll_customize(struct linkedlist * _list_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (!alloc) _list_->alloc = &cmc_alloc_node_default; else _list_->alloc = alloc; (_list_)->callbacks = callbacks; _list_->flag = CMC_FLAG_OK; } _Bool ll_push_front(struct linkedlist * _list_, size_t value) { struct linkedlist_node *_node_ = ll_new_node(_list_, value); if (!_node_) return 0; if (ll_empty(_list_)) { _list_->head = _node_; _list_->tail = _node_; } else { _node_->next = _list_->head; _list_->head->prev = _node_; _list_->head = _node_; } _list_->count++; _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->create) (_list_)->callbacks->create();; return 1; } _Bool ll_push_at(struct linkedlist * _list_, size_t value, size_t index) { if (index > _list_->count) { _list_->flag = CMC_FLAG_RANGE; return 0; } if (index == 0) { return ll_push_front(_list_, value); } else if (index == _list_->count) { return ll_push_back(_list_, value); } struct linkedlist_node *_node_ = ll_new_node(_list_, value); if (!_node_) return 0; struct linkedlist_node *scan = ll_get_node(_list_, index - 1); _node_->next = scan->next; _node_->prev = scan; _node_->next->prev = _node_; _node_->prev->next = _node_; _list_->count++; _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->create) (_list_)->callbacks->create();; return 1; } _Bool ll_push_back(struct linkedlist * _list_, size_t value) { struct linkedlist_node *_node_ = ll_new_node(_list_, value); if (!_node_) return 0; if (ll_empty(_list_)) { _list_->head = _node_; _list_->tail = _node_; } else { _node_->prev = _list_->tail; _list_->tail->next = _node_; _list_->tail = _node_; } _list_->count++; _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->create) (_list_)->callbacks->create();; return 1; } _Bool ll_pop_front(struct linkedlist * _list_) { if (ll_empty(_list_)) { _list_->flag = CMC_FLAG_EMPTY; return 0; } struct linkedlist_node *_node_ = _list_->head; _list_->head = _list_->head->next; _list_->alloc->free(_node_); if (_list_->head == ((void *)0)) _list_->tail = ((void *)0); else _list_->head->prev = ((void *)0); _list_->count--; _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->delete) (_list_)->callbacks->delete();; return 1; } _Bool ll_pop_at(struct linkedlist * _list_, size_t index) { if (ll_empty(_list_)) { _list_->flag = CMC_FLAG_EMPTY; return 0; } if (index >= _list_->count) { _list_->flag = CMC_FLAG_RANGE; return 0; } if (index == 0) { return ll_pop_front(_list_); } else if (index == _list_->count - 1) { return ll_pop_back(_list_); } struct linkedlist_node *_node_ = ll_get_node(_list_, index); if (!_node_) return 0; _node_->next->prev = _node_->prev; _node_->prev->next = _node_->next; _list_->alloc->free(_node_); _list_->count--; _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->delete) (_list_)->callbacks->delete();; return 1; } _Bool ll_pop_back(struct linkedlist * _list_) { if (ll_empty(_list_)) { _list_->flag = CMC_FLAG_EMPTY; return 0; } struct linkedlist_node *_node_ = _list_->tail; _list_->tail = _list_->tail->prev; _list_->alloc->free(_node_); if (_list_->tail == ((void *)0)) _list_->head = ((void *)0); else _list_->tail->next = ((void *)0); _list_->count--; _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->delete) (_list_)->callbacks->delete();; return 1; } size_t ll_front(struct linkedlist * _list_) { if (ll_empty(_list_)) { _list_->flag = CMC_FLAG_EMPTY; return (size_t){ 0 }; } _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->read) (_list_)->callbacks->read();; return _list_->head->value; } size_t ll_get(struct linkedlist * _list_, size_t index) { if (ll_empty(_list_)) { _list_->flag = CMC_FLAG_EMPTY; return (size_t){ 0 }; } if (index >= _list_->count) { _list_->flag = CMC_FLAG_RANGE; return (size_t){ 0 }; } struct linkedlist_node *scan = ll_get_node(_list_, index); if (scan == ((void *)0)) return (size_t){ 0 }; if ((_list_)->callbacks && (_list_)->callbacks->read) (_list_)->callbacks->read();; return scan->value; } size_t *ll_get_ref(struct linkedlist * _list_, size_t index) { if (ll_empty(_list_)) { _list_->flag = CMC_FLAG_EMPTY; return ((void *)0); } if (index >= _list_->count) { _list_->flag = CMC_FLAG_RANGE; return ((void *)0); } struct linkedlist_node *scan = ll_get_node(_list_, index); if (scan == ((void *)0)) return ((void *)0); if ((_list_)->callbacks && (_list_)->callbacks->read) (_list_)->callbacks->read();; return &(scan->value); } size_t ll_back(struct linkedlist * _list_) { if (ll_empty(_list_)) { _list_->flag = CMC_FLAG_EMPTY; return (size_t){ 0 }; } _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->read) (_list_)->callbacks->read();; return _list_->tail->value; } _Bool ll_contains(struct linkedlist * _list_, size_t value) { _list_->flag = CMC_FLAG_OK; _Bool result = 0; struct linkedlist_node *scan = _list_->head; while (scan != ((void *)0)) { if (_list_->f_val->cmp(scan->value, value) == 0) { result = 1; break; } scan = scan->next; } if ((_list_)->callbacks && (_list_)->callbacks->read) (_list_)->callbacks->read();; return result; } _Bool ll_empty(struct linkedlist * _list_) { return _list_->count == 0; } size_t ll_count(struct linkedlist * _list_) { return _list_->count; } int ll_flag(struct linkedlist * _list_) { return _list_->flag; } struct linkedlist *ll_copy_of(struct linkedlist * _list_) { struct linkedlist *result = ll_new_custom(_list_->f_val, _list_->alloc, ((void *)0)); if (!result) return ((void *)0); (result)->callbacks = _list_->callbacks; struct linkedlist_node *scan = _list_->head; while (scan != ((void *)0)) { struct linkedlist_node * new_node; if (_list_->f_val->cpy) new_node = ll_new_node(_list_, _list_->f_val->cpy(scan->value)); else new_node = ll_new_node(_list_, scan->value); if (!result->head) { result->head = new_node; result->tail = new_node; } else { new_node->prev = result->tail; result->tail->next = new_node; result->tail = new_node; } scan = scan->next; } result->count = _list_->count; _list_->flag = CMC_FLAG_OK; return result; } _Bool ll_equals(struct linkedlist * _list1_, struct linkedlist * _list2_) { _list1_->flag = CMC_FLAG_OK; _list2_->flag = CMC_FLAG_OK; if (_list1_->count != _list2_->count) return 0; struct linkedlist_node *scan1 = _list1_->head; struct linkedlist_node *scan2 = _list2_->head; while (scan1 != ((void *)0) && scan2 != ((void *)0)) { if (_list1_->f_val->cmp(scan1->value, scan2->value) != 0) return 0; scan1 = scan1->next; scan2 = scan2->next; } return 1; } struct linkedlist_iter ll_iter_start(struct linkedlist * target) { struct linkedlist_iter iter; iter.target = target; iter.cursor = target->head; iter.index = 0; iter.start = 1; iter.end = ll_empty(target); return iter; } struct linkedlist_iter ll_iter_end(struct linkedlist * target) { struct linkedlist_iter iter; iter.target = target; iter.cursor = target->tail; iter.index = 0; iter.start = ll_empty(target); iter.end = 1; if (!ll_empty(target)) iter.index = target->count - 1; return iter; } _Bool ll_iter_at_start(struct linkedlist_iter * iter) { return ll_empty(iter->target) || iter->start; } _Bool ll_iter_at_end(struct linkedlist_iter * iter) { return ll_empty(iter->target) || iter->end; } _Bool ll_iter_to_start(struct linkedlist_iter * iter) { if (!ll_empty(iter->target)) { iter->cursor = iter->target->head; iter->index = 0; iter->start = 1; iter->end = ll_empty(iter->target); return 1; } return 0; } _Bool ll_iter_to_end(struct linkedlist_iter * iter) { if (!ll_empty(iter->target)) { iter->cursor = iter->target->tail; iter->index = iter->target->count - 1; iter->start = ll_empty(iter->target); iter->end = 1; return 1; } return 0; } _Bool ll_iter_next(struct linkedlist_iter * iter) { if (iter->end) return 0; if (iter->cursor->next == ((void *)0)) { iter->end = 1; return 0; } iter->start = ll_empty(iter->target); iter->cursor = iter->cursor->next; iter->index++; return 1; } _Bool ll_iter_prev(struct linkedlist_iter * iter) { if (iter->start) return 0; if (iter->cursor->prev == ((void *)0)) { iter->start = 1; return 0; } iter->end = ll_empty(iter->target); iter->cursor = iter->cursor->prev; iter->index--; return 1; } _Bool ll_iter_advance(struct linkedlist_iter * iter, size_t steps) { if (iter->end) return 0; if (iter->cursor->next == ((void *)0)) { iter->end = 1; return 0; } if (steps == 0 || iter->index + steps >= iter->target->count) return 0; iter->start = ll_empty(iter->target); iter->index += steps; for (size_t i = 0; i < steps; i++) iter->cursor = iter->cursor->next; return 1; } _Bool ll_iter_rewind(struct linkedlist_iter * iter, size_t steps) { if (iter->start) return 0; if (iter->cursor->prev == ((void *)0)) { iter->start = 1; return 0; } if (steps == 0 || iter->index < steps) return 0; iter->end = ll_empty(iter->target); iter->index -= steps; for (size_t i = 0; i < steps; i++) iter->cursor = iter->cursor->prev; return 1; } _Bool ll_iter_go_to(struct linkedlist_iter * iter, size_t index) { if (index >= iter->target->count) return 0; if (iter->index > index) return ll_iter_rewind(iter, iter->index - index); else if (iter->index < index) return ll_iter_advance(iter, index - iter->index); return 1; } size_t ll_iter_value(struct linkedlist_iter * iter) { if (ll_empty(iter->target)) return (size_t){ 0 }; return iter->cursor->value; } size_t *ll_iter_rvalue(struct linkedlist_iter * iter) { if (ll_empty(iter->target)) return ((void *)0); return &(iter->cursor->value); } size_t ll_iter_index(struct linkedlist_iter * iter) { return iter->index; } struct linkedlist_node * ll_iter_node(struct linkedlist_iter * iter) { return iter->cursor; } struct linkedlist_node * ll_new_node(struct linkedlist * _list_, size_t value) { struct linkedlist_node *_node_ = _list_->alloc->malloc(sizeof(struct linkedlist_node)); if (!_node_) { _list_->flag = CMC_FLAG_ALLOC; return ((void *)0); } _node_->value = value; _node_->next = ((void *)0); _node_->prev = ((void *)0); return _node_; } void ll_free_node(struct linkedlist * _list_, struct linkedlist_node * _node_) { _list_->alloc->free(_node_); } struct linkedlist_node * ll_head(struct linkedlist * _list_) { return _list_->head; } struct linkedlist_node * ll_get_node(struct linkedlist * _list_, size_t index) { if (ll_empty(_list_)) { _list_->flag = CMC_FLAG_EMPTY; return ((void *)0); } if (index >= _list_->count) { _list_->flag = CMC_FLAG_RANGE; return ((void *)0); } struct linkedlist_node *_node_ = ((void *)0); if (index <= _list_->count / 2) { _node_ = _list_->head; for (size_t i = 0; i < index; i++) { _node_ = _node_->next; } } else { _node_ = _list_->tail; for (size_t i = _list_->count - 1; i > index; i--) { _node_ = _node_->prev; } } _list_->flag = CMC_FLAG_OK; return _node_; } struct linkedlist_node * ll_tail(struct linkedlist * _list_) { return _list_->tail; } _Bool ll_add_next(struct linkedlist * _owner_, struct linkedlist_node * _node_, size_t value) { struct linkedlist_node *new_node = ll_new_node(_owner_, value); if (!new_node) return 0; new_node->next = _node_->next; if (_node_->next != ((void *)0)) _node_->next->prev = new_node; else _owner_->tail = new_node; new_node->prev = _node_; _node_->next = new_node; _owner_->count++; _owner_->flag = CMC_FLAG_OK; return 1; } _Bool ll_add_prev(struct linkedlist * _owner_, struct linkedlist_node * _node_, size_t value) { struct linkedlist_node *new_node = ll_new_node(_owner_, value); if (!new_node) return 0; new_node->prev = _node_->prev; if (_node_->prev != ((void *)0)) _node_->prev->next = new_node; else _owner_->head = new_node; new_node->next = _node_; _node_->prev = new_node; _owner_->count++; _owner_->flag = CMC_FLAG_OK; return 1; } _Bool ll_del_next(struct linkedlist * _owner_, struct linkedlist_node * _node_) { if (_node_->next == ((void *)0)) { _owner_->flag = CMC_FLAG_INVALID; return 0; } struct linkedlist_node *tmp = _node_->next; _node_->next = _node_->next->next; if (tmp->next != ((void *)0)) tmp->next->prev = _node_; else _owner_->tail = _node_; _owner_->alloc->free(tmp); _owner_->count--; _owner_->flag = CMC_FLAG_OK; return 1; } _Bool ll_del_curr(struct linkedlist * _owner_, struct linkedlist_node * _node_) { if (_node_->prev != ((void *)0)) _node_->prev->next = _node_->next; else _owner_->head = _node_->next; if (_node_->next != ((void *)0)) _node_->next->prev = _node_->prev; else _owner_->tail = _node_->prev; _owner_->alloc->free(_node_); _owner_->count--; _owner_->flag = CMC_FLAG_OK; return 1; } _Bool ll_del_prev(struct linkedlist * _owner_, struct linkedlist_node * _node_) { if (_node_->prev == ((void *)0)) { _owner_->flag = CMC_FLAG_INVALID; return 0; } struct linkedlist_node *tmp = _node_->prev; _node_->prev = _node_->prev->prev; if (tmp->prev != ((void *)0)) tmp->prev->next = _node_; else _owner_->head = _node_; _owner_->alloc->free(tmp); _owner_->count--; _owner_->flag = CMC_FLAG_OK; return 1; } struct linkedlist_node * ll_next_node(struct linkedlist_node * _node_) { return _node_->next; } struct linkedlist_node * ll_prev_node(struct linkedlist_node * _node_) { return _node_->prev; } _Bool ll_to_string(struct linkedlist * _list_, FILE * fptr) { struct linkedlist *l_ = _list_; return 0 <= fprintf(fptr, "struct %s<%s> " "at %p { " "count:%" "I64u" ", " "head:%p, " "tail:%p, " "flag:%d, " "f_val:%p, " "alloc:%p, " "callbacks:%p }", "linkedlist", "size_t", l_, l_->count, l_->head, l_->tail, l_->flag, l_->f_val, l_->alloc, (l_)->callbacks); } _Bool ll_print(struct linkedlist * _list_, FILE * fptr, const char *start, const char *separator, const char *end) { fprintf(fptr, "%s", start); struct linkedlist_node *scan = _list_->head; while (scan != ((void *)0)) { if (!_list_->f_val->str(fptr, scan->value)) return 0; scan = scan->next; if (scan) fprintf(fptr, "%s", separator); } fprintf(fptr, "%s", end); return 1; } - - \ No newline at end of file +struct linkedlist *ll_new(struct linkedlist_fval *f_val) +{ + return ll_new_custom(f_val, ((void *)0), ((void *)0)); +} +struct linkedlist *ll_new_custom(struct linkedlist_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks) +{ + ; + if (!f_val) + return ((void *)0); + if (!alloc) + alloc = &cmc_alloc_node_default; + struct linkedlist *_list_ = alloc->malloc(sizeof(struct linkedlist)); + if (!_list_) + return ((void *)0); + _list_->count = 0; + _list_->head = ((void *)0); + _list_->tail = ((void *)0); + _list_->flag = CMC_FLAG_OK; + _list_->f_val = f_val; + _list_->alloc = alloc; + (_list_)->callbacks = callbacks; + return _list_; +} +void ll_clear(struct linkedlist *_list_) +{ + struct linkedlist_node *scan = _list_->head; + while (_list_->head != ((void *)0)) + { + _list_->head = _list_->head->next; + if (_list_->f_val->free) + { + _list_->f_val->free(scan->value); + } + _list_->alloc->free(scan); + scan = _list_->head; + } + _list_->count = 0; + _list_->head = ((void *)0); + _list_->tail = ((void *)0); + _list_->flag = CMC_FLAG_OK; +} +void ll_free(struct linkedlist *_list_) +{ + ll_clear(_list_); + _list_->alloc->free(_list_); +} +void ll_customize(struct linkedlist *_list_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks) +{ + ; + if (!alloc) + _list_->alloc = &cmc_alloc_node_default; + else + _list_->alloc = alloc; + (_list_)->callbacks = callbacks; + _list_->flag = CMC_FLAG_OK; +} +_Bool ll_push_front(struct linkedlist *_list_, size_t value) +{ + struct linkedlist_node *_node_ = ll_new_node(_list_, value); + if (!_node_) + return 0; + if (ll_empty(_list_)) + { + _list_->head = _node_; + _list_->tail = _node_; + } + else + { + _node_->next = _list_->head; + _list_->head->prev = _node_; + _list_->head = _node_; + } + _list_->count++; + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->create) + (_list_)->callbacks->create(); + ; + return 1; +} +_Bool ll_push_at(struct linkedlist *_list_, size_t value, size_t index) +{ + if (index > _list_->count) + { + _list_->flag = CMC_FLAG_RANGE; + return 0; + } + if (index == 0) + { + return ll_push_front(_list_, value); + } + else if (index == _list_->count) + { + return ll_push_back(_list_, value); + } + struct linkedlist_node *_node_ = ll_new_node(_list_, value); + if (!_node_) + return 0; + struct linkedlist_node *scan = ll_get_node(_list_, index - 1); + _node_->next = scan->next; + _node_->prev = scan; + _node_->next->prev = _node_; + _node_->prev->next = _node_; + _list_->count++; + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->create) + (_list_)->callbacks->create(); + ; + return 1; +} +_Bool ll_push_back(struct linkedlist *_list_, size_t value) +{ + struct linkedlist_node *_node_ = ll_new_node(_list_, value); + if (!_node_) + return 0; + if (ll_empty(_list_)) + { + _list_->head = _node_; + _list_->tail = _node_; + } + else + { + _node_->prev = _list_->tail; + _list_->tail->next = _node_; + _list_->tail = _node_; + } + _list_->count++; + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->create) + (_list_)->callbacks->create(); + ; + return 1; +} +_Bool ll_pop_front(struct linkedlist *_list_) +{ + if (ll_empty(_list_)) + { + _list_->flag = CMC_FLAG_EMPTY; + return 0; + } + struct linkedlist_node *_node_ = _list_->head; + _list_->head = _list_->head->next; + _list_->alloc->free(_node_); + if (_list_->head == ((void *)0)) + _list_->tail = ((void *)0); + else + _list_->head->prev = ((void *)0); + _list_->count--; + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->delete) + (_list_)->callbacks->delete (); + ; + return 1; +} +_Bool ll_pop_at(struct linkedlist *_list_, size_t index) +{ + if (ll_empty(_list_)) + { + _list_->flag = CMC_FLAG_EMPTY; + return 0; + } + if (index >= _list_->count) + { + _list_->flag = CMC_FLAG_RANGE; + return 0; + } + if (index == 0) + { + return ll_pop_front(_list_); + } + else if (index == _list_->count - 1) + { + return ll_pop_back(_list_); + } + struct linkedlist_node *_node_ = ll_get_node(_list_, index); + if (!_node_) + return 0; + _node_->next->prev = _node_->prev; + _node_->prev->next = _node_->next; + _list_->alloc->free(_node_); + _list_->count--; + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->delete) + (_list_)->callbacks->delete (); + ; + return 1; +} +_Bool ll_pop_back(struct linkedlist *_list_) +{ + if (ll_empty(_list_)) + { + _list_->flag = CMC_FLAG_EMPTY; + return 0; + } + struct linkedlist_node *_node_ = _list_->tail; + _list_->tail = _list_->tail->prev; + _list_->alloc->free(_node_); + if (_list_->tail == ((void *)0)) + _list_->head = ((void *)0); + else + _list_->tail->next = ((void *)0); + _list_->count--; + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->delete) + (_list_)->callbacks->delete (); + ; + return 1; +} +size_t ll_front(struct linkedlist *_list_) +{ + if (ll_empty(_list_)) + { + _list_->flag = CMC_FLAG_EMPTY; + return (size_t){ 0 }; + } + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->read) + (_list_)->callbacks->read(); + ; + return _list_->head->value; +} +size_t ll_get(struct linkedlist *_list_, size_t index) +{ + if (ll_empty(_list_)) + { + _list_->flag = CMC_FLAG_EMPTY; + return (size_t){ 0 }; + } + if (index >= _list_->count) + { + _list_->flag = CMC_FLAG_RANGE; + return (size_t){ 0 }; + } + struct linkedlist_node *scan = ll_get_node(_list_, index); + if (scan == ((void *)0)) + return (size_t){ 0 }; + if ((_list_)->callbacks && (_list_)->callbacks->read) + (_list_)->callbacks->read(); + ; + return scan->value; +} +size_t *ll_get_ref(struct linkedlist *_list_, size_t index) +{ + if (ll_empty(_list_)) + { + _list_->flag = CMC_FLAG_EMPTY; + return ((void *)0); + } + if (index >= _list_->count) + { + _list_->flag = CMC_FLAG_RANGE; + return ((void *)0); + } + struct linkedlist_node *scan = ll_get_node(_list_, index); + if (scan == ((void *)0)) + return ((void *)0); + if ((_list_)->callbacks && (_list_)->callbacks->read) + (_list_)->callbacks->read(); + ; + return &(scan->value); +} +size_t ll_back(struct linkedlist *_list_) +{ + if (ll_empty(_list_)) + { + _list_->flag = CMC_FLAG_EMPTY; + return (size_t){ 0 }; + } + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->read) + (_list_)->callbacks->read(); + ; + return _list_->tail->value; +} +_Bool ll_contains(struct linkedlist *_list_, size_t value) +{ + _list_->flag = CMC_FLAG_OK; + _Bool result = 0; + struct linkedlist_node *scan = _list_->head; + while (scan != ((void *)0)) + { + if (_list_->f_val->cmp(scan->value, value) == 0) + { + result = 1; + break; + } + scan = scan->next; + } + if ((_list_)->callbacks && (_list_)->callbacks->read) + (_list_)->callbacks->read(); + ; + return result; +} +_Bool ll_empty(struct linkedlist *_list_) +{ + return _list_->count == 0; +} +size_t ll_count(struct linkedlist *_list_) +{ + return _list_->count; +} +int ll_flag(struct linkedlist *_list_) +{ + return _list_->flag; +} +struct linkedlist *ll_copy_of(struct linkedlist *_list_) +{ + struct linkedlist *result = ll_new_custom(_list_->f_val, _list_->alloc, ((void *)0)); + if (!result) + return ((void *)0); + (result)->callbacks = _list_->callbacks; + struct linkedlist_node *scan = _list_->head; + while (scan != ((void *)0)) + { + struct linkedlist_node *new_node; + if (_list_->f_val->cpy) + new_node = ll_new_node(_list_, _list_->f_val->cpy(scan->value)); + else + new_node = ll_new_node(_list_, scan->value); + if (!result->head) + { + result->head = new_node; + result->tail = new_node; + } + else + { + new_node->prev = result->tail; + result->tail->next = new_node; + result->tail = new_node; + } + scan = scan->next; + } + result->count = _list_->count; + _list_->flag = CMC_FLAG_OK; + return result; +} +_Bool ll_equals(struct linkedlist *_list1_, struct linkedlist *_list2_) +{ + _list1_->flag = CMC_FLAG_OK; + _list2_->flag = CMC_FLAG_OK; + if (_list1_->count != _list2_->count) + return 0; + struct linkedlist_node *scan1 = _list1_->head; + struct linkedlist_node *scan2 = _list2_->head; + while (scan1 != ((void *)0) && scan2 != ((void *)0)) + { + if (_list1_->f_val->cmp(scan1->value, scan2->value) != 0) + return 0; + scan1 = scan1->next; + scan2 = scan2->next; + } + return 1; +} +struct linkedlist_iter ll_iter_start(struct linkedlist *target) +{ + struct linkedlist_iter iter; + iter.target = target; + iter.cursor = target->head; + iter.index = 0; + iter.start = 1; + iter.end = ll_empty(target); + return iter; +} +struct linkedlist_iter ll_iter_end(struct linkedlist *target) +{ + struct linkedlist_iter iter; + iter.target = target; + iter.cursor = target->tail; + iter.index = 0; + iter.start = ll_empty(target); + iter.end = 1; + if (!ll_empty(target)) + iter.index = target->count - 1; + return iter; +} +_Bool ll_iter_at_start(struct linkedlist_iter *iter) +{ + return ll_empty(iter->target) || iter->start; +} +_Bool ll_iter_at_end(struct linkedlist_iter *iter) +{ + return ll_empty(iter->target) || iter->end; +} +_Bool ll_iter_to_start(struct linkedlist_iter *iter) +{ + if (!ll_empty(iter->target)) + { + iter->cursor = iter->target->head; + iter->index = 0; + iter->start = 1; + iter->end = ll_empty(iter->target); + return 1; + } + return 0; +} +_Bool ll_iter_to_end(struct linkedlist_iter *iter) +{ + if (!ll_empty(iter->target)) + { + iter->cursor = iter->target->tail; + iter->index = iter->target->count - 1; + iter->start = ll_empty(iter->target); + iter->end = 1; + return 1; + } + return 0; +} +_Bool ll_iter_next(struct linkedlist_iter *iter) +{ + if (iter->end) + return 0; + if (iter->cursor->next == ((void *)0)) + { + iter->end = 1; + return 0; + } + iter->start = ll_empty(iter->target); + iter->cursor = iter->cursor->next; + iter->index++; + return 1; +} +_Bool ll_iter_prev(struct linkedlist_iter *iter) +{ + if (iter->start) + return 0; + if (iter->cursor->prev == ((void *)0)) + { + iter->start = 1; + return 0; + } + iter->end = ll_empty(iter->target); + iter->cursor = iter->cursor->prev; + iter->index--; + return 1; +} +_Bool ll_iter_advance(struct linkedlist_iter *iter, size_t steps) +{ + if (iter->end) + return 0; + if (iter->cursor->next == ((void *)0)) + { + iter->end = 1; + return 0; + } + if (steps == 0 || iter->index + steps >= iter->target->count) + return 0; + iter->start = ll_empty(iter->target); + iter->index += steps; + for (size_t i = 0; i < steps; i++) + iter->cursor = iter->cursor->next; + return 1; +} +_Bool ll_iter_rewind(struct linkedlist_iter *iter, size_t steps) +{ + if (iter->start) + return 0; + if (iter->cursor->prev == ((void *)0)) + { + iter->start = 1; + return 0; + } + if (steps == 0 || iter->index < steps) + return 0; + iter->end = ll_empty(iter->target); + iter->index -= steps; + for (size_t i = 0; i < steps; i++) + iter->cursor = iter->cursor->prev; + return 1; +} +_Bool ll_iter_go_to(struct linkedlist_iter *iter, size_t index) +{ + if (index >= iter->target->count) + return 0; + if (iter->index > index) + return ll_iter_rewind(iter, iter->index - index); + else if (iter->index < index) + return ll_iter_advance(iter, index - iter->index); + return 1; +} +size_t ll_iter_value(struct linkedlist_iter *iter) +{ + if (ll_empty(iter->target)) + return (size_t){ 0 }; + return iter->cursor->value; +} +size_t *ll_iter_rvalue(struct linkedlist_iter *iter) +{ + if (ll_empty(iter->target)) + return ((void *)0); + return &(iter->cursor->value); +} +size_t ll_iter_index(struct linkedlist_iter *iter) +{ + return iter->index; +} +struct linkedlist_node *ll_iter_node(struct linkedlist_iter *iter) +{ + return iter->cursor; +} +struct linkedlist_node *ll_new_node(struct linkedlist *_list_, size_t value) +{ + struct linkedlist_node *_node_ = _list_->alloc->malloc(sizeof(struct linkedlist_node)); + if (!_node_) + { + _list_->flag = CMC_FLAG_ALLOC; + return ((void *)0); + } + _node_->value = value; + _node_->next = ((void *)0); + _node_->prev = ((void *)0); + return _node_; +} +void ll_free_node(struct linkedlist *_list_, struct linkedlist_node *_node_) +{ + _list_->alloc->free(_node_); +} +struct linkedlist_node *ll_head(struct linkedlist *_list_) +{ + return _list_->head; +} +struct linkedlist_node *ll_get_node(struct linkedlist *_list_, size_t index) +{ + if (ll_empty(_list_)) + { + _list_->flag = CMC_FLAG_EMPTY; + return ((void *)0); + } + if (index >= _list_->count) + { + _list_->flag = CMC_FLAG_RANGE; + return ((void *)0); + } + struct linkedlist_node *_node_ = ((void *)0); + if (index <= _list_->count / 2) + { + _node_ = _list_->head; + for (size_t i = 0; i < index; i++) + { + _node_ = _node_->next; + } + } + else + { + _node_ = _list_->tail; + for (size_t i = _list_->count - 1; i > index; i--) + { + _node_ = _node_->prev; + } + } + _list_->flag = CMC_FLAG_OK; + return _node_; +} +struct linkedlist_node *ll_tail(struct linkedlist *_list_) +{ + return _list_->tail; +} +_Bool ll_add_next(struct linkedlist *_owner_, struct linkedlist_node *_node_, size_t value) +{ + struct linkedlist_node *new_node = ll_new_node(_owner_, value); + if (!new_node) + return 0; + new_node->next = _node_->next; + if (_node_->next != ((void *)0)) + _node_->next->prev = new_node; + else + _owner_->tail = new_node; + new_node->prev = _node_; + _node_->next = new_node; + _owner_->count++; + _owner_->flag = CMC_FLAG_OK; + return 1; +} +_Bool ll_add_prev(struct linkedlist *_owner_, struct linkedlist_node *_node_, size_t value) +{ + struct linkedlist_node *new_node = ll_new_node(_owner_, value); + if (!new_node) + return 0; + new_node->prev = _node_->prev; + if (_node_->prev != ((void *)0)) + _node_->prev->next = new_node; + else + _owner_->head = new_node; + new_node->next = _node_; + _node_->prev = new_node; + _owner_->count++; + _owner_->flag = CMC_FLAG_OK; + return 1; +} +_Bool ll_del_next(struct linkedlist *_owner_, struct linkedlist_node *_node_) +{ + if (_node_->next == ((void *)0)) + { + _owner_->flag = CMC_FLAG_INVALID; + return 0; + } + struct linkedlist_node *tmp = _node_->next; + _node_->next = _node_->next->next; + if (tmp->next != ((void *)0)) + tmp->next->prev = _node_; + else + _owner_->tail = _node_; + _owner_->alloc->free(tmp); + _owner_->count--; + _owner_->flag = CMC_FLAG_OK; + return 1; +} +_Bool ll_del_curr(struct linkedlist *_owner_, struct linkedlist_node *_node_) +{ + if (_node_->prev != ((void *)0)) + _node_->prev->next = _node_->next; + else + _owner_->head = _node_->next; + if (_node_->next != ((void *)0)) + _node_->next->prev = _node_->prev; + else + _owner_->tail = _node_->prev; + _owner_->alloc->free(_node_); + _owner_->count--; + _owner_->flag = CMC_FLAG_OK; + return 1; +} +_Bool ll_del_prev(struct linkedlist *_owner_, struct linkedlist_node *_node_) +{ + if (_node_->prev == ((void *)0)) + { + _owner_->flag = CMC_FLAG_INVALID; + return 0; + } + struct linkedlist_node *tmp = _node_->prev; + _node_->prev = _node_->prev->prev; + if (tmp->prev != ((void *)0)) + tmp->prev->next = _node_; + else + _owner_->head = _node_; + _owner_->alloc->free(tmp); + _owner_->count--; + _owner_->flag = CMC_FLAG_OK; + return 1; +} +struct linkedlist_node *ll_next_node(struct linkedlist_node *_node_) +{ + return _node_->next; +} +struct linkedlist_node *ll_prev_node(struct linkedlist_node *_node_) +{ + return _node_->prev; +} +_Bool ll_to_string(struct linkedlist *_list_, FILE *fptr) +{ + struct linkedlist *l_ = _list_; + return 0 <= fprintf(fptr, + "struct %s<%s> " + "at %p { " + "count:%" + "I64u" + ", " + "head:%p, " + "tail:%p, " + "flag:%d, " + "f_val:%p, " + "alloc:%p, " + "callbacks:%p }", + "linkedlist", "size_t", l_, l_->count, l_->head, l_->tail, l_->flag, l_->f_val, l_->alloc, + (l_)->callbacks); +} +_Bool ll_print(struct linkedlist *_list_, FILE *fptr, const char *start, const char *separator, const char *end) +{ + fprintf(fptr, "%s", start); + struct linkedlist_node *scan = _list_->head; + while (scan != ((void *)0)) + { + if (!_list_->f_val->str(fptr, scan->value)) + return 0; + scan = scan->next; + if (scan) + fprintf(fptr, "%s", separator); + } + fprintf(fptr, "%s", end); + return 1; +} diff --git a/tests/src/tst_cmc_list.c b/tests/src/tst_cmc_list.c index a0061d8..6ada698 100644 --- a/tests/src/tst_cmc_list.c +++ b/tests/src/tst_cmc_list.c @@ -1,7 +1,643 @@ - #include "tst_cmc_list.h" +#include "tst_cmc_list.h" - - struct list *l_new(size_t capacity, struct list_fval * f_val) { return l_new_custom(capacity, f_val, ((void *)0), ((void *)0)); } struct list *l_new_custom(size_t capacity, struct list_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (capacity < 1) return ((void *)0); if (!f_val) return ((void *)0); if (!alloc) alloc = &cmc_alloc_node_default; struct list *_list_ = alloc->malloc(sizeof(struct list)); if (!_list_) return ((void *)0); _list_->buffer = alloc->calloc(capacity, sizeof(size_t)); if (!_list_->buffer) { alloc->free(_list_); return ((void *)0); } _list_->capacity = capacity; _list_->count = 0; _list_->flag = CMC_FLAG_OK; _list_->f_val = f_val; _list_->alloc = alloc; (_list_)->callbacks = callbacks; return _list_; } void l_clear(struct list * _list_) { if (_list_->f_val->free) { for (size_t i = 0; i < _list_->count; i++) _list_->f_val->free(_list_->buffer[i]); } memset(_list_->buffer, 0, sizeof(size_t) * _list_->capacity); _list_->count = 0; _list_->flag = CMC_FLAG_OK; } void l_free(struct list * _list_) { if (_list_->f_val->free) { for (size_t i = 0; i < _list_->count; i++) _list_->f_val->free(_list_->buffer[i]); } _list_->alloc->free(_list_->buffer); _list_->alloc->free(_list_); } void l_customize(struct list * _list_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (!alloc) _list_->alloc = &cmc_alloc_node_default; else _list_->alloc = alloc; (_list_)->callbacks = callbacks; _list_->flag = CMC_FLAG_OK; } _Bool l_push_front(struct list * _list_, size_t value) { if (l_full(_list_)) { if (!l_resize(_list_, _list_->count * 2)) return 0; } if (!l_empty(_list_)) { memmove(_list_->buffer + 1, _list_->buffer, _list_->count * sizeof(size_t)); } _list_->buffer[0] = value; _list_->count++; _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->create) (_list_)->callbacks->create();; return 1; } _Bool l_push_at(struct list * _list_, size_t value, size_t index) { if (index > _list_->count) { _list_->flag = CMC_FLAG_RANGE; return 0; } if (l_full(_list_)) { if (!l_resize(_list_, _list_->count * 2)) return 0; } memmove(_list_->buffer + index + 1, _list_->buffer + index, (_list_->count - index) * sizeof(size_t)); _list_->buffer[index] = value; _list_->count++; _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->create) (_list_)->callbacks->create();; return 1; } _Bool l_push_back(struct list * _list_, size_t value) { if (l_full(_list_)) { if (!l_resize(_list_, _list_->count * 2)) return 0; } _list_->buffer[_list_->count++] = value; _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->create) (_list_)->callbacks->create();; return 1; } _Bool l_pop_front(struct list * _list_) { if (l_empty(_list_)) { _list_->flag = CMC_FLAG_EMPTY; return 0; } memmove(_list_->buffer, _list_->buffer + 1, (_list_->count - 1) * sizeof(size_t)); _list_->buffer[--_list_->count] = (size_t){ 0 }; _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->delete) (_list_)->callbacks->delete();; return 1; } _Bool l_pop_at(struct list * _list_, size_t index) { if (l_empty(_list_)) { _list_->flag = CMC_FLAG_EMPTY; return 0; } if (index >= _list_->count) { _list_->flag = CMC_FLAG_RANGE; return 0; } memmove(_list_->buffer + index, _list_->buffer + index + 1, (_list_->count - index - 1) * sizeof(size_t)); _list_->buffer[--_list_->count] = (size_t){ 0 }; _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->delete) (_list_)->callbacks->delete();; return 1; } _Bool l_pop_back(struct list * _list_) { if (l_empty(_list_)) return 0; _list_->buffer[--_list_->count] = (size_t){ 0 }; _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->delete) (_list_)->callbacks->delete();; return 1; } size_t l_front(struct list * _list_) { if (l_empty(_list_)) { _list_->flag = CMC_FLAG_EMPTY; return (size_t){ 0 }; } _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->read) (_list_)->callbacks->read();; return _list_->buffer[0]; } size_t l_get(struct list * _list_, size_t index) { if (l_empty(_list_)) { _list_->flag = CMC_FLAG_EMPTY; return (size_t){ 0 }; } if (index >= _list_->count) { _list_->flag = CMC_FLAG_RANGE; return (size_t){ 0 }; } _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->read) (_list_)->callbacks->read();; return _list_->buffer[index]; } size_t *l_get_ref(struct list * _list_, size_t index) { if (l_empty(_list_)) { _list_->flag = CMC_FLAG_EMPTY; return ((void *)0); } if (index >= _list_->count) { _list_->flag = CMC_FLAG_RANGE; return ((void *)0); } _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->read) (_list_)->callbacks->read();; return &(_list_->buffer[index]); } size_t l_back(struct list * _list_) { if (l_empty(_list_)) { _list_->flag = CMC_FLAG_EMPTY; return (size_t){ 0 }; } _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->read) (_list_)->callbacks->read();; return _list_->buffer[_list_->count - 1]; } size_t l_index_of(struct list * _list_, size_t value, _Bool from_start) { _list_->flag = CMC_FLAG_OK; size_t result = _list_->count; if (from_start) { for (size_t i = 0; i < _list_->count; i++) { if (_list_->f_val->cmp(_list_->buffer[i], value) == 0) { result = i; break; } } } else { for (size_t i = _list_->count; i > 0; i--) { if (_list_->f_val->cmp(_list_->buffer[i - 1], value) == 0) { result = i - 1; break; } } } if ((_list_)->callbacks && (_list_)->callbacks->read) (_list_)->callbacks->read();; return result; } _Bool l_contains(struct list * _list_, size_t value) { _list_->flag = CMC_FLAG_OK; _Bool result = 0; for (size_t i = 0; i < _list_->count; i++) { if (_list_->f_val->cmp(_list_->buffer[i], value) == 0) { result = 1; break; } } if ((_list_)->callbacks && (_list_)->callbacks->read) (_list_)->callbacks->read();; return result; } _Bool l_empty(struct list * _list_) { return _list_->count == 0; } _Bool l_full(struct list * _list_) { return _list_->count >= _list_->capacity; } size_t l_count(struct list * _list_) { return _list_->count; } _Bool l_fits(struct list * _list_, size_t size) { return _list_->count + size <= _list_->capacity; } size_t l_capacity(struct list * _list_) { return _list_->capacity; } int l_flag(struct list * _list_) { return _list_->flag; } _Bool l_resize(struct list * _list_, size_t capacity) { _list_->flag = CMC_FLAG_OK; if (_list_->capacity == capacity) return 1; if (capacity < _list_->count) { _list_->flag = CMC_FLAG_INVALID; return 0; } size_t *new_buffer = _list_->alloc->realloc(_list_->buffer, sizeof(size_t) * capacity); if (!new_buffer) { _list_->flag = CMC_FLAG_ALLOC; return 0; } _list_->buffer = new_buffer; _list_->capacity = capacity; if ((_list_)->callbacks && (_list_)->callbacks->resize) (_list_)->callbacks->resize();; return 1; } struct list *l_copy_of(struct list * _list_) { struct list *result = l_new_custom(_list_->capacity, _list_->f_val, _list_->alloc, ((void *)0)); if (!result) { _list_->flag = CMC_FLAG_ALLOC; return ((void *)0); } (result)->callbacks = _list_->callbacks; if (_list_->f_val->cpy) { for (size_t i = 0; i < _list_->count; i++) result->buffer[i] = _list_->f_val->cpy(_list_->buffer[i]); } else memcpy(result->buffer, _list_->buffer, sizeof(size_t) * _list_->count); result->count = _list_->count; _list_->flag = CMC_FLAG_OK; return result; } _Bool l_equals(struct list * _list1_, struct list * _list2_) { _list1_->flag = CMC_FLAG_OK; _list2_->flag = CMC_FLAG_OK; if (_list1_->count != _list2_->count) return 0; for (size_t i = 0; i < _list1_->count; i++) { if (0 != _list1_->f_val->cmp(_list1_->buffer[i], _list2_->buffer[i])) return 0; } return 1; } struct list_iter l_iter_start(struct list * target) { struct list_iter iter; iter.target = target; iter.cursor = 0; iter.start = 1; iter.end = l_empty(target); return iter; } struct list_iter l_iter_end(struct list * target) { struct list_iter iter; iter.target = target; iter.cursor = 0; iter.start = l_empty(target); iter.end = 1; if (!l_empty(target)) iter.cursor = target->count - 1; return iter; } _Bool l_iter_at_start(struct list_iter * iter) { return l_empty(iter->target) || iter->start; } _Bool l_iter_at_end(struct list_iter * iter) { return l_empty(iter->target) || iter->end; } _Bool l_iter_to_start(struct list_iter * iter) { if (!l_empty(iter->target)) { iter->cursor = 0; iter->start = 1; iter->end = l_empty(iter->target); return 1; } return 0; } _Bool l_iter_to_end(struct list_iter * iter) { if (!l_empty(iter->target)) { iter->start = l_empty(iter->target); iter->cursor = iter->target->count - 1; iter->end = 1; return 1; } return 0; } _Bool l_iter_next(struct list_iter * iter) { if (iter->end) return 0; if (iter->cursor + 1 == iter->target->count) { iter->end = 1; return 0; } iter->start = l_empty(iter->target); iter->cursor++; return 1; } _Bool l_iter_prev(struct list_iter * iter) { if (iter->start) return 0; if (iter->cursor == 0) { iter->start = 1; return 0; } iter->end = l_empty(iter->target); iter->cursor--; return 1; } _Bool l_iter_advance(struct list_iter * iter, size_t steps) { if (iter->end) return 0; if (iter->cursor + 1 == iter->target->count) { iter->end = 1; return 0; } if (steps == 0 || iter->cursor + steps >= iter->target->count) return 0; iter->start = l_empty(iter->target); iter->cursor += steps; return 1; } _Bool l_iter_rewind(struct list_iter * iter, size_t steps) { if (iter->start) return 0; if (iter->cursor == 0) { iter->start = 1; return 0; } if (steps == 0 || iter->cursor < steps) return 0; iter->end = l_empty(iter->target); iter->cursor -= steps; return 1; } _Bool l_iter_go_to(struct list_iter * iter, size_t index) { if (index >= iter->target->count) return 0; if (iter->cursor > index) return l_iter_rewind(iter, iter->cursor - index); else if (iter->cursor < index) return l_iter_advance(iter, index - iter->cursor); return 1; } size_t l_iter_value(struct list_iter * iter) { if (l_empty(iter->target)) return (size_t){ 0 }; return iter->target->buffer[iter->cursor]; } size_t *l_iter_rvalue(struct list_iter * iter) { if (l_empty(iter->target)) return ((void *)0); return &(iter->target->buffer[iter->cursor]); } size_t l_iter_index(struct list_iter * iter) { return iter->cursor; } _Bool l_seq_push_front(struct list * _list_, size_t * values, size_t size) { if (size == 0) { _list_->flag = CMC_FLAG_INVALID; return 0; } if (!l_fits(_list_, size)) { if (!l_resize(_list_, _list_->count + size)) return 0; } memmove(_list_->buffer + size, _list_->buffer, _list_->count * sizeof(size_t)); memcpy(_list_->buffer, values, size * sizeof(size_t)); _list_->count += size; _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->create) (_list_)->callbacks->create();; return 1; } _Bool l_seq_push_at(struct list * _list_, size_t * values, size_t size, size_t index) { if (size == 0) { _list_->flag = CMC_FLAG_INVALID; return 0; } if (index > _list_->count) { _list_->flag = CMC_FLAG_RANGE; return 0; } if (index == 0) return l_seq_push_front(_list_, values, size); else if (index == _list_->count) return l_seq_push_back(_list_, values, size); if (!l_fits(_list_, size)) { if (!l_resize(_list_, _list_->count + size)) return 0; } memmove(_list_->buffer + index + size, _list_->buffer + index, (_list_->count - index) * sizeof(size_t)); memcpy(_list_->buffer + index, values, size * sizeof(size_t)); _list_->count += size; _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->create) (_list_)->callbacks->create();; return 1; } _Bool l_seq_push_back(struct list * _list_, size_t * values, size_t size) { if (size == 0) { _list_->flag = CMC_FLAG_INVALID; return 0; } if (!l_fits(_list_, size)) { if (!l_resize(_list_, _list_->count + size)) return 0; } memcpy(_list_->buffer + _list_->count, values, size * sizeof(size_t)); _list_->count += size; _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->create) (_list_)->callbacks->create();; return 1; } _Bool l_seq_pop_at(struct list * _list_, size_t from, size_t to) { if (from > to) { _list_->flag = CMC_FLAG_INVALID; return 0; } if (to >= _list_->count) { _list_->flag = CMC_FLAG_RANGE; return 0; } size_t length = (to - from + 1); memmove(_list_->buffer + from, _list_->buffer + to + 1, (_list_->count - to - 1) * sizeof(size_t)); memset(_list_->buffer + _list_->count - length, 0, length * sizeof(size_t)); _list_->count -= to - from + 1; _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->delete) (_list_)->callbacks->delete();; return 1; } struct list *l_seq_sublist(struct list * _list_, size_t from, size_t to) { if (from > to) { _list_->flag = CMC_FLAG_INVALID; return ((void *)0); } if (to >= _list_->count) { _list_->flag = CMC_FLAG_RANGE; return ((void *)0); } size_t length = to - from + 1; struct list *result = l_new_custom(length, _list_->f_val, _list_->alloc, (_list_)->callbacks); if (!result) { _list_->flag = CMC_FLAG_ALLOC; return ((void *)0); } memcpy(result->buffer, _list_->buffer, length * sizeof(size_t)); memmove(_list_->buffer + from, _list_->buffer + to + 1, (_list_->count - to - 1) * sizeof(size_t)); memset(_list_->buffer + _list_->count - length, 0, length * sizeof(size_t)); _list_->count -= length; result->count = length; _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->delete) (_list_)->callbacks->delete();; return result; } _Bool l_to_string(struct list * _list_, FILE * fptr) { struct list *l_ = _list_; return 0 <= fprintf(fptr, "struct %s<%s> " "at %p { " "buffer:%p, " "capacity:%" "I64u" ", " "count:%" "I64u" ", " "flag:%d, " "f_val:%p, " "alloc:%p, " "callbacks:%p }", "list", "size_t", l_, l_->buffer, l_->capacity, l_->count, l_->flag, l_->f_val, l_->alloc, (l_)->callbacks); } _Bool l_print(struct list * _list_, FILE * fptr, const char *start, const char *separator, const char *end) { fprintf(fptr, "%s", start); for (size_t i = 0; i < _list_->count; i++) { if (!_list_->f_val->str(fptr, _list_->buffer[i])) return 0; if (i + 1 < _list_->count) fprintf(fptr, "%s", separator); } fprintf(fptr, "%s", end); return 1; } - - \ No newline at end of file +struct list *l_new(size_t capacity, struct list_fval *f_val) +{ + return l_new_custom(capacity, f_val, ((void *)0), ((void *)0)); +} +struct list *l_new_custom(size_t capacity, struct list_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks) +{ + ; + if (capacity < 1) + return ((void *)0); + if (!f_val) + return ((void *)0); + if (!alloc) + alloc = &cmc_alloc_node_default; + struct list *_list_ = alloc->malloc(sizeof(struct list)); + if (!_list_) + return ((void *)0); + _list_->buffer = alloc->calloc(capacity, sizeof(size_t)); + if (!_list_->buffer) + { + alloc->free(_list_); + return ((void *)0); + } + _list_->capacity = capacity; + _list_->count = 0; + _list_->flag = CMC_FLAG_OK; + _list_->f_val = f_val; + _list_->alloc = alloc; + (_list_)->callbacks = callbacks; + return _list_; +} +void l_clear(struct list *_list_) +{ + if (_list_->f_val->free) + { + for (size_t i = 0; i < _list_->count; i++) + _list_->f_val->free(_list_->buffer[i]); + } + memset(_list_->buffer, 0, sizeof(size_t) * _list_->capacity); + _list_->count = 0; + _list_->flag = CMC_FLAG_OK; +} +void l_free(struct list *_list_) +{ + if (_list_->f_val->free) + { + for (size_t i = 0; i < _list_->count; i++) + _list_->f_val->free(_list_->buffer[i]); + } + _list_->alloc->free(_list_->buffer); + _list_->alloc->free(_list_); +} +void l_customize(struct list *_list_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks) +{ + ; + if (!alloc) + _list_->alloc = &cmc_alloc_node_default; + else + _list_->alloc = alloc; + (_list_)->callbacks = callbacks; + _list_->flag = CMC_FLAG_OK; +} +_Bool l_push_front(struct list *_list_, size_t value) +{ + if (l_full(_list_)) + { + if (!l_resize(_list_, _list_->count * 2)) + return 0; + } + if (!l_empty(_list_)) + { + memmove(_list_->buffer + 1, _list_->buffer, _list_->count * sizeof(size_t)); + } + _list_->buffer[0] = value; + _list_->count++; + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->create) + (_list_)->callbacks->create(); + ; + return 1; +} +_Bool l_push_at(struct list *_list_, size_t value, size_t index) +{ + if (index > _list_->count) + { + _list_->flag = CMC_FLAG_RANGE; + return 0; + } + if (l_full(_list_)) + { + if (!l_resize(_list_, _list_->count * 2)) + return 0; + } + memmove(_list_->buffer + index + 1, _list_->buffer + index, (_list_->count - index) * sizeof(size_t)); + _list_->buffer[index] = value; + _list_->count++; + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->create) + (_list_)->callbacks->create(); + ; + return 1; +} +_Bool l_push_back(struct list *_list_, size_t value) +{ + if (l_full(_list_)) + { + if (!l_resize(_list_, _list_->count * 2)) + return 0; + } + _list_->buffer[_list_->count++] = value; + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->create) + (_list_)->callbacks->create(); + ; + return 1; +} +_Bool l_pop_front(struct list *_list_) +{ + if (l_empty(_list_)) + { + _list_->flag = CMC_FLAG_EMPTY; + return 0; + } + memmove(_list_->buffer, _list_->buffer + 1, (_list_->count - 1) * sizeof(size_t)); + _list_->buffer[--_list_->count] = (size_t){ 0 }; + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->delete) + (_list_)->callbacks->delete (); + ; + return 1; +} +_Bool l_pop_at(struct list *_list_, size_t index) +{ + if (l_empty(_list_)) + { + _list_->flag = CMC_FLAG_EMPTY; + return 0; + } + if (index >= _list_->count) + { + _list_->flag = CMC_FLAG_RANGE; + return 0; + } + memmove(_list_->buffer + index, _list_->buffer + index + 1, (_list_->count - index - 1) * sizeof(size_t)); + _list_->buffer[--_list_->count] = (size_t){ 0 }; + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->delete) + (_list_)->callbacks->delete (); + ; + return 1; +} +_Bool l_pop_back(struct list *_list_) +{ + if (l_empty(_list_)) + return 0; + _list_->buffer[--_list_->count] = (size_t){ 0 }; + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->delete) + (_list_)->callbacks->delete (); + ; + return 1; +} +size_t l_front(struct list *_list_) +{ + if (l_empty(_list_)) + { + _list_->flag = CMC_FLAG_EMPTY; + return (size_t){ 0 }; + } + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->read) + (_list_)->callbacks->read(); + ; + return _list_->buffer[0]; +} +size_t l_get(struct list *_list_, size_t index) +{ + if (l_empty(_list_)) + { + _list_->flag = CMC_FLAG_EMPTY; + return (size_t){ 0 }; + } + if (index >= _list_->count) + { + _list_->flag = CMC_FLAG_RANGE; + return (size_t){ 0 }; + } + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->read) + (_list_)->callbacks->read(); + ; + return _list_->buffer[index]; +} +size_t *l_get_ref(struct list *_list_, size_t index) +{ + if (l_empty(_list_)) + { + _list_->flag = CMC_FLAG_EMPTY; + return ((void *)0); + } + if (index >= _list_->count) + { + _list_->flag = CMC_FLAG_RANGE; + return ((void *)0); + } + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->read) + (_list_)->callbacks->read(); + ; + return &(_list_->buffer[index]); +} +size_t l_back(struct list *_list_) +{ + if (l_empty(_list_)) + { + _list_->flag = CMC_FLAG_EMPTY; + return (size_t){ 0 }; + } + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->read) + (_list_)->callbacks->read(); + ; + return _list_->buffer[_list_->count - 1]; +} +size_t l_index_of(struct list *_list_, size_t value, _Bool from_start) +{ + _list_->flag = CMC_FLAG_OK; + size_t result = _list_->count; + if (from_start) + { + for (size_t i = 0; i < _list_->count; i++) + { + if (_list_->f_val->cmp(_list_->buffer[i], value) == 0) + { + result = i; + break; + } + } + } + else + { + for (size_t i = _list_->count; i > 0; i--) + { + if (_list_->f_val->cmp(_list_->buffer[i - 1], value) == 0) + { + result = i - 1; + break; + } + } + } + if ((_list_)->callbacks && (_list_)->callbacks->read) + (_list_)->callbacks->read(); + ; + return result; +} +_Bool l_contains(struct list *_list_, size_t value) +{ + _list_->flag = CMC_FLAG_OK; + _Bool result = 0; + for (size_t i = 0; i < _list_->count; i++) + { + if (_list_->f_val->cmp(_list_->buffer[i], value) == 0) + { + result = 1; + break; + } + } + if ((_list_)->callbacks && (_list_)->callbacks->read) + (_list_)->callbacks->read(); + ; + return result; +} +_Bool l_empty(struct list *_list_) +{ + return _list_->count == 0; +} +_Bool l_full(struct list *_list_) +{ + return _list_->count >= _list_->capacity; +} +size_t l_count(struct list *_list_) +{ + return _list_->count; +} +_Bool l_fits(struct list *_list_, size_t size) +{ + return _list_->count + size <= _list_->capacity; +} +size_t l_capacity(struct list *_list_) +{ + return _list_->capacity; +} +int l_flag(struct list *_list_) +{ + return _list_->flag; +} +_Bool l_resize(struct list *_list_, size_t capacity) +{ + _list_->flag = CMC_FLAG_OK; + if (_list_->capacity == capacity) + return 1; + if (capacity < _list_->count) + { + _list_->flag = CMC_FLAG_INVALID; + return 0; + } + size_t *new_buffer = _list_->alloc->realloc(_list_->buffer, sizeof(size_t) * capacity); + if (!new_buffer) + { + _list_->flag = CMC_FLAG_ALLOC; + return 0; + } + _list_->buffer = new_buffer; + _list_->capacity = capacity; + if ((_list_)->callbacks && (_list_)->callbacks->resize) + (_list_)->callbacks->resize(); + ; + return 1; +} +struct list *l_copy_of(struct list *_list_) +{ + struct list *result = l_new_custom(_list_->capacity, _list_->f_val, _list_->alloc, ((void *)0)); + if (!result) + { + _list_->flag = CMC_FLAG_ALLOC; + return ((void *)0); + } + (result)->callbacks = _list_->callbacks; + if (_list_->f_val->cpy) + { + for (size_t i = 0; i < _list_->count; i++) + result->buffer[i] = _list_->f_val->cpy(_list_->buffer[i]); + } + else + memcpy(result->buffer, _list_->buffer, sizeof(size_t) * _list_->count); + result->count = _list_->count; + _list_->flag = CMC_FLAG_OK; + return result; +} +_Bool l_equals(struct list *_list1_, struct list *_list2_) +{ + _list1_->flag = CMC_FLAG_OK; + _list2_->flag = CMC_FLAG_OK; + if (_list1_->count != _list2_->count) + return 0; + for (size_t i = 0; i < _list1_->count; i++) + { + if (0 != _list1_->f_val->cmp(_list1_->buffer[i], _list2_->buffer[i])) + return 0; + } + return 1; +} +struct list_iter l_iter_start(struct list *target) +{ + struct list_iter iter; + iter.target = target; + iter.cursor = 0; + iter.start = 1; + iter.end = l_empty(target); + return iter; +} +struct list_iter l_iter_end(struct list *target) +{ + struct list_iter iter; + iter.target = target; + iter.cursor = 0; + iter.start = l_empty(target); + iter.end = 1; + if (!l_empty(target)) + iter.cursor = target->count - 1; + return iter; +} +_Bool l_iter_at_start(struct list_iter *iter) +{ + return l_empty(iter->target) || iter->start; +} +_Bool l_iter_at_end(struct list_iter *iter) +{ + return l_empty(iter->target) || iter->end; +} +_Bool l_iter_to_start(struct list_iter *iter) +{ + if (!l_empty(iter->target)) + { + iter->cursor = 0; + iter->start = 1; + iter->end = l_empty(iter->target); + return 1; + } + return 0; +} +_Bool l_iter_to_end(struct list_iter *iter) +{ + if (!l_empty(iter->target)) + { + iter->start = l_empty(iter->target); + iter->cursor = iter->target->count - 1; + iter->end = 1; + return 1; + } + return 0; +} +_Bool l_iter_next(struct list_iter *iter) +{ + if (iter->end) + return 0; + if (iter->cursor + 1 == iter->target->count) + { + iter->end = 1; + return 0; + } + iter->start = l_empty(iter->target); + iter->cursor++; + return 1; +} +_Bool l_iter_prev(struct list_iter *iter) +{ + if (iter->start) + return 0; + if (iter->cursor == 0) + { + iter->start = 1; + return 0; + } + iter->end = l_empty(iter->target); + iter->cursor--; + return 1; +} +_Bool l_iter_advance(struct list_iter *iter, size_t steps) +{ + if (iter->end) + return 0; + if (iter->cursor + 1 == iter->target->count) + { + iter->end = 1; + return 0; + } + if (steps == 0 || iter->cursor + steps >= iter->target->count) + return 0; + iter->start = l_empty(iter->target); + iter->cursor += steps; + return 1; +} +_Bool l_iter_rewind(struct list_iter *iter, size_t steps) +{ + if (iter->start) + return 0; + if (iter->cursor == 0) + { + iter->start = 1; + return 0; + } + if (steps == 0 || iter->cursor < steps) + return 0; + iter->end = l_empty(iter->target); + iter->cursor -= steps; + return 1; +} +_Bool l_iter_go_to(struct list_iter *iter, size_t index) +{ + if (index >= iter->target->count) + return 0; + if (iter->cursor > index) + return l_iter_rewind(iter, iter->cursor - index); + else if (iter->cursor < index) + return l_iter_advance(iter, index - iter->cursor); + return 1; +} +size_t l_iter_value(struct list_iter *iter) +{ + if (l_empty(iter->target)) + return (size_t){ 0 }; + return iter->target->buffer[iter->cursor]; +} +size_t *l_iter_rvalue(struct list_iter *iter) +{ + if (l_empty(iter->target)) + return ((void *)0); + return &(iter->target->buffer[iter->cursor]); +} +size_t l_iter_index(struct list_iter *iter) +{ + return iter->cursor; +} +_Bool l_seq_push_front(struct list *_list_, size_t *values, size_t size) +{ + if (size == 0) + { + _list_->flag = CMC_FLAG_INVALID; + return 0; + } + if (!l_fits(_list_, size)) + { + if (!l_resize(_list_, _list_->count + size)) + return 0; + } + memmove(_list_->buffer + size, _list_->buffer, _list_->count * sizeof(size_t)); + memcpy(_list_->buffer, values, size * sizeof(size_t)); + _list_->count += size; + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->create) + (_list_)->callbacks->create(); + ; + return 1; +} +_Bool l_seq_push_at(struct list *_list_, size_t *values, size_t size, size_t index) +{ + if (size == 0) + { + _list_->flag = CMC_FLAG_INVALID; + return 0; + } + if (index > _list_->count) + { + _list_->flag = CMC_FLAG_RANGE; + return 0; + } + if (index == 0) + return l_seq_push_front(_list_, values, size); + else if (index == _list_->count) + return l_seq_push_back(_list_, values, size); + if (!l_fits(_list_, size)) + { + if (!l_resize(_list_, _list_->count + size)) + return 0; + } + memmove(_list_->buffer + index + size, _list_->buffer + index, (_list_->count - index) * sizeof(size_t)); + memcpy(_list_->buffer + index, values, size * sizeof(size_t)); + _list_->count += size; + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->create) + (_list_)->callbacks->create(); + ; + return 1; +} +_Bool l_seq_push_back(struct list *_list_, size_t *values, size_t size) +{ + if (size == 0) + { + _list_->flag = CMC_FLAG_INVALID; + return 0; + } + if (!l_fits(_list_, size)) + { + if (!l_resize(_list_, _list_->count + size)) + return 0; + } + memcpy(_list_->buffer + _list_->count, values, size * sizeof(size_t)); + _list_->count += size; + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->create) + (_list_)->callbacks->create(); + ; + return 1; +} +_Bool l_seq_pop_at(struct list *_list_, size_t from, size_t to) +{ + if (from > to) + { + _list_->flag = CMC_FLAG_INVALID; + return 0; + } + if (to >= _list_->count) + { + _list_->flag = CMC_FLAG_RANGE; + return 0; + } + size_t length = (to - from + 1); + memmove(_list_->buffer + from, _list_->buffer + to + 1, (_list_->count - to - 1) * sizeof(size_t)); + memset(_list_->buffer + _list_->count - length, 0, length * sizeof(size_t)); + _list_->count -= to - from + 1; + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->delete) + (_list_)->callbacks->delete (); + ; + return 1; +} +struct list *l_seq_sublist(struct list *_list_, size_t from, size_t to) +{ + if (from > to) + { + _list_->flag = CMC_FLAG_INVALID; + return ((void *)0); + } + if (to >= _list_->count) + { + _list_->flag = CMC_FLAG_RANGE; + return ((void *)0); + } + size_t length = to - from + 1; + struct list *result = l_new_custom(length, _list_->f_val, _list_->alloc, (_list_)->callbacks); + if (!result) + { + _list_->flag = CMC_FLAG_ALLOC; + return ((void *)0); + } + memcpy(result->buffer, _list_->buffer, length * sizeof(size_t)); + memmove(_list_->buffer + from, _list_->buffer + to + 1, (_list_->count - to - 1) * sizeof(size_t)); + memset(_list_->buffer + _list_->count - length, 0, length * sizeof(size_t)); + _list_->count -= length; + result->count = length; + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->delete) + (_list_)->callbacks->delete (); + ; + return result; +} +_Bool l_to_string(struct list *_list_, FILE *fptr) +{ + struct list *l_ = _list_; + return 0 <= fprintf(fptr, + "struct %s<%s> " + "at %p { " + "buffer:%p, " + "capacity:%" + "I64u" + ", " + "count:%" + "I64u" + ", " + "flag:%d, " + "f_val:%p, " + "alloc:%p, " + "callbacks:%p }", + "list", "size_t", l_, l_->buffer, l_->capacity, l_->count, l_->flag, l_->f_val, l_->alloc, + (l_)->callbacks); +} +_Bool l_print(struct list *_list_, FILE *fptr, const char *start, const char *separator, const char *end) +{ + fprintf(fptr, "%s", start); + for (size_t i = 0; i < _list_->count; i++) + { + if (!_list_->f_val->str(fptr, _list_->buffer[i])) + return 0; + if (i + 1 < _list_->count) + fprintf(fptr, "%s", separator); + } + fprintf(fptr, "%s", end); + return 1; +} diff --git a/tests/src/tst_cmc_queue.c b/tests/src/tst_cmc_queue.c index 9ae20dc..82dc6cb 100644 --- a/tests/src/tst_cmc_queue.c +++ b/tests/src/tst_cmc_queue.c @@ -1,7 +1,431 @@ - #include "tst_cmc_queue.h" +#include "tst_cmc_queue.h" - - struct queue *q_new(size_t capacity, struct queue_fval * f_val) { return q_new_custom(capacity, f_val, ((void *)0), ((void *)0)); } struct queue *q_new_custom(size_t capacity, struct queue_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (capacity < 1) return ((void *)0); if (!f_val) return ((void *)0); if (!alloc) alloc = &cmc_alloc_node_default; struct queue *_queue_ = alloc->malloc(sizeof(struct queue)); if (!_queue_) return ((void *)0); _queue_->buffer = alloc->calloc(capacity, sizeof(size_t)); if (!_queue_->buffer) { alloc->free(_queue_); return ((void *)0); } _queue_->capacity = capacity; _queue_->count = 0; _queue_->front = 0; _queue_->back = 0; _queue_->flag = CMC_FLAG_OK; _queue_->f_val = f_val; _queue_->alloc = alloc; (_queue_)->callbacks = callbacks; return _queue_; } void q_clear(struct queue * _queue_) { if (_queue_->f_val->free) { for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) { _queue_->f_val->free(_queue_->buffer[i]); i = (i + 1) % _queue_->capacity; } } memset(_queue_->buffer, 0, sizeof(size_t) * _queue_->capacity); _queue_->count = 0; _queue_->front = 0; _queue_->back = 0; _queue_->flag = CMC_FLAG_OK; } void q_free(struct queue * _queue_) { if (_queue_->f_val->free) { for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) { _queue_->f_val->free(_queue_->buffer[i]); i = (i + 1) % _queue_->capacity; } } _queue_->alloc->free(_queue_->buffer); _queue_->alloc->free(_queue_); } void q_customize(struct queue * _queue_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (!alloc) _queue_->alloc = &cmc_alloc_node_default; else _queue_->alloc = alloc; (_queue_)->callbacks = callbacks; _queue_->flag = CMC_FLAG_OK; } _Bool q_enqueue(struct queue * _queue_, size_t value) { if (q_full(_queue_)) { if (!q_resize(_queue_, _queue_->capacity * 2)) return 0; } _queue_->buffer[_queue_->back] = value; _queue_->back = (_queue_->back == _queue_->capacity - 1) ? 0 : _queue_->back + 1; _queue_->count++; _queue_->flag = CMC_FLAG_OK; if ((_queue_)->callbacks && (_queue_)->callbacks->create) (_queue_)->callbacks->create();; return 1; } _Bool q_dequeue(struct queue * _queue_) { if (q_empty(_queue_)) { _queue_->flag = CMC_FLAG_EMPTY; return 0; } _queue_->buffer[_queue_->front] = (size_t){ 0 }; _queue_->front = (_queue_->front == _queue_->capacity - 1) ? 0 : _queue_->front + 1; _queue_->count--; _queue_->flag = CMC_FLAG_OK; if ((_queue_)->callbacks && (_queue_)->callbacks->delete) (_queue_)->callbacks->delete();; return 1; } size_t q_peek(struct queue * _queue_) { if (q_empty(_queue_)) { _queue_->flag = CMC_FLAG_EMPTY; return (size_t){ 0 }; } _queue_->flag = CMC_FLAG_OK; if ((_queue_)->callbacks && (_queue_)->callbacks->read) (_queue_)->callbacks->read();; return _queue_->buffer[_queue_->front]; } _Bool q_contains(struct queue * _queue_, size_t value) { _queue_->flag = CMC_FLAG_OK; _Bool result = 0; for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) { if (_queue_->f_val->cmp(_queue_->buffer[i], value) == 0) { result = 1; break; } i = (i + 1) % _queue_->capacity; } if ((_queue_)->callbacks && (_queue_)->callbacks->read) (_queue_)->callbacks->read();; return result; } _Bool q_empty(struct queue * _queue_) { return _queue_->count == 0; } _Bool q_full(struct queue * _queue_) { return _queue_->count >= _queue_->capacity; } size_t q_count(struct queue * _queue_) { return _queue_->count; } size_t q_capacity(struct queue * _queue_) { return _queue_->capacity; } int q_flag(struct queue * _queue_) { return _queue_->flag; } _Bool q_resize(struct queue * _queue_, size_t capacity) { if (_queue_->capacity == capacity) goto success; if (capacity < _queue_->count) { _queue_->flag = CMC_FLAG_INVALID; return 0; } size_t *new_buffer = _queue_->alloc->malloc(sizeof(size_t) * capacity); if (!new_buffer) { _queue_->flag = CMC_FLAG_ALLOC; return 0; } for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) { new_buffer[j] = _queue_->buffer[i]; i = (i + 1) % _queue_->capacity; } _queue_->alloc->free(_queue_->buffer); _queue_->buffer = new_buffer; _queue_->capacity = capacity; _queue_->front = 0; _queue_->back = _queue_->count; success: _queue_->flag = CMC_FLAG_OK; if ((_queue_)->callbacks && (_queue_)->callbacks->resize) (_queue_)->callbacks->resize();; return 1; } struct queue *q_copy_of(struct queue * _queue_) { struct queue *result = q_new_custom(_queue_->capacity, _queue_->f_val, _queue_->alloc, ((void *)0)); if (!result) { _queue_->flag = CMC_FLAG_ERROR; return ((void *)0); } (result)->callbacks = _queue_->callbacks; if (_queue_->f_val->cpy) { for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) { result->buffer[j] = _queue_->f_val->cpy(_queue_->buffer[i]); i = (i + 1) % _queue_->capacity; } } else { for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) { result->buffer[j] = _queue_->buffer[i]; i = (i + 1) % _queue_->capacity; } } result->count = _queue_->count; result->front = 0; result->back = _queue_->count; _queue_->flag = CMC_FLAG_OK; return result; } _Bool q_equals(struct queue * _queue1_, struct queue * _queue2_) { _queue1_->flag = CMC_FLAG_OK; _queue2_->flag = CMC_FLAG_OK; if (_queue1_->count != _queue2_->count) return 0; size_t i, j, k; for (i = _queue1_->front, j = _queue2_->front, k = 0; k < _queue1_->count; k++) { if (_queue1_->f_val->cmp(_queue1_->buffer[i], _queue2_->buffer[j]) != 0) return 0; i = (i + 1) % _queue1_->capacity; j = (j + 1) % _queue2_->capacity; } return 1; } struct queue_iter q_iter_start(struct queue * target) { struct queue_iter iter; iter.target = target; iter.cursor = target->front; iter.index = 0; iter.start = 1; iter.end = q_empty(target); return iter; } struct queue_iter q_iter_end(struct queue * target) { struct queue_iter iter; iter.target = target; if (!q_empty(target)) { if (iter.target->back == 0) iter.cursor = iter.target->capacity - 1; else iter.cursor = iter.target->back - 1; iter.index = iter.target->count - 1; } else { iter.cursor = 0; iter.index = 0; } iter.start = q_empty(target); iter.end = 1; return iter; } _Bool q_iter_at_start(struct queue_iter * iter) { return q_empty(iter->target) || iter->start; } _Bool q_iter_at_end(struct queue_iter * iter) { return q_empty(iter->target) || iter->end; } _Bool q_iter_to_start(struct queue_iter * iter) { if (!q_empty(iter->target)) { iter->cursor = iter->target->front; iter->index = 0; iter->start = 1; iter->end = 0; return 1; } return 0; } _Bool q_iter_to_end(struct queue_iter * iter) { if (!q_empty(iter->target)) { if (iter->target->back == 0) iter->cursor = iter->target->capacity - 1; else iter->cursor = iter->target->back - 1; iter->index = iter->target->count - 1; iter->start = 0; iter->end = 1; return 1; } return 0; } _Bool q_iter_next(struct queue_iter * iter) { if (iter->end) return 0; if (iter->index + 1 == iter->target->count) { iter->end = 1; return 0; } iter->start = q_empty(iter->target); iter->cursor = (iter->cursor + 1) % (iter->target->capacity); iter->index++; return 1; } _Bool q_iter_prev(struct queue_iter * iter) { if (iter->start) return 0; if (iter->index == 0) { iter->start = 1; return 0; } iter->end = q_empty(iter->target); iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; iter->index--; return 1; } _Bool q_iter_advance(struct queue_iter * iter, size_t steps) { if (iter->end) return 0; if (iter->index + 1 == iter->target->count) { iter->end = 1; return 0; } if (steps == 0 || iter->index + steps >= iter->target->count) return 0; iter->start = q_empty(iter->target); iter->index += steps; iter->cursor = (iter->cursor + steps) % iter->target->capacity; return 1; } _Bool q_iter_rewind(struct queue_iter * iter, size_t steps) { if (iter->start) return 0; if (iter->index == 0) { iter->start = 1; return 0; } if (steps == 0 || iter->index < steps) return 0; iter->end = q_empty(iter->target); iter->index -= steps; if (iter->cursor < steps) iter->cursor += iter->target->capacity; iter->cursor -= steps; return 1; } _Bool q_iter_go_to(struct queue_iter * iter, size_t index) { if (index >= iter->target->count) return 0; if (iter->index > index) return q_iter_rewind(iter, iter->index - index); else if (iter->index < index) return q_iter_advance(iter, index - iter->index); return 1; } size_t q_iter_value(struct queue_iter * iter) { if (q_empty(iter->target)) return (size_t){ 0 }; return iter->target->buffer[iter->cursor]; } size_t *q_iter_rvalue(struct queue_iter * iter) { if (q_empty(iter->target)) return ((void *)0); return &(iter->target->buffer[iter->cursor]); } size_t q_iter_index(struct queue_iter * iter) { return iter->index; } _Bool q_to_string(struct queue * _queue_, FILE * fptr) { struct queue *q_ = _queue_; return 0 <= fprintf(fptr, "struct %s<%s> " "at %p { " "buffer:%p, " "capacity:%" "I64u" ", " "count:%" "I64u" ", " "front:%" "I64u" ", " "back:%" "I64u" ", " "flag:%d, " "f_val:%p, " "alloc:%p, " "callbacks:%p }", "queue", "size_t", q_, q_->buffer, q_->capacity, q_->count, q_->front, q_->back, q_->flag, q_->f_val, q_->alloc, (q_)->callbacks); } _Bool q_print(struct queue * _queue_, FILE * fptr, const char *start, const char *separator, const char *end) { fprintf(fptr, "%s", start); for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) { if (!_queue_->f_val->str(fptr, _queue_->buffer[i])) return 0; i = (i + 1) % _queue_->capacity; if (j + 1 < _queue_->count) fprintf(fptr, "%s", separator); } fprintf(fptr, "%s", end); return 1; } - - \ No newline at end of file +struct queue *q_new(size_t capacity, struct queue_fval *f_val) +{ + return q_new_custom(capacity, f_val, ((void *)0), ((void *)0)); +} +struct queue *q_new_custom(size_t capacity, struct queue_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks) +{ + ; + if (capacity < 1) + return ((void *)0); + if (!f_val) + return ((void *)0); + if (!alloc) + alloc = &cmc_alloc_node_default; + struct queue *_queue_ = alloc->malloc(sizeof(struct queue)); + if (!_queue_) + return ((void *)0); + _queue_->buffer = alloc->calloc(capacity, sizeof(size_t)); + if (!_queue_->buffer) + { + alloc->free(_queue_); + return ((void *)0); + } + _queue_->capacity = capacity; + _queue_->count = 0; + _queue_->front = 0; + _queue_->back = 0; + _queue_->flag = CMC_FLAG_OK; + _queue_->f_val = f_val; + _queue_->alloc = alloc; + (_queue_)->callbacks = callbacks; + return _queue_; +} +void q_clear(struct queue *_queue_) +{ + if (_queue_->f_val->free) + { + for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) + { + _queue_->f_val->free(_queue_->buffer[i]); + i = (i + 1) % _queue_->capacity; + } + } + memset(_queue_->buffer, 0, sizeof(size_t) * _queue_->capacity); + _queue_->count = 0; + _queue_->front = 0; + _queue_->back = 0; + _queue_->flag = CMC_FLAG_OK; +} +void q_free(struct queue *_queue_) +{ + if (_queue_->f_val->free) + { + for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) + { + _queue_->f_val->free(_queue_->buffer[i]); + i = (i + 1) % _queue_->capacity; + } + } + _queue_->alloc->free(_queue_->buffer); + _queue_->alloc->free(_queue_); +} +void q_customize(struct queue *_queue_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks) +{ + ; + if (!alloc) + _queue_->alloc = &cmc_alloc_node_default; + else + _queue_->alloc = alloc; + (_queue_)->callbacks = callbacks; + _queue_->flag = CMC_FLAG_OK; +} +_Bool q_enqueue(struct queue *_queue_, size_t value) +{ + if (q_full(_queue_)) + { + if (!q_resize(_queue_, _queue_->capacity * 2)) + return 0; + } + _queue_->buffer[_queue_->back] = value; + _queue_->back = (_queue_->back == _queue_->capacity - 1) ? 0 : _queue_->back + 1; + _queue_->count++; + _queue_->flag = CMC_FLAG_OK; + if ((_queue_)->callbacks && (_queue_)->callbacks->create) + (_queue_)->callbacks->create(); + ; + return 1; +} +_Bool q_dequeue(struct queue *_queue_) +{ + if (q_empty(_queue_)) + { + _queue_->flag = CMC_FLAG_EMPTY; + return 0; + } + _queue_->buffer[_queue_->front] = (size_t){ 0 }; + _queue_->front = (_queue_->front == _queue_->capacity - 1) ? 0 : _queue_->front + 1; + _queue_->count--; + _queue_->flag = CMC_FLAG_OK; + if ((_queue_)->callbacks && (_queue_)->callbacks->delete) + (_queue_)->callbacks->delete (); + ; + return 1; +} +size_t q_peek(struct queue *_queue_) +{ + if (q_empty(_queue_)) + { + _queue_->flag = CMC_FLAG_EMPTY; + return (size_t){ 0 }; + } + _queue_->flag = CMC_FLAG_OK; + if ((_queue_)->callbacks && (_queue_)->callbacks->read) + (_queue_)->callbacks->read(); + ; + return _queue_->buffer[_queue_->front]; +} +_Bool q_contains(struct queue *_queue_, size_t value) +{ + _queue_->flag = CMC_FLAG_OK; + _Bool result = 0; + for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) + { + if (_queue_->f_val->cmp(_queue_->buffer[i], value) == 0) + { + result = 1; + break; + } + i = (i + 1) % _queue_->capacity; + } + if ((_queue_)->callbacks && (_queue_)->callbacks->read) + (_queue_)->callbacks->read(); + ; + return result; +} +_Bool q_empty(struct queue *_queue_) +{ + return _queue_->count == 0; +} +_Bool q_full(struct queue *_queue_) +{ + return _queue_->count >= _queue_->capacity; +} +size_t q_count(struct queue *_queue_) +{ + return _queue_->count; +} +size_t q_capacity(struct queue *_queue_) +{ + return _queue_->capacity; +} +int q_flag(struct queue *_queue_) +{ + return _queue_->flag; +} +_Bool q_resize(struct queue *_queue_, size_t capacity) +{ + if (_queue_->capacity == capacity) + goto success; + if (capacity < _queue_->count) + { + _queue_->flag = CMC_FLAG_INVALID; + return 0; + } + size_t *new_buffer = _queue_->alloc->malloc(sizeof(size_t) * capacity); + if (!new_buffer) + { + _queue_->flag = CMC_FLAG_ALLOC; + return 0; + } + for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) + { + new_buffer[j] = _queue_->buffer[i]; + i = (i + 1) % _queue_->capacity; + } + _queue_->alloc->free(_queue_->buffer); + _queue_->buffer = new_buffer; + _queue_->capacity = capacity; + _queue_->front = 0; + _queue_->back = _queue_->count; +success: + _queue_->flag = CMC_FLAG_OK; + if ((_queue_)->callbacks && (_queue_)->callbacks->resize) + (_queue_)->callbacks->resize(); + ; + return 1; +} +struct queue *q_copy_of(struct queue *_queue_) +{ + struct queue *result = q_new_custom(_queue_->capacity, _queue_->f_val, _queue_->alloc, ((void *)0)); + if (!result) + { + _queue_->flag = CMC_FLAG_ERROR; + return ((void *)0); + } + (result)->callbacks = _queue_->callbacks; + if (_queue_->f_val->cpy) + { + for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) + { + result->buffer[j] = _queue_->f_val->cpy(_queue_->buffer[i]); + i = (i + 1) % _queue_->capacity; + } + } + else + { + for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) + { + result->buffer[j] = _queue_->buffer[i]; + i = (i + 1) % _queue_->capacity; + } + } + result->count = _queue_->count; + result->front = 0; + result->back = _queue_->count; + _queue_->flag = CMC_FLAG_OK; + return result; +} +_Bool q_equals(struct queue *_queue1_, struct queue *_queue2_) +{ + _queue1_->flag = CMC_FLAG_OK; + _queue2_->flag = CMC_FLAG_OK; + if (_queue1_->count != _queue2_->count) + return 0; + size_t i, j, k; + for (i = _queue1_->front, j = _queue2_->front, k = 0; k < _queue1_->count; k++) + { + if (_queue1_->f_val->cmp(_queue1_->buffer[i], _queue2_->buffer[j]) != 0) + return 0; + i = (i + 1) % _queue1_->capacity; + j = (j + 1) % _queue2_->capacity; + } + return 1; +} +struct queue_iter q_iter_start(struct queue *target) +{ + struct queue_iter iter; + iter.target = target; + iter.cursor = target->front; + iter.index = 0; + iter.start = 1; + iter.end = q_empty(target); + return iter; +} +struct queue_iter q_iter_end(struct queue *target) +{ + struct queue_iter iter; + iter.target = target; + if (!q_empty(target)) + { + if (iter.target->back == 0) + iter.cursor = iter.target->capacity - 1; + else + iter.cursor = iter.target->back - 1; + iter.index = iter.target->count - 1; + } + else + { + iter.cursor = 0; + iter.index = 0; + } + iter.start = q_empty(target); + iter.end = 1; + return iter; +} +_Bool q_iter_at_start(struct queue_iter *iter) +{ + return q_empty(iter->target) || iter->start; +} +_Bool q_iter_at_end(struct queue_iter *iter) +{ + return q_empty(iter->target) || iter->end; +} +_Bool q_iter_to_start(struct queue_iter *iter) +{ + if (!q_empty(iter->target)) + { + iter->cursor = iter->target->front; + iter->index = 0; + iter->start = 1; + iter->end = 0; + return 1; + } + return 0; +} +_Bool q_iter_to_end(struct queue_iter *iter) +{ + if (!q_empty(iter->target)) + { + if (iter->target->back == 0) + iter->cursor = iter->target->capacity - 1; + else + iter->cursor = iter->target->back - 1; + iter->index = iter->target->count - 1; + iter->start = 0; + iter->end = 1; + return 1; + } + return 0; +} +_Bool q_iter_next(struct queue_iter *iter) +{ + if (iter->end) + return 0; + if (iter->index + 1 == iter->target->count) + { + iter->end = 1; + return 0; + } + iter->start = q_empty(iter->target); + iter->cursor = (iter->cursor + 1) % (iter->target->capacity); + iter->index++; + return 1; +} +_Bool q_iter_prev(struct queue_iter *iter) +{ + if (iter->start) + return 0; + if (iter->index == 0) + { + iter->start = 1; + return 0; + } + iter->end = q_empty(iter->target); + iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; + iter->index--; + return 1; +} +_Bool q_iter_advance(struct queue_iter *iter, size_t steps) +{ + if (iter->end) + return 0; + if (iter->index + 1 == iter->target->count) + { + iter->end = 1; + return 0; + } + if (steps == 0 || iter->index + steps >= iter->target->count) + return 0; + iter->start = q_empty(iter->target); + iter->index += steps; + iter->cursor = (iter->cursor + steps) % iter->target->capacity; + return 1; +} +_Bool q_iter_rewind(struct queue_iter *iter, size_t steps) +{ + if (iter->start) + return 0; + if (iter->index == 0) + { + iter->start = 1; + return 0; + } + if (steps == 0 || iter->index < steps) + return 0; + iter->end = q_empty(iter->target); + iter->index -= steps; + if (iter->cursor < steps) + iter->cursor += iter->target->capacity; + iter->cursor -= steps; + return 1; +} +_Bool q_iter_go_to(struct queue_iter *iter, size_t index) +{ + if (index >= iter->target->count) + return 0; + if (iter->index > index) + return q_iter_rewind(iter, iter->index - index); + else if (iter->index < index) + return q_iter_advance(iter, index - iter->index); + return 1; +} +size_t q_iter_value(struct queue_iter *iter) +{ + if (q_empty(iter->target)) + return (size_t){ 0 }; + return iter->target->buffer[iter->cursor]; +} +size_t *q_iter_rvalue(struct queue_iter *iter) +{ + if (q_empty(iter->target)) + return ((void *)0); + return &(iter->target->buffer[iter->cursor]); +} +size_t q_iter_index(struct queue_iter *iter) +{ + return iter->index; +} +_Bool q_to_string(struct queue *_queue_, FILE *fptr) +{ + struct queue *q_ = _queue_; + return 0 <= fprintf(fptr, + "struct %s<%s> " + "at %p { " + "buffer:%p, " + "capacity:%" + "I64u" + ", " + "count:%" + "I64u" + ", " + "front:%" + "I64u" + ", " + "back:%" + "I64u" + ", " + "flag:%d, " + "f_val:%p, " + "alloc:%p, " + "callbacks:%p }", + "queue", "size_t", q_, q_->buffer, q_->capacity, q_->count, q_->front, q_->back, q_->flag, + q_->f_val, q_->alloc, (q_)->callbacks); +} +_Bool q_print(struct queue *_queue_, FILE *fptr, const char *start, const char *separator, const char *end) +{ + fprintf(fptr, "%s", start); + for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) + { + if (!_queue_->f_val->str(fptr, _queue_->buffer[i])) + return 0; + i = (i + 1) % _queue_->capacity; + if (j + 1 < _queue_->count) + fprintf(fptr, "%s", separator); + } + fprintf(fptr, "%s", end); + return 1; +} diff --git a/tests/src/tst_cmc_sortedlist.c b/tests/src/tst_cmc_sortedlist.c index 75c57f9..ae46830 100644 --- a/tests/src/tst_cmc_sortedlist.c +++ b/tests/src/tst_cmc_sortedlist.c @@ -1,7 +1,512 @@ - #include "tst_cmc_sortedlist.h" +#include "tst_cmc_sortedlist.h" - - static size_t sl_impl_binary_search_first(struct sortedlist * _list_, size_t value); static size_t sl_impl_binary_search_last(struct sortedlist * _list_, size_t value); void sl_impl_sort_quicksort(size_t * array, int (*cmp)(size_t, size_t), size_t low, size_t high); void sl_impl_sort_insertion(size_t * array, int (*cmp)(size_t, size_t), size_t low, size_t high); struct sortedlist *sl_new(size_t capacity, struct sortedlist_fval * f_val) { return sl_new_custom(capacity, f_val, ((void *)0), ((void *)0)); } struct sortedlist *sl_new_custom(size_t capacity, struct sortedlist_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (capacity < 1) return ((void *)0); if (!alloc) alloc = &cmc_alloc_node_default; struct sortedlist *_list_ = alloc->malloc(sizeof(struct sortedlist)); if (!_list_) return ((void *)0); _list_->buffer = alloc->calloc(capacity, sizeof(size_t)); if (!_list_->buffer) { alloc->free(_list_); return ((void *)0); } _list_->capacity = capacity; _list_->count = 0; _list_->is_sorted = 0; _list_->flag = CMC_FLAG_OK; _list_->f_val = f_val; _list_->alloc = alloc; (_list_)->callbacks = callbacks; return _list_; } void sl_clear(struct sortedlist * _list_) { if (_list_->f_val->free) { for (size_t i = 0; i < _list_->count; i++) _list_->f_val->free(_list_->buffer[i]); } memset(_list_->buffer, 0, sizeof(size_t) * _list_->capacity); _list_->count = 0; _list_->flag = CMC_FLAG_OK; } void sl_free(struct sortedlist * _list_) { if (_list_->f_val->free) { for (size_t i = 0; i < _list_->count; i++) _list_->f_val->free(_list_->buffer[i]); } _list_->alloc->free(_list_->buffer); _list_->alloc->free(_list_); } void sl_customize(struct sortedlist * _list_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (!alloc) _list_->alloc = &cmc_alloc_node_default; else _list_->alloc = alloc; (_list_)->callbacks = callbacks; _list_->flag = CMC_FLAG_OK; } _Bool sl_insert(struct sortedlist * _list_, size_t value) { if (sl_full(_list_)) { if (!sl_resize(_list_, _list_->capacity * 2)) return 0; } _list_->buffer[_list_->count++] = value; _list_->is_sorted = 0; _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->create) (_list_)->callbacks->create();; return 1; } _Bool sl_remove(struct sortedlist * _list_, size_t index) { if (sl_empty(_list_)) { _list_->flag = CMC_FLAG_EMPTY; return 0; } if (index >= _list_->count) { _list_->flag = CMC_FLAG_RANGE; return 0; } memmove(_list_->buffer + index, _list_->buffer + index + 1, (_list_->count - index) * sizeof(size_t)); _list_->buffer[--_list_->count] = (size_t){ 0 }; _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->delete) (_list_)->callbacks->delete();; return 1; } size_t sl_max(struct sortedlist * _list_) { if (sl_empty(_list_)) { _list_->flag = CMC_FLAG_EMPTY; return (size_t){ 0 }; } sl_sort(_list_); _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->read) (_list_)->callbacks->read();; return _list_->buffer[_list_->count - 1]; } size_t sl_min(struct sortedlist * _list_) { if (sl_empty(_list_)) { _list_->flag = CMC_FLAG_EMPTY; return (size_t){ 0 }; } sl_sort(_list_); _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->read) (_list_)->callbacks->read();; return _list_->buffer[0]; } size_t sl_get(struct sortedlist * _list_, size_t index) { if (sl_empty(_list_)) { _list_->flag = CMC_FLAG_EMPTY; return (size_t){ 0 }; } if (index >= _list_->count) { _list_->flag = CMC_FLAG_RANGE; return (size_t){ 0 }; } sl_sort(_list_); _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->read) (_list_)->callbacks->read();; return _list_->buffer[index]; } size_t sl_index_of(struct sortedlist * _list_, size_t value, _Bool from_start) { _list_->flag = CMC_FLAG_OK; sl_sort(_list_); if ((_list_)->callbacks && (_list_)->callbacks->read) (_list_)->callbacks->read();; if (from_start) { return sl_impl_binary_search_first(_list_, value); } return sl_impl_binary_search_last(_list_, value); } _Bool sl_contains(struct sortedlist * _list_, size_t value) { _list_->flag = CMC_FLAG_OK; if (sl_empty(_list_)) return 0; sl_sort(_list_); if ((_list_)->callbacks && (_list_)->callbacks->read) (_list_)->callbacks->read();; return sl_impl_binary_search_first(_list_, value) < _list_->count; } _Bool sl_empty(struct sortedlist * _list_) { return _list_->count == 0; } _Bool sl_full(struct sortedlist * _list_) { return _list_->count >= _list_->capacity; } size_t sl_count(struct sortedlist * _list_) { return _list_->count; } size_t sl_capacity(struct sortedlist * _list_) { return _list_->capacity; } int sl_flag(struct sortedlist * _list_) { return _list_->flag; } _Bool sl_resize(struct sortedlist * _list_, size_t capacity) { if (_list_->capacity == capacity) goto success; if (capacity < _list_->count) { _list_->flag = CMC_FLAG_INVALID; return 0; } size_t *new_buffer = _list_->alloc->realloc(_list_->buffer, sizeof(size_t) * capacity); if (!new_buffer) { _list_->flag = CMC_FLAG_ALLOC; return 0; } _list_->buffer = new_buffer; _list_->capacity = capacity; success: _list_->flag = CMC_FLAG_OK; if ((_list_)->callbacks && (_list_)->callbacks->resize) (_list_)->callbacks->resize();; return 1; } void sl_sort(struct sortedlist * _list_) { _list_->flag = CMC_FLAG_OK; if (!_list_->is_sorted && _list_->count > 1) { sl_impl_sort_quicksort (_list_->buffer, _list_->f_val->cmp, 0, _list_->count - 1); _list_->is_sorted = 1; } } struct sortedlist *sl_copy_of(struct sortedlist * _list_) { struct sortedlist *result = sl_new_custom(_list_->capacity, _list_->f_val, _list_->alloc, ((void *)0)); if (!result) { _list_->flag = CMC_FLAG_ERROR; return ((void *)0); } (result)->callbacks = _list_->callbacks; if (_list_->f_val->cpy) { for (size_t i = 0; i < _list_->count; i++) result->buffer[i] = _list_->f_val->cpy(_list_->buffer[i]); } else memcpy(result->buffer, _list_->buffer, sizeof(size_t) * _list_->count); result->count = _list_->count; _list_->flag = CMC_FLAG_OK; return result; } _Bool sl_equals(struct sortedlist * _list1_, struct sortedlist * _list2_) { if (_list1_->count != _list2_->count) return 0; sl_sort(_list1_); sl_sort(_list2_); for (size_t i = 0; i < _list1_->count; i++) { if (_list1_->f_val->cmp(_list1_->buffer[i], _list2_->buffer[i]) != 0) return 0; } return 1; } static size_t sl_impl_binary_search_first(struct sortedlist * _list_, size_t value) { if (sl_empty(_list_)) return 1; size_t L = 0; size_t R = _list_->count; while (L < R) { size_t M = L + (R - L) / 2; if (_list_->f_val->cmp(_list_->buffer[M], value) < 0) L = M + 1; else R = M; } if (_list_->f_val->cmp(_list_->buffer[L], value) == 0) return L; return _list_->count; } static size_t sl_impl_binary_search_last(struct sortedlist * _list_, size_t value) { if (sl_empty(_list_)) return 1; size_t L = 0; size_t R = _list_->count; while (L < R) { size_t M = L + (R - L) / 2; if (_list_->f_val->cmp(_list_->buffer[M], value) > 0) R = M; else L = M + 1; } if (L > 0 && _list_->f_val->cmp(_list_->buffer[L - 1], value) == 0) return L - 1; return _list_->count; } void sl_impl_sort_quicksort(size_t * array, int (*cmp)(size_t, size_t), size_t low, size_t high) { while (low < high) { if (high - low < 10) { sl_impl_sort_insertion(array, cmp, low, high); break; } else { size_t pivot = array[high]; size_t pindex = low; for (size_t i = low; i < high; i++) { if (cmp(array[i], pivot) <= 0) { size_t _tmp_ = array[i]; array[i] = array[pindex]; array[pindex] = _tmp_; pindex++; } } size_t _tmp_ = array[pindex]; array[pindex] = array[high]; array[high] = _tmp_; if (pindex - low < high - pindex) { sl_impl_sort_quicksort (array, cmp, low, pindex - 1); low = pindex + 1; } else { sl_impl_sort_quicksort (array, cmp, pindex + 1, high); high = pindex - 1; } } } } void sl_impl_sort_insertion(size_t * array, int (*cmp)(size_t, size_t), size_t low, size_t high) { for (size_t i = low + 1; i <= high; i++) { size_t _tmp_ = array[i]; size_t j = i; while (j > low && cmp(array[j - 1], _tmp_) > 0) { array[j] = array[j - 1]; j--; } array[j] = _tmp_; } } struct sortedlist_iter sl_iter_start(struct sortedlist * target) { sl_sort(target); struct sortedlist_iter iter; iter.target = target; iter.cursor = 0; iter.start = 1; iter.end = sl_empty(target); return iter; } struct sortedlist_iter sl_iter_end(struct sortedlist * target) { sl_sort(target); struct sortedlist_iter iter; iter.target = target; iter.cursor = 0; iter.start = sl_empty(target); iter.end = 1; if (!sl_empty(target)) iter.cursor = target->count - 1; return iter; } _Bool sl_iter_at_start(struct sortedlist_iter * iter) { return sl_empty(iter->target) || iter->start; } _Bool sl_iter_at_end(struct sortedlist_iter * iter) { return sl_empty(iter->target) || iter->end; } _Bool sl_iter_to_start(struct sortedlist_iter * iter) { if (!sl_empty(iter->target)) { iter->cursor = 0; iter->start = 1; iter->end = sl_empty(iter->target); return 1; } return 0; } _Bool sl_iter_to_end(struct sortedlist_iter * iter) { if (!sl_empty(iter->target)) { iter->start = sl_empty(iter->target); iter->cursor = iter->target->count - 1; iter->end = 1; return 1; } return 0; } _Bool sl_iter_next(struct sortedlist_iter * iter) { if (iter->end) return 0; if (iter->cursor + 1 == iter->target->count) { iter->end = 1; return 0; } iter->start = sl_empty(iter->target); iter->cursor++; return 1; } _Bool sl_iter_prev(struct sortedlist_iter * iter) { if (iter->start) return 0; if (iter->cursor == 0) { iter->start = 1; return 0; } iter->end = sl_empty(iter->target); iter->cursor--; return 1; } _Bool sl_iter_advance(struct sortedlist_iter * iter, size_t steps) { if (iter->end) return 0; if (iter->cursor + 1 == iter->target->count) { iter->end = 1; return 0; } if (steps == 0 || iter->cursor + steps >= iter->target->count) return 0; iter->start = sl_empty(iter->target); iter->cursor += steps; return 1; } _Bool sl_iter_rewind(struct sortedlist_iter * iter, size_t steps) { if (iter->start) return 0; if (iter->cursor == 0) { iter->start = 1; return 0; } if (steps == 0 || iter->cursor < steps) return 0; iter->end = sl_empty(iter->target); iter->cursor -= steps; return 1; } _Bool sl_iter_go_to(struct sortedlist_iter * iter, size_t index) { if (index >= iter->target->count) return 0; if (iter->cursor > index) return sl_iter_rewind(iter, iter->cursor - index); else if (iter->cursor < index) return sl_iter_advance(iter, index - iter->cursor); return 1; } size_t sl_iter_value(struct sortedlist_iter * iter) { if (sl_empty(iter->target)) return (size_t){ 0 }; return iter->target->buffer[iter->cursor]; } size_t sl_iter_index(struct sortedlist_iter * iter) { return iter->cursor; } _Bool sl_to_string(struct sortedlist * _list_, FILE * fptr) { struct sortedlist *l_ = _list_; return 0 <= fprintf(fptr, "struct %s<%s> " "at %p { " "buffer:%p, " "capacity:%" "I64u" ", " "count:%" "I64u" ", " "is_sorted:%s, " "flag:%d, " "f_val:%p, " "alloc:%p, " "callbacks:%p }", "sortedlist", "size_t", l_, l_->buffer, l_->capacity, l_->count, l_->is_sorted ? "true" : "false", l_->flag, l_->f_val, l_->alloc, (l_)->callbacks); } _Bool sl_print(struct sortedlist * _list_, FILE * fptr, const char *start, const char *separator, const char *end) { sl_sort(_list_); fprintf(fptr, "%s", start); for (size_t i = 0; i < _list_->count; i++) { if (!_list_->f_val->str(fptr, _list_->buffer[i])) return 0; if (i + 1 < _list_->count) fprintf(fptr, "%s", separator); } fprintf(fptr, "%s", end); return 1; } - - \ No newline at end of file +static size_t sl_impl_binary_search_first(struct sortedlist *_list_, size_t value); +static size_t sl_impl_binary_search_last(struct sortedlist *_list_, size_t value); +void sl_impl_sort_quicksort(size_t *array, int (*cmp)(size_t, size_t), size_t low, size_t high); +void sl_impl_sort_insertion(size_t *array, int (*cmp)(size_t, size_t), size_t low, size_t high); +struct sortedlist *sl_new(size_t capacity, struct sortedlist_fval *f_val) +{ + return sl_new_custom(capacity, f_val, ((void *)0), ((void *)0)); +} +struct sortedlist *sl_new_custom(size_t capacity, struct sortedlist_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks) +{ + ; + if (capacity < 1) + return ((void *)0); + if (!alloc) + alloc = &cmc_alloc_node_default; + struct sortedlist *_list_ = alloc->malloc(sizeof(struct sortedlist)); + if (!_list_) + return ((void *)0); + _list_->buffer = alloc->calloc(capacity, sizeof(size_t)); + if (!_list_->buffer) + { + alloc->free(_list_); + return ((void *)0); + } + _list_->capacity = capacity; + _list_->count = 0; + _list_->is_sorted = 0; + _list_->flag = CMC_FLAG_OK; + _list_->f_val = f_val; + _list_->alloc = alloc; + (_list_)->callbacks = callbacks; + return _list_; +} +void sl_clear(struct sortedlist *_list_) +{ + if (_list_->f_val->free) + { + for (size_t i = 0; i < _list_->count; i++) + _list_->f_val->free(_list_->buffer[i]); + } + memset(_list_->buffer, 0, sizeof(size_t) * _list_->capacity); + _list_->count = 0; + _list_->flag = CMC_FLAG_OK; +} +void sl_free(struct sortedlist *_list_) +{ + if (_list_->f_val->free) + { + for (size_t i = 0; i < _list_->count; i++) + _list_->f_val->free(_list_->buffer[i]); + } + _list_->alloc->free(_list_->buffer); + _list_->alloc->free(_list_); +} +void sl_customize(struct sortedlist *_list_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks) +{ + ; + if (!alloc) + _list_->alloc = &cmc_alloc_node_default; + else + _list_->alloc = alloc; + (_list_)->callbacks = callbacks; + _list_->flag = CMC_FLAG_OK; +} +_Bool sl_insert(struct sortedlist *_list_, size_t value) +{ + if (sl_full(_list_)) + { + if (!sl_resize(_list_, _list_->capacity * 2)) + return 0; + } + _list_->buffer[_list_->count++] = value; + _list_->is_sorted = 0; + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->create) + (_list_)->callbacks->create(); + ; + return 1; +} +_Bool sl_remove(struct sortedlist *_list_, size_t index) +{ + if (sl_empty(_list_)) + { + _list_->flag = CMC_FLAG_EMPTY; + return 0; + } + if (index >= _list_->count) + { + _list_->flag = CMC_FLAG_RANGE; + return 0; + } + memmove(_list_->buffer + index, _list_->buffer + index + 1, (_list_->count - index) * sizeof(size_t)); + _list_->buffer[--_list_->count] = (size_t){ 0 }; + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->delete) + (_list_)->callbacks->delete (); + ; + return 1; +} +size_t sl_max(struct sortedlist *_list_) +{ + if (sl_empty(_list_)) + { + _list_->flag = CMC_FLAG_EMPTY; + return (size_t){ 0 }; + } + sl_sort(_list_); + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->read) + (_list_)->callbacks->read(); + ; + return _list_->buffer[_list_->count - 1]; +} +size_t sl_min(struct sortedlist *_list_) +{ + if (sl_empty(_list_)) + { + _list_->flag = CMC_FLAG_EMPTY; + return (size_t){ 0 }; + } + sl_sort(_list_); + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->read) + (_list_)->callbacks->read(); + ; + return _list_->buffer[0]; +} +size_t sl_get(struct sortedlist *_list_, size_t index) +{ + if (sl_empty(_list_)) + { + _list_->flag = CMC_FLAG_EMPTY; + return (size_t){ 0 }; + } + if (index >= _list_->count) + { + _list_->flag = CMC_FLAG_RANGE; + return (size_t){ 0 }; + } + sl_sort(_list_); + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->read) + (_list_)->callbacks->read(); + ; + return _list_->buffer[index]; +} +size_t sl_index_of(struct sortedlist *_list_, size_t value, _Bool from_start) +{ + _list_->flag = CMC_FLAG_OK; + sl_sort(_list_); + if ((_list_)->callbacks && (_list_)->callbacks->read) + (_list_)->callbacks->read(); + ; + if (from_start) + { + return sl_impl_binary_search_first(_list_, value); + } + return sl_impl_binary_search_last(_list_, value); +} +_Bool sl_contains(struct sortedlist *_list_, size_t value) +{ + _list_->flag = CMC_FLAG_OK; + if (sl_empty(_list_)) + return 0; + sl_sort(_list_); + if ((_list_)->callbacks && (_list_)->callbacks->read) + (_list_)->callbacks->read(); + ; + return sl_impl_binary_search_first(_list_, value) < _list_->count; +} +_Bool sl_empty(struct sortedlist *_list_) +{ + return _list_->count == 0; +} +_Bool sl_full(struct sortedlist *_list_) +{ + return _list_->count >= _list_->capacity; +} +size_t sl_count(struct sortedlist *_list_) +{ + return _list_->count; +} +size_t sl_capacity(struct sortedlist *_list_) +{ + return _list_->capacity; +} +int sl_flag(struct sortedlist *_list_) +{ + return _list_->flag; +} +_Bool sl_resize(struct sortedlist *_list_, size_t capacity) +{ + if (_list_->capacity == capacity) + goto success; + if (capacity < _list_->count) + { + _list_->flag = CMC_FLAG_INVALID; + return 0; + } + size_t *new_buffer = _list_->alloc->realloc(_list_->buffer, sizeof(size_t) * capacity); + if (!new_buffer) + { + _list_->flag = CMC_FLAG_ALLOC; + return 0; + } + _list_->buffer = new_buffer; + _list_->capacity = capacity; +success: + _list_->flag = CMC_FLAG_OK; + if ((_list_)->callbacks && (_list_)->callbacks->resize) + (_list_)->callbacks->resize(); + ; + return 1; +} +void sl_sort(struct sortedlist *_list_) +{ + _list_->flag = CMC_FLAG_OK; + if (!_list_->is_sorted && _list_->count > 1) + { + sl_impl_sort_quicksort(_list_->buffer, _list_->f_val->cmp, 0, _list_->count - 1); + _list_->is_sorted = 1; + } +} +struct sortedlist *sl_copy_of(struct sortedlist *_list_) +{ + struct sortedlist *result = sl_new_custom(_list_->capacity, _list_->f_val, _list_->alloc, ((void *)0)); + if (!result) + { + _list_->flag = CMC_FLAG_ERROR; + return ((void *)0); + } + (result)->callbacks = _list_->callbacks; + if (_list_->f_val->cpy) + { + for (size_t i = 0; i < _list_->count; i++) + result->buffer[i] = _list_->f_val->cpy(_list_->buffer[i]); + } + else + memcpy(result->buffer, _list_->buffer, sizeof(size_t) * _list_->count); + result->count = _list_->count; + _list_->flag = CMC_FLAG_OK; + return result; +} +_Bool sl_equals(struct sortedlist *_list1_, struct sortedlist *_list2_) +{ + if (_list1_->count != _list2_->count) + return 0; + sl_sort(_list1_); + sl_sort(_list2_); + for (size_t i = 0; i < _list1_->count; i++) + { + if (_list1_->f_val->cmp(_list1_->buffer[i], _list2_->buffer[i]) != 0) + return 0; + } + return 1; +} +static size_t sl_impl_binary_search_first(struct sortedlist *_list_, size_t value) +{ + if (sl_empty(_list_)) + return 1; + size_t L = 0; + size_t R = _list_->count; + while (L < R) + { + size_t M = L + (R - L) / 2; + if (_list_->f_val->cmp(_list_->buffer[M], value) < 0) + L = M + 1; + else + R = M; + } + if (_list_->f_val->cmp(_list_->buffer[L], value) == 0) + return L; + return _list_->count; +} +static size_t sl_impl_binary_search_last(struct sortedlist *_list_, size_t value) +{ + if (sl_empty(_list_)) + return 1; + size_t L = 0; + size_t R = _list_->count; + while (L < R) + { + size_t M = L + (R - L) / 2; + if (_list_->f_val->cmp(_list_->buffer[M], value) > 0) + R = M; + else + L = M + 1; + } + if (L > 0 && _list_->f_val->cmp(_list_->buffer[L - 1], value) == 0) + return L - 1; + return _list_->count; +} +void sl_impl_sort_quicksort(size_t *array, int (*cmp)(size_t, size_t), size_t low, size_t high) +{ + while (low < high) + { + if (high - low < 10) + { + sl_impl_sort_insertion(array, cmp, low, high); + break; + } + else + { + size_t pivot = array[high]; + size_t pindex = low; + for (size_t i = low; i < high; i++) + { + if (cmp(array[i], pivot) <= 0) + { + size_t _tmp_ = array[i]; + array[i] = array[pindex]; + array[pindex] = _tmp_; + pindex++; + } + } + size_t _tmp_ = array[pindex]; + array[pindex] = array[high]; + array[high] = _tmp_; + if (pindex - low < high - pindex) + { + sl_impl_sort_quicksort(array, cmp, low, pindex - 1); + low = pindex + 1; + } + else + { + sl_impl_sort_quicksort(array, cmp, pindex + 1, high); + high = pindex - 1; + } + } + } +} +void sl_impl_sort_insertion(size_t *array, int (*cmp)(size_t, size_t), size_t low, size_t high) +{ + for (size_t i = low + 1; i <= high; i++) + { + size_t _tmp_ = array[i]; + size_t j = i; + while (j > low && cmp(array[j - 1], _tmp_) > 0) + { + array[j] = array[j - 1]; + j--; + } + array[j] = _tmp_; + } +} +struct sortedlist_iter sl_iter_start(struct sortedlist *target) +{ + sl_sort(target); + struct sortedlist_iter iter; + iter.target = target; + iter.cursor = 0; + iter.start = 1; + iter.end = sl_empty(target); + return iter; +} +struct sortedlist_iter sl_iter_end(struct sortedlist *target) +{ + sl_sort(target); + struct sortedlist_iter iter; + iter.target = target; + iter.cursor = 0; + iter.start = sl_empty(target); + iter.end = 1; + if (!sl_empty(target)) + iter.cursor = target->count - 1; + return iter; +} +_Bool sl_iter_at_start(struct sortedlist_iter *iter) +{ + return sl_empty(iter->target) || iter->start; +} +_Bool sl_iter_at_end(struct sortedlist_iter *iter) +{ + return sl_empty(iter->target) || iter->end; +} +_Bool sl_iter_to_start(struct sortedlist_iter *iter) +{ + if (!sl_empty(iter->target)) + { + iter->cursor = 0; + iter->start = 1; + iter->end = sl_empty(iter->target); + return 1; + } + return 0; +} +_Bool sl_iter_to_end(struct sortedlist_iter *iter) +{ + if (!sl_empty(iter->target)) + { + iter->start = sl_empty(iter->target); + iter->cursor = iter->target->count - 1; + iter->end = 1; + return 1; + } + return 0; +} +_Bool sl_iter_next(struct sortedlist_iter *iter) +{ + if (iter->end) + return 0; + if (iter->cursor + 1 == iter->target->count) + { + iter->end = 1; + return 0; + } + iter->start = sl_empty(iter->target); + iter->cursor++; + return 1; +} +_Bool sl_iter_prev(struct sortedlist_iter *iter) +{ + if (iter->start) + return 0; + if (iter->cursor == 0) + { + iter->start = 1; + return 0; + } + iter->end = sl_empty(iter->target); + iter->cursor--; + return 1; +} +_Bool sl_iter_advance(struct sortedlist_iter *iter, size_t steps) +{ + if (iter->end) + return 0; + if (iter->cursor + 1 == iter->target->count) + { + iter->end = 1; + return 0; + } + if (steps == 0 || iter->cursor + steps >= iter->target->count) + return 0; + iter->start = sl_empty(iter->target); + iter->cursor += steps; + return 1; +} +_Bool sl_iter_rewind(struct sortedlist_iter *iter, size_t steps) +{ + if (iter->start) + return 0; + if (iter->cursor == 0) + { + iter->start = 1; + return 0; + } + if (steps == 0 || iter->cursor < steps) + return 0; + iter->end = sl_empty(iter->target); + iter->cursor -= steps; + return 1; +} +_Bool sl_iter_go_to(struct sortedlist_iter *iter, size_t index) +{ + if (index >= iter->target->count) + return 0; + if (iter->cursor > index) + return sl_iter_rewind(iter, iter->cursor - index); + else if (iter->cursor < index) + return sl_iter_advance(iter, index - iter->cursor); + return 1; +} +size_t sl_iter_value(struct sortedlist_iter *iter) +{ + if (sl_empty(iter->target)) + return (size_t){ 0 }; + return iter->target->buffer[iter->cursor]; +} +size_t sl_iter_index(struct sortedlist_iter *iter) +{ + return iter->cursor; +} +_Bool sl_to_string(struct sortedlist *_list_, FILE *fptr) +{ + struct sortedlist *l_ = _list_; + return 0 <= fprintf(fptr, + "struct %s<%s> " + "at %p { " + "buffer:%p, " + "capacity:%" + "I64u" + ", " + "count:%" + "I64u" + ", " + "is_sorted:%s, " + "flag:%d, " + "f_val:%p, " + "alloc:%p, " + "callbacks:%p }", + "sortedlist", "size_t", l_, l_->buffer, l_->capacity, l_->count, + l_->is_sorted ? "true" : "false", l_->flag, l_->f_val, l_->alloc, (l_)->callbacks); +} +_Bool sl_print(struct sortedlist *_list_, FILE *fptr, const char *start, const char *separator, const char *end) +{ + sl_sort(_list_); + fprintf(fptr, "%s", start); + for (size_t i = 0; i < _list_->count; i++) + { + if (!_list_->f_val->str(fptr, _list_->buffer[i])) + return 0; + if (i + 1 < _list_->count) + fprintf(fptr, "%s", separator); + } + fprintf(fptr, "%s", end); + return 1; +} diff --git a/tests/src/tst_cmc_stack.c b/tests/src/tst_cmc_stack.c index 16f8bf8..e6030a3 100644 --- a/tests/src/tst_cmc_stack.c +++ b/tests/src/tst_cmc_stack.c @@ -1,7 +1,367 @@ - #include "tst_cmc_stack.h" +#include "tst_cmc_stack.h" - - struct stack *s_new(size_t capacity, struct stack_fval * f_val) { return s_new_custom(capacity, f_val, ((void *)0), ((void *)0)); } struct stack *s_new_custom(size_t capacity, struct stack_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (capacity < 1) return ((void *)0); if (!f_val) return ((void *)0); if (!alloc) alloc = &cmc_alloc_node_default; struct stack *_stack_ = alloc->malloc(sizeof(struct stack)); if (!_stack_) return ((void *)0); _stack_->buffer = alloc->calloc(capacity, sizeof(size_t)); if (!_stack_->buffer) { alloc->free(_stack_); return ((void *)0); } _stack_->capacity = capacity; _stack_->count = 0; _stack_->flag = CMC_FLAG_OK; _stack_->f_val = f_val; _stack_->alloc = alloc; (_stack_)->callbacks = callbacks; return _stack_; } void s_clear(struct stack * _stack_) { if (_stack_->f_val->free) { for (size_t i = 0; i < _stack_->count; i++) _stack_->f_val->free(_stack_->buffer[i]); } memset(_stack_->buffer, 0, sizeof(size_t) * _stack_->capacity); _stack_->count = 0; _stack_->flag = CMC_FLAG_OK; } void s_free(struct stack * _stack_) { if (_stack_->f_val->free) { for (size_t i = 0; i < _stack_->count; i++) _stack_->f_val->free(_stack_->buffer[i]); } _stack_->alloc->free(_stack_->buffer); _stack_->alloc->free(_stack_); } void s_customize(struct stack * _stack_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (!alloc) _stack_->alloc = &cmc_alloc_node_default; else _stack_->alloc = alloc; (_stack_)->callbacks = callbacks; _stack_->flag = CMC_FLAG_OK; } _Bool s_push(struct stack * _stack_, size_t value) { if (s_full(_stack_)) { if (!s_resize(_stack_, _stack_->capacity * 2)) return 0; } _stack_->buffer[_stack_->count++] = value; _stack_->flag = CMC_FLAG_OK; if ((_stack_)->callbacks && (_stack_)->callbacks->create) (_stack_)->callbacks->create();; return 1; } _Bool s_pop(struct stack * _stack_) { if (s_empty(_stack_)) { _stack_->flag = CMC_FLAG_EMPTY; return 0; } _stack_->buffer[--_stack_->count] = (size_t){ 0 }; _stack_->flag = CMC_FLAG_OK; if ((_stack_)->callbacks && (_stack_)->callbacks->delete) (_stack_)->callbacks->delete();; return 1; } size_t s_top(struct stack * _stack_) { if (s_empty(_stack_)) { _stack_->flag = CMC_FLAG_EMPTY; return (size_t){ 0 }; } _stack_->flag = CMC_FLAG_OK; if ((_stack_)->callbacks && (_stack_)->callbacks->read) (_stack_)->callbacks->read();; return _stack_->buffer[_stack_->count - 1]; } _Bool s_contains(struct stack * _stack_, size_t value) { _stack_->flag = CMC_FLAG_OK; _Bool result = 0; for (size_t i = 0; i < _stack_->count; i++) { if (_stack_->f_val->cmp(_stack_->buffer[i], value) == 0) { result = 1; break; } } if ((_stack_)->callbacks && (_stack_)->callbacks->read) (_stack_)->callbacks->read();; return result; } _Bool s_empty(struct stack * _stack_) { return _stack_->count == 0; } _Bool s_full(struct stack * _stack_) { return _stack_->count >= _stack_->capacity; } size_t s_count(struct stack * _stack_) { return _stack_->count; } size_t s_capacity(struct stack * _stack_) { return _stack_->capacity; } int s_flag(struct stack * _stack_) { return _stack_->flag; } _Bool s_resize(struct stack * _stack_, size_t capacity) { if (_stack_->capacity == capacity) goto success; if (capacity < _stack_->count) { _stack_->flag = CMC_FLAG_INVALID; return 0; } size_t *new_buffer = _stack_->alloc->realloc(_stack_->buffer, sizeof(size_t) * capacity); if (!new_buffer) { _stack_->flag = CMC_FLAG_ALLOC; return 0; } _stack_->buffer = new_buffer; _stack_->capacity = capacity; success: _stack_->flag = CMC_FLAG_OK; if ((_stack_)->callbacks && (_stack_)->callbacks->resize) (_stack_)->callbacks->resize();; return 1; } struct stack *s_copy_of(struct stack * _stack_) { struct stack *result = s_new_custom(_stack_->capacity, _stack_->f_val, _stack_->alloc, ((void *)0)); if (!result) { _stack_->flag = CMC_FLAG_ERROR; return ((void *)0); } (result)->callbacks = _stack_->callbacks; if (_stack_->f_val->cpy) { for (size_t i = 0; i < _stack_->count; i++) result->buffer[i] = _stack_->f_val->cpy(_stack_->buffer[i]); } else memcpy(result->buffer, _stack_->buffer, sizeof(size_t) * _stack_->count); result->count = _stack_->count; _stack_->flag = CMC_FLAG_OK; return result; } _Bool s_equals(struct stack * _stack1_, struct stack * _stack2_) { _stack1_->flag = CMC_FLAG_OK; _stack2_->flag = CMC_FLAG_OK; if (_stack1_->count != _stack2_->count) return 0; for (size_t i = 0; i < _stack1_->count; i++) { if (_stack1_->f_val->cmp(_stack1_->buffer[i], _stack2_->buffer[i]) != 0) return 0; } return 1; } struct stack_iter s_iter_start(struct stack * target) { struct stack_iter iter; iter.target = target; iter.cursor = 0; iter.start = 1; iter.end = s_empty(target); if (!s_empty(target)) iter.cursor = target->count - 1; return iter; } struct stack_iter s_iter_end(struct stack * target) { struct stack_iter iter; iter.target = target; iter.cursor = 0; iter.start = s_empty(target); iter.end = 1; return iter; } _Bool s_iter_at_start(struct stack_iter * iter) { return s_empty(iter->target) || iter->start; } _Bool s_iter_at_end(struct stack_iter * iter) { return s_empty(iter->target) || iter->end; } _Bool s_iter_to_start(struct stack_iter * iter) { if (!s_empty(iter->target)) { iter->cursor = iter->target->count - 1; iter->start = 1; iter->end = s_empty(iter->target); return 1; } return 0; } _Bool s_iter_to_end(struct stack_iter * iter) { if (!s_empty(iter->target)) { iter->cursor = 0; iter->start = s_empty(iter->target); iter->end = 1; return 1; } return 0; } _Bool s_iter_next(struct stack_iter * iter) { if (iter->end) return 0; if (iter->cursor == 0) { iter->end = 1; return 0; } iter->start = s_empty(iter->target); iter->cursor--; return 1; } _Bool s_iter_prev(struct stack_iter * iter) { if (iter->start) return 0; if (iter->cursor + 1 == iter->target->count) { iter->start = 1; return 0; } iter->end = s_empty(iter->target); iter->cursor++; return 1; } _Bool s_iter_advance(struct stack_iter * iter, size_t steps) { if (iter->end) return 0; if (iter->cursor == 0) { iter->end = 1; return 0; } if (steps == 0 || iter->cursor < steps) return 0; iter->start = s_empty(iter->target); iter->cursor -= steps; return 1; } _Bool s_iter_rewind(struct stack_iter * iter, size_t steps) { if (iter->start) return 0; if (iter->cursor + 1 == iter->target->count) { iter->start = 1; return 0; } if (steps == 0 || iter->cursor + steps >= iter->target->count) return 0; iter->end = s_empty(iter->target); iter->cursor += steps; return 1; } _Bool s_iter_go_to(struct stack_iter * iter, size_t index) { if (index >= iter->target->count) return 0; if (iter->cursor > index) return s_iter_advance(iter, iter->cursor - index); else if (iter->cursor < index) return s_iter_rewind(iter, index - iter->cursor); return 1; } size_t s_iter_value(struct stack_iter * iter) { if (s_empty(iter->target)) return (size_t){ 0 }; return iter->target->buffer[iter->cursor]; } size_t *s_iter_rvalue(struct stack_iter * iter) { if (s_empty(iter->target)) return ((void *)0); return &(iter->target->buffer[iter->cursor]); } size_t s_iter_index(struct stack_iter * iter) { if (s_empty(iter->target)) return 0; return iter->target->count - 1 - iter->cursor; } _Bool s_to_string(struct stack * _stack_, FILE * fptr) { struct stack *s_ = _stack_; return 0 <= fprintf(fptr, "struct %s<%s> " "at %p { " "buffer:%p, " "capacity:%" "I64u" ", " "count:%" "I64u" ", " "flag:%d, " "f_val:%p, " "alloc:%p, " "callbacks:%p }", "stack", "size_t", s_, s_->buffer, s_->capacity, s_->count, s_->flag, s_->f_val, s_->alloc, (s_)->callbacks); } _Bool s_print(struct stack * _stack_, FILE * fptr, const char *start, const char *separator, const char *end) { fprintf(fptr, "%s", start); for (size_t i = _stack_->count; i > 0; i--) { if (!_stack_->f_val->str(fptr, _stack_->buffer[i - 1])) return 0; if (i - 1 != 0) fprintf(fptr, "%s", separator); } fprintf(fptr, "%s", end); return 1; } - - \ No newline at end of file +struct stack *s_new(size_t capacity, struct stack_fval *f_val) +{ + return s_new_custom(capacity, f_val, ((void *)0), ((void *)0)); +} +struct stack *s_new_custom(size_t capacity, struct stack_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks) +{ + ; + if (capacity < 1) + return ((void *)0); + if (!f_val) + return ((void *)0); + if (!alloc) + alloc = &cmc_alloc_node_default; + struct stack *_stack_ = alloc->malloc(sizeof(struct stack)); + if (!_stack_) + return ((void *)0); + _stack_->buffer = alloc->calloc(capacity, sizeof(size_t)); + if (!_stack_->buffer) + { + alloc->free(_stack_); + return ((void *)0); + } + _stack_->capacity = capacity; + _stack_->count = 0; + _stack_->flag = CMC_FLAG_OK; + _stack_->f_val = f_val; + _stack_->alloc = alloc; + (_stack_)->callbacks = callbacks; + return _stack_; +} +void s_clear(struct stack *_stack_) +{ + if (_stack_->f_val->free) + { + for (size_t i = 0; i < _stack_->count; i++) + _stack_->f_val->free(_stack_->buffer[i]); + } + memset(_stack_->buffer, 0, sizeof(size_t) * _stack_->capacity); + _stack_->count = 0; + _stack_->flag = CMC_FLAG_OK; +} +void s_free(struct stack *_stack_) +{ + if (_stack_->f_val->free) + { + for (size_t i = 0; i < _stack_->count; i++) + _stack_->f_val->free(_stack_->buffer[i]); + } + _stack_->alloc->free(_stack_->buffer); + _stack_->alloc->free(_stack_); +} +void s_customize(struct stack *_stack_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks) +{ + ; + if (!alloc) + _stack_->alloc = &cmc_alloc_node_default; + else + _stack_->alloc = alloc; + (_stack_)->callbacks = callbacks; + _stack_->flag = CMC_FLAG_OK; +} +_Bool s_push(struct stack *_stack_, size_t value) +{ + if (s_full(_stack_)) + { + if (!s_resize(_stack_, _stack_->capacity * 2)) + return 0; + } + _stack_->buffer[_stack_->count++] = value; + _stack_->flag = CMC_FLAG_OK; + if ((_stack_)->callbacks && (_stack_)->callbacks->create) + (_stack_)->callbacks->create(); + ; + return 1; +} +_Bool s_pop(struct stack *_stack_) +{ + if (s_empty(_stack_)) + { + _stack_->flag = CMC_FLAG_EMPTY; + return 0; + } + _stack_->buffer[--_stack_->count] = (size_t){ 0 }; + _stack_->flag = CMC_FLAG_OK; + if ((_stack_)->callbacks && (_stack_)->callbacks->delete) + (_stack_)->callbacks->delete (); + ; + return 1; +} +size_t s_top(struct stack *_stack_) +{ + if (s_empty(_stack_)) + { + _stack_->flag = CMC_FLAG_EMPTY; + return (size_t){ 0 }; + } + _stack_->flag = CMC_FLAG_OK; + if ((_stack_)->callbacks && (_stack_)->callbacks->read) + (_stack_)->callbacks->read(); + ; + return _stack_->buffer[_stack_->count - 1]; +} +_Bool s_contains(struct stack *_stack_, size_t value) +{ + _stack_->flag = CMC_FLAG_OK; + _Bool result = 0; + for (size_t i = 0; i < _stack_->count; i++) + { + if (_stack_->f_val->cmp(_stack_->buffer[i], value) == 0) + { + result = 1; + break; + } + } + if ((_stack_)->callbacks && (_stack_)->callbacks->read) + (_stack_)->callbacks->read(); + ; + return result; +} +_Bool s_empty(struct stack *_stack_) +{ + return _stack_->count == 0; +} +_Bool s_full(struct stack *_stack_) +{ + return _stack_->count >= _stack_->capacity; +} +size_t s_count(struct stack *_stack_) +{ + return _stack_->count; +} +size_t s_capacity(struct stack *_stack_) +{ + return _stack_->capacity; +} +int s_flag(struct stack *_stack_) +{ + return _stack_->flag; +} +_Bool s_resize(struct stack *_stack_, size_t capacity) +{ + if (_stack_->capacity == capacity) + goto success; + if (capacity < _stack_->count) + { + _stack_->flag = CMC_FLAG_INVALID; + return 0; + } + size_t *new_buffer = _stack_->alloc->realloc(_stack_->buffer, sizeof(size_t) * capacity); + if (!new_buffer) + { + _stack_->flag = CMC_FLAG_ALLOC; + return 0; + } + _stack_->buffer = new_buffer; + _stack_->capacity = capacity; +success: + _stack_->flag = CMC_FLAG_OK; + if ((_stack_)->callbacks && (_stack_)->callbacks->resize) + (_stack_)->callbacks->resize(); + ; + return 1; +} +struct stack *s_copy_of(struct stack *_stack_) +{ + struct stack *result = s_new_custom(_stack_->capacity, _stack_->f_val, _stack_->alloc, ((void *)0)); + if (!result) + { + _stack_->flag = CMC_FLAG_ERROR; + return ((void *)0); + } + (result)->callbacks = _stack_->callbacks; + if (_stack_->f_val->cpy) + { + for (size_t i = 0; i < _stack_->count; i++) + result->buffer[i] = _stack_->f_val->cpy(_stack_->buffer[i]); + } + else + memcpy(result->buffer, _stack_->buffer, sizeof(size_t) * _stack_->count); + result->count = _stack_->count; + _stack_->flag = CMC_FLAG_OK; + return result; +} +_Bool s_equals(struct stack *_stack1_, struct stack *_stack2_) +{ + _stack1_->flag = CMC_FLAG_OK; + _stack2_->flag = CMC_FLAG_OK; + if (_stack1_->count != _stack2_->count) + return 0; + for (size_t i = 0; i < _stack1_->count; i++) + { + if (_stack1_->f_val->cmp(_stack1_->buffer[i], _stack2_->buffer[i]) != 0) + return 0; + } + return 1; +} +struct stack_iter s_iter_start(struct stack *target) +{ + struct stack_iter iter; + iter.target = target; + iter.cursor = 0; + iter.start = 1; + iter.end = s_empty(target); + if (!s_empty(target)) + iter.cursor = target->count - 1; + return iter; +} +struct stack_iter s_iter_end(struct stack *target) +{ + struct stack_iter iter; + iter.target = target; + iter.cursor = 0; + iter.start = s_empty(target); + iter.end = 1; + return iter; +} +_Bool s_iter_at_start(struct stack_iter *iter) +{ + return s_empty(iter->target) || iter->start; +} +_Bool s_iter_at_end(struct stack_iter *iter) +{ + return s_empty(iter->target) || iter->end; +} +_Bool s_iter_to_start(struct stack_iter *iter) +{ + if (!s_empty(iter->target)) + { + iter->cursor = iter->target->count - 1; + iter->start = 1; + iter->end = s_empty(iter->target); + return 1; + } + return 0; +} +_Bool s_iter_to_end(struct stack_iter *iter) +{ + if (!s_empty(iter->target)) + { + iter->cursor = 0; + iter->start = s_empty(iter->target); + iter->end = 1; + return 1; + } + return 0; +} +_Bool s_iter_next(struct stack_iter *iter) +{ + if (iter->end) + return 0; + if (iter->cursor == 0) + { + iter->end = 1; + return 0; + } + iter->start = s_empty(iter->target); + iter->cursor--; + return 1; +} +_Bool s_iter_prev(struct stack_iter *iter) +{ + if (iter->start) + return 0; + if (iter->cursor + 1 == iter->target->count) + { + iter->start = 1; + return 0; + } + iter->end = s_empty(iter->target); + iter->cursor++; + return 1; +} +_Bool s_iter_advance(struct stack_iter *iter, size_t steps) +{ + if (iter->end) + return 0; + if (iter->cursor == 0) + { + iter->end = 1; + return 0; + } + if (steps == 0 || iter->cursor < steps) + return 0; + iter->start = s_empty(iter->target); + iter->cursor -= steps; + return 1; +} +_Bool s_iter_rewind(struct stack_iter *iter, size_t steps) +{ + if (iter->start) + return 0; + if (iter->cursor + 1 == iter->target->count) + { + iter->start = 1; + return 0; + } + if (steps == 0 || iter->cursor + steps >= iter->target->count) + return 0; + iter->end = s_empty(iter->target); + iter->cursor += steps; + return 1; +} +_Bool s_iter_go_to(struct stack_iter *iter, size_t index) +{ + if (index >= iter->target->count) + return 0; + if (iter->cursor > index) + return s_iter_advance(iter, iter->cursor - index); + else if (iter->cursor < index) + return s_iter_rewind(iter, index - iter->cursor); + return 1; +} +size_t s_iter_value(struct stack_iter *iter) +{ + if (s_empty(iter->target)) + return (size_t){ 0 }; + return iter->target->buffer[iter->cursor]; +} +size_t *s_iter_rvalue(struct stack_iter *iter) +{ + if (s_empty(iter->target)) + return ((void *)0); + return &(iter->target->buffer[iter->cursor]); +} +size_t s_iter_index(struct stack_iter *iter) +{ + if (s_empty(iter->target)) + return 0; + return iter->target->count - 1 - iter->cursor; +} +_Bool s_to_string(struct stack *_stack_, FILE *fptr) +{ + struct stack *s_ = _stack_; + return 0 <= fprintf(fptr, + "struct %s<%s> " + "at %p { " + "buffer:%p, " + "capacity:%" + "I64u" + ", " + "count:%" + "I64u" + ", " + "flag:%d, " + "f_val:%p, " + "alloc:%p, " + "callbacks:%p }", + "stack", "size_t", s_, s_->buffer, s_->capacity, s_->count, s_->flag, s_->f_val, s_->alloc, + (s_)->callbacks); +} +_Bool s_print(struct stack *_stack_, FILE *fptr, const char *start, const char *separator, const char *end) +{ + fprintf(fptr, "%s", start); + for (size_t i = _stack_->count; i > 0; i--) + { + if (!_stack_->f_val->str(fptr, _stack_->buffer[i - 1])) + return 0; + if (i - 1 != 0) + fprintf(fptr, "%s", separator); + } + fprintf(fptr, "%s", end); + return 1; +} diff --git a/tests/src/tst_cmc_treemap.c b/tests/src/tst_cmc_treemap.c index b6e2f5c..ed28e22 100644 --- a/tests/src/tst_cmc_treemap.c +++ b/tests/src/tst_cmc_treemap.c @@ -1,7 +1,852 @@ - #include "tst_cmc_treemap.h" +#include "tst_cmc_treemap.h" - - static struct treemap_node * tm_impl_new_node(struct treemap * _map_, size_t key, size_t value); static struct treemap_node * tm_impl_get_node(struct treemap * _map_, size_t key); static unsigned char tm_impl_h(struct treemap_node * node); static unsigned char tm_impl_hupdate(struct treemap_node * node); static void tm_impl_rotate_right(struct treemap_node * *Z); static void tm_impl_rotate_left(struct treemap_node * *Z); static void tm_impl_rebalance(struct treemap * _map_, struct treemap_node * node); struct treemap *tm_new(struct treemap_fkey * f_key, struct treemap_fval * f_val) { return tm_new_custom(f_key, f_val, ((void *)0), ((void *)0)); } struct treemap *tm_new_custom(struct treemap_fkey * f_key, struct treemap_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (!f_key || !f_val) return ((void *)0); if (!alloc) alloc = &cmc_alloc_node_default; struct treemap *_map_ = alloc->malloc(sizeof(struct treemap)); if (!_map_) return ((void *)0); _map_->count = 0; _map_->root = ((void *)0); _map_->flag = CMC_FLAG_OK; _map_->f_key = f_key; _map_->f_val = f_val; _map_->alloc = alloc; (_map_)->callbacks = callbacks; return _map_; } void tm_clear(struct treemap * _map_) { struct treemap_node *scan = _map_->root; struct treemap_node *up = ((void *)0); while (scan != ((void *)0)) { if (scan->left != ((void *)0)) { struct treemap_node *left = scan->left; scan->left = up; up = scan; scan = left; } else if (scan->right != ((void *)0)) { struct treemap_node *right = scan->right; scan->left = up; scan->right = ((void *)0); up = scan; scan = right; } else { if (up == ((void *)0)) { if (_map_->f_key->free) _map_->f_key->free(scan->key); if (_map_->f_val->free) _map_->f_val->free(scan->value); _map_->alloc->free(scan); scan = ((void *)0); } while (up != ((void *)0)) { if (_map_->f_key->free) _map_->f_key->free(scan->key); if (_map_->f_val->free) _map_->f_val->free(scan->value); _map_->alloc->free(scan); if (up->right != ((void *)0)) { scan = up->right; up->right = ((void *)0); break; } else { scan = up; up = up->left; } } } } _map_->count = 0; _map_->root = ((void *)0); _map_->flag = CMC_FLAG_OK; } void tm_free(struct treemap * _map_) { tm_clear(_map_); _map_->alloc->free(_map_); } void tm_customize(struct treemap * _map_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (!alloc) _map_->alloc = &cmc_alloc_node_default; else _map_->alloc = alloc; (_map_)->callbacks = callbacks; _map_->flag = CMC_FLAG_OK; } _Bool tm_insert(struct treemap * _map_, size_t key, size_t value) { if (tm_empty(_map_)) { _map_->root = tm_impl_new_node(_map_, key, value); if (!_map_->root) { _map_->flag = CMC_FLAG_ALLOC; return 0; } } else { struct treemap_node *scan = _map_->root; struct treemap_node *parent = scan; while (scan != ((void *)0)) { parent = scan; if (_map_->f_key->cmp(scan->key, key) > 0) scan = scan->left; else if (_map_->f_key->cmp(scan->key, key) < 0) scan = scan->right; else { _map_->flag = CMC_FLAG_DUPLICATE; return 0; } } struct treemap_node * node; if (_map_->f_key->cmp(parent->key, key) > 0) { parent->left = tm_impl_new_node(_map_, key, value); if (!parent->left) { _map_->flag = CMC_FLAG_ALLOC; return 0; } parent->left->parent = parent; node = parent->left; } else { parent->right = tm_impl_new_node(_map_, key, value); if (!parent->right) { _map_->flag = CMC_FLAG_ALLOC; return 0; } parent->right->parent = parent; node = parent->right; } tm_impl_rebalance(_map_, node); } _map_->count++; _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->create) (_map_)->callbacks->create();; return 1; } _Bool tm_update(struct treemap * _map_, size_t key, size_t new_value, size_t * old_value) { struct treemap_node *node = tm_impl_get_node(_map_, key); if (!node) { _map_->flag = CMC_FLAG_NOT_FOUND; return 0; } if (old_value) *old_value = node->value; node->value = new_value; _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->update) (_map_)->callbacks->update();; return 1; } _Bool tm_remove(struct treemap * _map_, size_t key, size_t * out_value) { if (tm_empty(_map_)) { _map_->flag = CMC_FLAG_EMPTY; return 0; } struct treemap_node *node = tm_impl_get_node(_map_, key); if (!node) { _map_->flag = CMC_FLAG_NOT_FOUND; return 0; } if (out_value) *out_value = node->value; struct treemap_node *temp = ((void *)0), *unbalanced = ((void *)0); _Bool is_root = node->parent == ((void *)0); if (node->left == ((void *)0) && node->right == ((void *)0)) { if (is_root) _map_->root = ((void *)0); else { unbalanced = node->parent; if (node->parent->right == node) node->parent->right = ((void *)0); else node->parent->left = ((void *)0); } _map_->alloc->free(node); } else if (node->left == ((void *)0)) { if (is_root) { _map_->root = node->right; _map_->root->parent = ((void *)0); } else { unbalanced = node->parent; node->right->parent = node->parent; if (node->parent->right == node) node->parent->right = node->right; else node->parent->left = node->right; } _map_->alloc->free(node); } else if (node->right == ((void *)0)) { if (is_root) { _map_->root = node->left; _map_->root->parent = ((void *)0); } else { unbalanced = node->parent; node->left->parent = node->parent; if (node->parent->right == node) node->parent->right = node->left; else node->parent->left = node->left; } _map_->alloc->free(node); } else { temp = node->right; while (temp->left != ((void *)0)) temp = temp->left; size_t temp_key = temp->key; size_t temp_val = temp->value; unbalanced = temp->parent; if (temp->left == ((void *)0) && temp->right == ((void *)0)) { if (temp->parent->right == temp) temp->parent->right = ((void *)0); else temp->parent->left = ((void *)0); } else if (temp->left == ((void *)0)) { temp->right->parent = temp->parent; if (temp->parent->right == temp) temp->parent->right = temp->right; else temp->parent->left = temp->right; } else if (temp->right == ((void *)0)) { temp->left->parent = temp->parent; if (temp->parent->right == temp) temp->parent->right = temp->left; else temp->parent->left = temp->left; } _map_->alloc->free(temp); node->key = temp_key; node->value = temp_val; } if (unbalanced != ((void *)0)) tm_impl_rebalance(_map_, unbalanced); if (_map_->count == 0) _map_->root = ((void *)0); _map_->count--; _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->delete) (_map_)->callbacks->delete();; return 1; } _Bool tm_max(struct treemap * _map_, size_t * key, size_t * value) { if (tm_empty(_map_)) { _map_->flag = CMC_FLAG_EMPTY; return 0; } struct treemap_node *scan = _map_->root; while (scan->right != ((void *)0)) scan = scan->right; if (key) *key = scan->key; if (value) *value = scan->value; _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->read) (_map_)->callbacks->read();; return 1; } _Bool tm_min(struct treemap * _map_, size_t * key, size_t * value) { if (tm_empty(_map_)) { _map_->flag = CMC_FLAG_EMPTY; return 0; } struct treemap_node *scan = _map_->root; while (scan->left != ((void *)0)) scan = scan->left; if (key) *key = scan->key; if (value) *value = scan->value; _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->read) (_map_)->callbacks->read();; return 1; } size_t tm_get(struct treemap * _map_, size_t key) { if (tm_empty(_map_)) { _map_->flag = CMC_FLAG_EMPTY; return (size_t){ 0 }; } struct treemap_node *node = tm_impl_get_node(_map_, key); if (!node) { _map_->flag = CMC_FLAG_NOT_FOUND; return (size_t){ 0 }; } _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->read) (_map_)->callbacks->read();; return node->value; } size_t *tm_get_ref(struct treemap * _map_, size_t key) { if (tm_empty(_map_)) { _map_->flag = CMC_FLAG_EMPTY; return ((void *)0); } struct treemap_node *node = tm_impl_get_node(_map_, key); if (!node) { _map_->flag = CMC_FLAG_NOT_FOUND; return ((void *)0); } _map_->flag = CMC_FLAG_OK; if ((_map_)->callbacks && (_map_)->callbacks->read) (_map_)->callbacks->read();; return &(node->value); } _Bool tm_contains(struct treemap * _map_, size_t key) { _Bool result = tm_impl_get_node(_map_, key) != ((void *)0); if ((_map_)->callbacks && (_map_)->callbacks->read) (_map_)->callbacks->read();; return result; } _Bool tm_empty(struct treemap * _map_) { return _map_->count == 0; } size_t tm_count(struct treemap * _map_) { return _map_->count; } int tm_flag(struct treemap * _map_) { return _map_->flag; } struct treemap *tm_copy_of(struct treemap * _map_) { struct treemap *result = tm_new_custom(_map_->f_key, _map_->f_val, _map_->alloc, ((void *)0)); if (!result) { _map_->flag = CMC_FLAG_ERROR; return ((void *)0); } struct treemap_node *root = _map_->root; _Bool left_done = 0; while (root) { if (!left_done) { while (root->left) root = root->left; } size_t key; size_t value; if (_map_->f_key->cpy) key = _map_->f_key->cpy(root->key); else key = root->key; if (_map_->f_val->cpy) value = _map_->f_val->cpy(root->value); else value = root->value; tm_insert(result, key, value); left_done = 1; if (root->right) { left_done = 0; root = root->right; } else if (root->parent) { while (root->parent && root == root->parent->right) root = root->parent; if (!root->parent) break; root = root->parent; } else break; } _map_->flag = CMC_FLAG_OK; (result)->callbacks = _map_->callbacks; return result; } _Bool tm_equals(struct treemap * _map1_, struct treemap * _map2_) { _map1_->flag = CMC_FLAG_OK; _map2_->flag = CMC_FLAG_OK; if (_map1_->count != _map2_->count) return 0; struct treemap_node *root = _map1_->root; _Bool left_done = 0; while (root) { if (!left_done) { while (root->left) root = root->left; } struct treemap_node *node = tm_impl_get_node(_map2_, root->key); if (node == ((void *)0)) return 0; if (_map1_->f_val->cmp(node->value, root->value) != 0) return 0; left_done = 1; if (root->right) { left_done = 0; root = root->right; } else if (root->parent) { while (root->parent && root == root->parent->right) root = root->parent; if (!root->parent) break; root = root->parent; } else break; } return 1; } static struct treemap_node * tm_impl_new_node(struct treemap * _map_, size_t key, size_t value) { struct treemap_node *node = _map_->alloc->malloc(sizeof(struct treemap_node)); if (!node) return ((void *)0); node->key = key; node->value = value; node->right = ((void *)0); node->left = ((void *)0); node->parent = ((void *)0); node->height = 0; return node; } static struct treemap_node * tm_impl_get_node(struct treemap * _map_, size_t key) { struct treemap_node *scan = _map_->root; while (scan != ((void *)0)) { if (_map_->f_key->cmp(scan->key, key) > 0) scan = scan->left; else if (_map_->f_key->cmp(scan->key, key) < 0) scan = scan->right; else return scan; } return ((void *)0); } static unsigned char tm_impl_h(struct treemap_node * node) { if (node == ((void *)0)) return 0; return node->height; } static unsigned char tm_impl_hupdate(struct treemap_node * node) { if (node == ((void *)0)) return 0; unsigned char h_l = tm_impl_h(node->left); unsigned char h_r = tm_impl_h(node->right); return 1 + (h_l > h_r ? h_l : h_r); } static void tm_impl_rotate_right(struct treemap_node * *Z) { struct treemap_node *root = *Z; struct treemap_node *new_root = root->left; if (root->parent != ((void *)0)) { if (root->parent->left == root) root->parent->left = new_root; else root->parent->right = new_root; } new_root->parent = root->parent; root->parent = new_root; root->left = new_root->right; if (root->left) root->left->parent = root; new_root->right = root; root->height = tm_impl_hupdate(root); new_root->height = tm_impl_hupdate(new_root); *Z = new_root; } static void tm_impl_rotate_left(struct treemap_node * *Z) { struct treemap_node *root = *Z; struct treemap_node *new_root = root->right; if (root->parent != ((void *)0)) { if (root->parent->right == root) root->parent->right = new_root; else root->parent->left = new_root; } new_root->parent = root->parent; root->parent = new_root; root->right = new_root->left; if (root->right) root->right->parent = root; new_root->left = root; root->height = tm_impl_hupdate(root); new_root->height = tm_impl_hupdate(new_root); *Z = new_root; } static void tm_impl_rebalance(struct treemap * _map_, struct treemap_node * node) { struct treemap_node *scan = node, *child = ((void *)0); int balance; _Bool is_root = 0; while (scan != ((void *)0)) { if (scan->parent == ((void *)0)) is_root = 1; scan->height = tm_impl_hupdate(scan); balance = tm_impl_h(scan->right) - tm_impl_h(scan->left); if (balance >= 2) { child = scan->right; if (tm_impl_h(child->right) < tm_impl_h(child->left)) tm_impl_rotate_right(&(scan->right)); tm_impl_rotate_left(&scan); } else if (balance <= -2) { child = scan->left; if (tm_impl_h(child->left) < tm_impl_h(child->right)) tm_impl_rotate_left(&(scan->left)); tm_impl_rotate_right(&scan); } if (is_root) { _map_->root = scan; is_root = 0; } scan = scan->parent; } } struct treemap_iter tm_iter_start(struct treemap * target) { struct treemap_iter iter; iter.target = target; iter.cursor = target->root; iter.first = ((void *)0); iter.last = ((void *)0); iter.index = 0; iter.start = 1; iter.end = tm_empty(target); if (!tm_empty(target)) { while (iter.cursor->left != ((void *)0)) iter.cursor = iter.cursor->left; iter.first = iter.cursor; iter.last = target->root; while (iter.last->right != ((void *)0)) iter.last = iter.last->right; } return iter; } struct treemap_iter tm_iter_end(struct treemap * target) { struct treemap_iter iter; iter.target = target; iter.cursor = target->root; iter.first = ((void *)0); iter.last = ((void *)0); iter.index = 0; iter.start = tm_empty(target); iter.end = 1; if (!tm_empty(target)) { while (iter.cursor->right != ((void *)0)) iter.cursor = iter.cursor->right; iter.last = iter.cursor; iter.first = target->root; while (iter.first->left != ((void *)0)) iter.first = iter.first->left; iter.index = target->count - 1; } return iter; } _Bool tm_iter_at_start(struct treemap_iter * iter) { return tm_empty(iter->target) || iter->start; } _Bool tm_iter_at_end(struct treemap_iter * iter) { return tm_empty(iter->target) || iter->end; } _Bool tm_iter_to_start(struct treemap_iter * iter) { if (!tm_empty(iter->target)) { iter->index = 0; iter->start = 1; iter->end = tm_empty(iter->target); iter->cursor = iter->first; return 1; } return 0; } _Bool tm_iter_to_end(struct treemap_iter * iter) { if (!tm_empty(iter->target)) { iter->index = iter->target->count - 1; iter->start = tm_empty(iter->target); iter->end = 1; iter->cursor = iter->last; return 1; } return 0; } _Bool tm_iter_next(struct treemap_iter * iter) { if (iter->end) return 0; if (iter->cursor == iter->last) { iter->end = 1; return 0; } iter->start = tm_empty(iter->target); if (iter->cursor->right != ((void *)0)) { iter->cursor = iter->cursor->right; while (iter->cursor->left != ((void *)0)) iter->cursor = iter->cursor->left; iter->index++; return 1; } while (1) { if (iter->cursor->parent->left == iter->cursor) { iter->cursor = iter->cursor->parent; iter->index++; return 1; } iter->cursor = iter->cursor->parent; } } _Bool tm_iter_prev(struct treemap_iter * iter) { if (iter->start) return 0; if (iter->cursor == iter->first) { iter->start = 1; return 0; } iter->end = tm_empty(iter->target); if (iter->cursor->left != ((void *)0)) { iter->cursor = iter->cursor->left; while (iter->cursor->right != ((void *)0)) iter->cursor = iter->cursor->right; iter->index--; return 1; } while (1) { if (iter->cursor->parent->right == iter->cursor) { iter->cursor = iter->cursor->parent; iter->index--; return 1; } iter->cursor = iter->cursor->parent; } } _Bool tm_iter_advance(struct treemap_iter * iter, size_t steps) { if (iter->end) return 0; if (iter->cursor == iter->last) { iter->end = 1; return 0; } if (steps == 0 || iter->index + steps >= iter->target->count) return 0; for (size_t i = 0; i < steps; i++) tm_iter_next(iter); return 1; } _Bool tm_iter_rewind(struct treemap_iter * iter, size_t steps) { if (iter->start) return 0; if (iter->cursor == iter->first) { iter->start = 1; return 0; } if (steps == 0 || iter->index < steps) return 0; for (size_t i = 0; i < steps; i++) tm_iter_prev(iter); return 1; } _Bool tm_iter_go_to(struct treemap_iter * iter, size_t index) { if (index >= iter->target->count) return 0; if (iter->index > index) return tm_iter_rewind(iter, iter->index - index); else if (iter->index < index) return tm_iter_advance(iter, index - iter->index); return 1; } size_t tm_iter_key(struct treemap_iter * iter) { if (tm_empty(iter->target)) return (size_t){ 0 }; return iter->cursor->key; } size_t tm_iter_value(struct treemap_iter * iter) { if (tm_empty(iter->target)) return (size_t){ 0 }; return iter->cursor->value; } size_t *tm_iter_rvalue(struct treemap_iter * iter) { if (tm_empty(iter->target)) return ((void *)0); return &(iter->cursor->value); } size_t tm_iter_index(struct treemap_iter * iter) { return iter->index; } _Bool tm_to_string(struct treemap * _map_, FILE * fptr) { struct treemap *m_ = _map_; return 0 <= fprintf(fptr, "struct %s<%s, %s> " "at %p { " "root:%p, " "count:%" "I64u" ", " "flag:%d, " "f_val:%p, " "f_key:%p, " "alloc:%p, " "callbacks:%p }", "treemap", "size_t", "size_t", m_, m_->root, m_->count, m_->flag, m_->f_key, m_->f_val, m_->alloc, (m_)->callbacks); } _Bool tm_print(struct treemap * _map_, FILE * fptr, const char *start, const char *separator, const char *end, const char *key_val_sep) { fprintf(fptr, "%s", start); struct treemap_node *root = _map_->root; _Bool left_done = 0; size_t i = 0; while (root) { if (!left_done) { while (root->left) root = root->left; } if (!_map_->f_key->str(fptr, root->key)) return 0; fprintf(fptr, "%s", key_val_sep); if (!_map_->f_val->str(fptr, root->value)) return 0; if (++i < _map_->count) fprintf(fptr, "%s", separator); left_done = 1; if (root->right) { left_done = 0; root = root->right; } else if (root->parent) { while (root->parent && root == root->parent->right) root = root->parent; if (!root->parent) break; root = root->parent; } else break; } fprintf(fptr, "%s", end); return 1; } - - \ No newline at end of file +static struct treemap_node *tm_impl_new_node(struct treemap *_map_, size_t key, size_t value); +static struct treemap_node *tm_impl_get_node(struct treemap *_map_, size_t key); +static unsigned char tm_impl_h(struct treemap_node *node); +static unsigned char tm_impl_hupdate(struct treemap_node *node); +static void tm_impl_rotate_right(struct treemap_node **Z); +static void tm_impl_rotate_left(struct treemap_node **Z); +static void tm_impl_rebalance(struct treemap *_map_, struct treemap_node *node); +struct treemap *tm_new(struct treemap_fkey *f_key, struct treemap_fval *f_val) +{ + return tm_new_custom(f_key, f_val, ((void *)0), ((void *)0)); +} +struct treemap *tm_new_custom(struct treemap_fkey *f_key, struct treemap_fval *f_val, struct cmc_alloc_node *alloc, + struct cmc_callbacks *callbacks) +{ + ; + if (!f_key || !f_val) + return ((void *)0); + if (!alloc) + alloc = &cmc_alloc_node_default; + struct treemap *_map_ = alloc->malloc(sizeof(struct treemap)); + if (!_map_) + return ((void *)0); + _map_->count = 0; + _map_->root = ((void *)0); + _map_->flag = CMC_FLAG_OK; + _map_->f_key = f_key; + _map_->f_val = f_val; + _map_->alloc = alloc; + (_map_)->callbacks = callbacks; + return _map_; +} +void tm_clear(struct treemap *_map_) +{ + struct treemap_node *scan = _map_->root; + struct treemap_node *up = ((void *)0); + while (scan != ((void *)0)) + { + if (scan->left != ((void *)0)) + { + struct treemap_node *left = scan->left; + scan->left = up; + up = scan; + scan = left; + } + else if (scan->right != ((void *)0)) + { + struct treemap_node *right = scan->right; + scan->left = up; + scan->right = ((void *)0); + up = scan; + scan = right; + } + else + { + if (up == ((void *)0)) + { + if (_map_->f_key->free) + _map_->f_key->free(scan->key); + if (_map_->f_val->free) + _map_->f_val->free(scan->value); + _map_->alloc->free(scan); + scan = ((void *)0); + } + while (up != ((void *)0)) + { + if (_map_->f_key->free) + _map_->f_key->free(scan->key); + if (_map_->f_val->free) + _map_->f_val->free(scan->value); + _map_->alloc->free(scan); + if (up->right != ((void *)0)) + { + scan = up->right; + up->right = ((void *)0); + break; + } + else + { + scan = up; + up = up->left; + } + } + } + } + _map_->count = 0; + _map_->root = ((void *)0); + _map_->flag = CMC_FLAG_OK; +} +void tm_free(struct treemap *_map_) +{ + tm_clear(_map_); + _map_->alloc->free(_map_); +} +void tm_customize(struct treemap *_map_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks) +{ + ; + if (!alloc) + _map_->alloc = &cmc_alloc_node_default; + else + _map_->alloc = alloc; + (_map_)->callbacks = callbacks; + _map_->flag = CMC_FLAG_OK; +} +_Bool tm_insert(struct treemap *_map_, size_t key, size_t value) +{ + if (tm_empty(_map_)) + { + _map_->root = tm_impl_new_node(_map_, key, value); + if (!_map_->root) + { + _map_->flag = CMC_FLAG_ALLOC; + return 0; + } + } + else + { + struct treemap_node *scan = _map_->root; + struct treemap_node *parent = scan; + while (scan != ((void *)0)) + { + parent = scan; + if (_map_->f_key->cmp(scan->key, key) > 0) + scan = scan->left; + else if (_map_->f_key->cmp(scan->key, key) < 0) + scan = scan->right; + else + { + _map_->flag = CMC_FLAG_DUPLICATE; + return 0; + } + } + struct treemap_node *node; + if (_map_->f_key->cmp(parent->key, key) > 0) + { + parent->left = tm_impl_new_node(_map_, key, value); + if (!parent->left) + { + _map_->flag = CMC_FLAG_ALLOC; + return 0; + } + parent->left->parent = parent; + node = parent->left; + } + else + { + parent->right = tm_impl_new_node(_map_, key, value); + if (!parent->right) + { + _map_->flag = CMC_FLAG_ALLOC; + return 0; + } + parent->right->parent = parent; + node = parent->right; + } + tm_impl_rebalance(_map_, node); + } + _map_->count++; + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->create) + (_map_)->callbacks->create(); + ; + return 1; +} +_Bool tm_update(struct treemap *_map_, size_t key, size_t new_value, size_t *old_value) +{ + struct treemap_node *node = tm_impl_get_node(_map_, key); + if (!node) + { + _map_->flag = CMC_FLAG_NOT_FOUND; + return 0; + } + if (old_value) + *old_value = node->value; + node->value = new_value; + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->update) + (_map_)->callbacks->update(); + ; + return 1; +} +_Bool tm_remove(struct treemap *_map_, size_t key, size_t *out_value) +{ + if (tm_empty(_map_)) + { + _map_->flag = CMC_FLAG_EMPTY; + return 0; + } + struct treemap_node *node = tm_impl_get_node(_map_, key); + if (!node) + { + _map_->flag = CMC_FLAG_NOT_FOUND; + return 0; + } + if (out_value) + *out_value = node->value; + struct treemap_node *temp = ((void *)0), *unbalanced = ((void *)0); + _Bool is_root = node->parent == ((void *)0); + if (node->left == ((void *)0) && node->right == ((void *)0)) + { + if (is_root) + _map_->root = ((void *)0); + else + { + unbalanced = node->parent; + if (node->parent->right == node) + node->parent->right = ((void *)0); + else + node->parent->left = ((void *)0); + } + _map_->alloc->free(node); + } + else if (node->left == ((void *)0)) + { + if (is_root) + { + _map_->root = node->right; + _map_->root->parent = ((void *)0); + } + else + { + unbalanced = node->parent; + node->right->parent = node->parent; + if (node->parent->right == node) + node->parent->right = node->right; + else + node->parent->left = node->right; + } + _map_->alloc->free(node); + } + else if (node->right == ((void *)0)) + { + if (is_root) + { + _map_->root = node->left; + _map_->root->parent = ((void *)0); + } + else + { + unbalanced = node->parent; + node->left->parent = node->parent; + if (node->parent->right == node) + node->parent->right = node->left; + else + node->parent->left = node->left; + } + _map_->alloc->free(node); + } + else + { + temp = node->right; + while (temp->left != ((void *)0)) + temp = temp->left; + size_t temp_key = temp->key; + size_t temp_val = temp->value; + unbalanced = temp->parent; + if (temp->left == ((void *)0) && temp->right == ((void *)0)) + { + if (temp->parent->right == temp) + temp->parent->right = ((void *)0); + else + temp->parent->left = ((void *)0); + } + else if (temp->left == ((void *)0)) + { + temp->right->parent = temp->parent; + if (temp->parent->right == temp) + temp->parent->right = temp->right; + else + temp->parent->left = temp->right; + } + else if (temp->right == ((void *)0)) + { + temp->left->parent = temp->parent; + if (temp->parent->right == temp) + temp->parent->right = temp->left; + else + temp->parent->left = temp->left; + } + _map_->alloc->free(temp); + node->key = temp_key; + node->value = temp_val; + } + if (unbalanced != ((void *)0)) + tm_impl_rebalance(_map_, unbalanced); + if (_map_->count == 0) + _map_->root = ((void *)0); + _map_->count--; + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->delete) + (_map_)->callbacks->delete (); + ; + return 1; +} +_Bool tm_max(struct treemap *_map_, size_t *key, size_t *value) +{ + if (tm_empty(_map_)) + { + _map_->flag = CMC_FLAG_EMPTY; + return 0; + } + struct treemap_node *scan = _map_->root; + while (scan->right != ((void *)0)) + scan = scan->right; + if (key) + *key = scan->key; + if (value) + *value = scan->value; + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->read) + (_map_)->callbacks->read(); + ; + return 1; +} +_Bool tm_min(struct treemap *_map_, size_t *key, size_t *value) +{ + if (tm_empty(_map_)) + { + _map_->flag = CMC_FLAG_EMPTY; + return 0; + } + struct treemap_node *scan = _map_->root; + while (scan->left != ((void *)0)) + scan = scan->left; + if (key) + *key = scan->key; + if (value) + *value = scan->value; + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->read) + (_map_)->callbacks->read(); + ; + return 1; +} +size_t tm_get(struct treemap *_map_, size_t key) +{ + if (tm_empty(_map_)) + { + _map_->flag = CMC_FLAG_EMPTY; + return (size_t){ 0 }; + } + struct treemap_node *node = tm_impl_get_node(_map_, key); + if (!node) + { + _map_->flag = CMC_FLAG_NOT_FOUND; + return (size_t){ 0 }; + } + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->read) + (_map_)->callbacks->read(); + ; + return node->value; +} +size_t *tm_get_ref(struct treemap *_map_, size_t key) +{ + if (tm_empty(_map_)) + { + _map_->flag = CMC_FLAG_EMPTY; + return ((void *)0); + } + struct treemap_node *node = tm_impl_get_node(_map_, key); + if (!node) + { + _map_->flag = CMC_FLAG_NOT_FOUND; + return ((void *)0); + } + _map_->flag = CMC_FLAG_OK; + if ((_map_)->callbacks && (_map_)->callbacks->read) + (_map_)->callbacks->read(); + ; + return &(node->value); +} +_Bool tm_contains(struct treemap *_map_, size_t key) +{ + _Bool result = tm_impl_get_node(_map_, key) != ((void *)0); + if ((_map_)->callbacks && (_map_)->callbacks->read) + (_map_)->callbacks->read(); + ; + return result; +} +_Bool tm_empty(struct treemap *_map_) +{ + return _map_->count == 0; +} +size_t tm_count(struct treemap *_map_) +{ + return _map_->count; +} +int tm_flag(struct treemap *_map_) +{ + return _map_->flag; +} +struct treemap *tm_copy_of(struct treemap *_map_) +{ + struct treemap *result = tm_new_custom(_map_->f_key, _map_->f_val, _map_->alloc, ((void *)0)); + if (!result) + { + _map_->flag = CMC_FLAG_ERROR; + return ((void *)0); + } + struct treemap_node *root = _map_->root; + _Bool left_done = 0; + while (root) + { + if (!left_done) + { + while (root->left) + root = root->left; + } + size_t key; + size_t value; + if (_map_->f_key->cpy) + key = _map_->f_key->cpy(root->key); + else + key = root->key; + if (_map_->f_val->cpy) + value = _map_->f_val->cpy(root->value); + else + value = root->value; + tm_insert(result, key, value); + left_done = 1; + if (root->right) + { + left_done = 0; + root = root->right; + } + else if (root->parent) + { + while (root->parent && root == root->parent->right) + root = root->parent; + if (!root->parent) + break; + root = root->parent; + } + else + break; + } + _map_->flag = CMC_FLAG_OK; + (result)->callbacks = _map_->callbacks; + return result; +} +_Bool tm_equals(struct treemap *_map1_, struct treemap *_map2_) +{ + _map1_->flag = CMC_FLAG_OK; + _map2_->flag = CMC_FLAG_OK; + if (_map1_->count != _map2_->count) + return 0; + struct treemap_node *root = _map1_->root; + _Bool left_done = 0; + while (root) + { + if (!left_done) + { + while (root->left) + root = root->left; + } + struct treemap_node *node = tm_impl_get_node(_map2_, root->key); + if (node == ((void *)0)) + return 0; + if (_map1_->f_val->cmp(node->value, root->value) != 0) + return 0; + left_done = 1; + if (root->right) + { + left_done = 0; + root = root->right; + } + else if (root->parent) + { + while (root->parent && root == root->parent->right) + root = root->parent; + if (!root->parent) + break; + root = root->parent; + } + else + break; + } + return 1; +} +static struct treemap_node *tm_impl_new_node(struct treemap *_map_, size_t key, size_t value) +{ + struct treemap_node *node = _map_->alloc->malloc(sizeof(struct treemap_node)); + if (!node) + return ((void *)0); + node->key = key; + node->value = value; + node->right = ((void *)0); + node->left = ((void *)0); + node->parent = ((void *)0); + node->height = 0; + return node; +} +static struct treemap_node *tm_impl_get_node(struct treemap *_map_, size_t key) +{ + struct treemap_node *scan = _map_->root; + while (scan != ((void *)0)) + { + if (_map_->f_key->cmp(scan->key, key) > 0) + scan = scan->left; + else if (_map_->f_key->cmp(scan->key, key) < 0) + scan = scan->right; + else + return scan; + } + return ((void *)0); +} +static unsigned char tm_impl_h(struct treemap_node *node) +{ + if (node == ((void *)0)) + return 0; + return node->height; +} +static unsigned char tm_impl_hupdate(struct treemap_node *node) +{ + if (node == ((void *)0)) + return 0; + unsigned char h_l = tm_impl_h(node->left); + unsigned char h_r = tm_impl_h(node->right); + return 1 + (h_l > h_r ? h_l : h_r); +} +static void tm_impl_rotate_right(struct treemap_node **Z) +{ + struct treemap_node *root = *Z; + struct treemap_node *new_root = root->left; + if (root->parent != ((void *)0)) + { + if (root->parent->left == root) + root->parent->left = new_root; + else + root->parent->right = new_root; + } + new_root->parent = root->parent; + root->parent = new_root; + root->left = new_root->right; + if (root->left) + root->left->parent = root; + new_root->right = root; + root->height = tm_impl_hupdate(root); + new_root->height = tm_impl_hupdate(new_root); + *Z = new_root; +} +static void tm_impl_rotate_left(struct treemap_node **Z) +{ + struct treemap_node *root = *Z; + struct treemap_node *new_root = root->right; + if (root->parent != ((void *)0)) + { + if (root->parent->right == root) + root->parent->right = new_root; + else + root->parent->left = new_root; + } + new_root->parent = root->parent; + root->parent = new_root; + root->right = new_root->left; + if (root->right) + root->right->parent = root; + new_root->left = root; + root->height = tm_impl_hupdate(root); + new_root->height = tm_impl_hupdate(new_root); + *Z = new_root; +} +static void tm_impl_rebalance(struct treemap *_map_, struct treemap_node *node) +{ + struct treemap_node *scan = node, *child = ((void *)0); + int balance; + _Bool is_root = 0; + while (scan != ((void *)0)) + { + if (scan->parent == ((void *)0)) + is_root = 1; + scan->height = tm_impl_hupdate(scan); + balance = tm_impl_h(scan->right) - tm_impl_h(scan->left); + if (balance >= 2) + { + child = scan->right; + if (tm_impl_h(child->right) < tm_impl_h(child->left)) + tm_impl_rotate_right(&(scan->right)); + tm_impl_rotate_left(&scan); + } + else if (balance <= -2) + { + child = scan->left; + if (tm_impl_h(child->left) < tm_impl_h(child->right)) + tm_impl_rotate_left(&(scan->left)); + tm_impl_rotate_right(&scan); + } + if (is_root) + { + _map_->root = scan; + is_root = 0; + } + scan = scan->parent; + } +} +struct treemap_iter tm_iter_start(struct treemap *target) +{ + struct treemap_iter iter; + iter.target = target; + iter.cursor = target->root; + iter.first = ((void *)0); + iter.last = ((void *)0); + iter.index = 0; + iter.start = 1; + iter.end = tm_empty(target); + if (!tm_empty(target)) + { + while (iter.cursor->left != ((void *)0)) + iter.cursor = iter.cursor->left; + iter.first = iter.cursor; + iter.last = target->root; + while (iter.last->right != ((void *)0)) + iter.last = iter.last->right; + } + return iter; +} +struct treemap_iter tm_iter_end(struct treemap *target) +{ + struct treemap_iter iter; + iter.target = target; + iter.cursor = target->root; + iter.first = ((void *)0); + iter.last = ((void *)0); + iter.index = 0; + iter.start = tm_empty(target); + iter.end = 1; + if (!tm_empty(target)) + { + while (iter.cursor->right != ((void *)0)) + iter.cursor = iter.cursor->right; + iter.last = iter.cursor; + iter.first = target->root; + while (iter.first->left != ((void *)0)) + iter.first = iter.first->left; + iter.index = target->count - 1; + } + return iter; +} +_Bool tm_iter_at_start(struct treemap_iter *iter) +{ + return tm_empty(iter->target) || iter->start; +} +_Bool tm_iter_at_end(struct treemap_iter *iter) +{ + return tm_empty(iter->target) || iter->end; +} +_Bool tm_iter_to_start(struct treemap_iter *iter) +{ + if (!tm_empty(iter->target)) + { + iter->index = 0; + iter->start = 1; + iter->end = tm_empty(iter->target); + iter->cursor = iter->first; + return 1; + } + return 0; +} +_Bool tm_iter_to_end(struct treemap_iter *iter) +{ + if (!tm_empty(iter->target)) + { + iter->index = iter->target->count - 1; + iter->start = tm_empty(iter->target); + iter->end = 1; + iter->cursor = iter->last; + return 1; + } + return 0; +} +_Bool tm_iter_next(struct treemap_iter *iter) +{ + if (iter->end) + return 0; + if (iter->cursor == iter->last) + { + iter->end = 1; + return 0; + } + iter->start = tm_empty(iter->target); + if (iter->cursor->right != ((void *)0)) + { + iter->cursor = iter->cursor->right; + while (iter->cursor->left != ((void *)0)) + iter->cursor = iter->cursor->left; + iter->index++; + return 1; + } + while (1) + { + if (iter->cursor->parent->left == iter->cursor) + { + iter->cursor = iter->cursor->parent; + iter->index++; + return 1; + } + iter->cursor = iter->cursor->parent; + } +} +_Bool tm_iter_prev(struct treemap_iter *iter) +{ + if (iter->start) + return 0; + if (iter->cursor == iter->first) + { + iter->start = 1; + return 0; + } + iter->end = tm_empty(iter->target); + if (iter->cursor->left != ((void *)0)) + { + iter->cursor = iter->cursor->left; + while (iter->cursor->right != ((void *)0)) + iter->cursor = iter->cursor->right; + iter->index--; + return 1; + } + while (1) + { + if (iter->cursor->parent->right == iter->cursor) + { + iter->cursor = iter->cursor->parent; + iter->index--; + return 1; + } + iter->cursor = iter->cursor->parent; + } +} +_Bool tm_iter_advance(struct treemap_iter *iter, size_t steps) +{ + if (iter->end) + return 0; + if (iter->cursor == iter->last) + { + iter->end = 1; + return 0; + } + if (steps == 0 || iter->index + steps >= iter->target->count) + return 0; + for (size_t i = 0; i < steps; i++) + tm_iter_next(iter); + return 1; +} +_Bool tm_iter_rewind(struct treemap_iter *iter, size_t steps) +{ + if (iter->start) + return 0; + if (iter->cursor == iter->first) + { + iter->start = 1; + return 0; + } + if (steps == 0 || iter->index < steps) + return 0; + for (size_t i = 0; i < steps; i++) + tm_iter_prev(iter); + return 1; +} +_Bool tm_iter_go_to(struct treemap_iter *iter, size_t index) +{ + if (index >= iter->target->count) + return 0; + if (iter->index > index) + return tm_iter_rewind(iter, iter->index - index); + else if (iter->index < index) + return tm_iter_advance(iter, index - iter->index); + return 1; +} +size_t tm_iter_key(struct treemap_iter *iter) +{ + if (tm_empty(iter->target)) + return (size_t){ 0 }; + return iter->cursor->key; +} +size_t tm_iter_value(struct treemap_iter *iter) +{ + if (tm_empty(iter->target)) + return (size_t){ 0 }; + return iter->cursor->value; +} +size_t *tm_iter_rvalue(struct treemap_iter *iter) +{ + if (tm_empty(iter->target)) + return ((void *)0); + return &(iter->cursor->value); +} +size_t tm_iter_index(struct treemap_iter *iter) +{ + return iter->index; +} +_Bool tm_to_string(struct treemap *_map_, FILE *fptr) +{ + struct treemap *m_ = _map_; + return 0 <= fprintf(fptr, + "struct %s<%s, %s> " + "at %p { " + "root:%p, " + "count:%" + "I64u" + ", " + "flag:%d, " + "f_val:%p, " + "f_key:%p, " + "alloc:%p, " + "callbacks:%p }", + "treemap", "size_t", "size_t", m_, m_->root, m_->count, m_->flag, m_->f_key, m_->f_val, + m_->alloc, (m_)->callbacks); +} +_Bool tm_print(struct treemap *_map_, FILE *fptr, const char *start, const char *separator, const char *end, + const char *key_val_sep) +{ + fprintf(fptr, "%s", start); + struct treemap_node *root = _map_->root; + _Bool left_done = 0; + size_t i = 0; + while (root) + { + if (!left_done) + { + while (root->left) + root = root->left; + } + if (!_map_->f_key->str(fptr, root->key)) + return 0; + fprintf(fptr, "%s", key_val_sep); + if (!_map_->f_val->str(fptr, root->value)) + return 0; + if (++i < _map_->count) + fprintf(fptr, "%s", separator); + left_done = 1; + if (root->right) + { + left_done = 0; + root = root->right; + } + else if (root->parent) + { + while (root->parent && root == root->parent->right) + root = root->parent; + if (!root->parent) + break; + root = root->parent; + } + else + break; + } + fprintf(fptr, "%s", end); + return 1; +} diff --git a/tests/src/tst_cmc_treeset.c b/tests/src/tst_cmc_treeset.c index 1b46b22..b0a60ce 100644 --- a/tests/src/tst_cmc_treeset.c +++ b/tests/src/tst_cmc_treeset.c @@ -1,7 +1,841 @@ - #include "tst_cmc_treeset.h" +#include "tst_cmc_treeset.h" - - static struct treeset_node * ts_impl_new_node(struct treeset * _set_, size_t value); static struct treeset_node * ts_impl_get_node(struct treeset * _set_, size_t value); static unsigned char ts_impl_h(struct treeset_node * node); static unsigned char ts_impl_hupdate(struct treeset_node * node); static void ts_impl_rotate_right(struct treeset_node * *Z); static void ts_impl_rotate_left(struct treeset_node * *Z); static void ts_impl_rebalance(struct treeset * _set_, struct treeset_node * node); struct treeset *ts_new(struct treeset_fval * f_val) { return ts_new_custom(f_val, ((void *)0), ((void *)0)); } struct treeset *ts_new_custom(struct treeset_fval * f_val, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (!f_val) return ((void *)0); if (!alloc) alloc = &cmc_alloc_node_default; struct treeset *_set_ = alloc->malloc(sizeof(struct treeset)); if (!_set_) return ((void *)0); _set_->count = 0; _set_->root = ((void *)0); _set_->flag = CMC_FLAG_OK; _set_->f_val = f_val; _set_->alloc = alloc; (_set_)->callbacks = callbacks; return _set_; } void ts_clear(struct treeset * _set_) { struct treeset_node *scan = _set_->root; struct treeset_node *up = ((void *)0); while (scan != ((void *)0)) { if (scan->left != ((void *)0)) { struct treeset_node *left = scan->left; scan->left = up; up = scan; scan = left; } else if (scan->right != ((void *)0)) { struct treeset_node *right = scan->right; scan->left = up; scan->right = ((void *)0); up = scan; scan = right; } else { if (up == ((void *)0)) { if (_set_->f_val->free) _set_->f_val->free(scan->value); _set_->alloc->free(scan); scan = ((void *)0); } while (up != ((void *)0)) { if (_set_->f_val->free) _set_->f_val->free(scan->value); _set_->alloc->free(scan); if (up->right != ((void *)0)) { scan = up->right; up->right = ((void *)0); break; } else { scan = up; up = up->left; } } } } _set_->count = 0; _set_->root = ((void *)0); _set_->flag = CMC_FLAG_OK; } void ts_free(struct treeset * _set_) { ts_clear(_set_); _set_->alloc->free(_set_); } void ts_customize(struct treeset * _set_, struct cmc_alloc_node * alloc, struct cmc_callbacks * callbacks) { ; if (!alloc) _set_->alloc = &cmc_alloc_node_default; else _set_->alloc = alloc; (_set_)->callbacks = callbacks; _set_->flag = CMC_FLAG_OK; } _Bool ts_insert(struct treeset * _set_, size_t value) { if (ts_empty(_set_)) { _set_->root = ts_impl_new_node(_set_, value); if (!_set_->root) { _set_->flag = CMC_FLAG_ALLOC; return 0; } } else { struct treeset_node *scan = _set_->root; struct treeset_node *parent = scan; while (scan != ((void *)0)) { parent = scan; if (_set_->f_val->cmp(scan->value, value) > 0) scan = scan->left; else if (_set_->f_val->cmp(scan->value, value) < 0) scan = scan->right; else { _set_->flag = CMC_FLAG_DUPLICATE; return 0; } } struct treeset_node * node; if (_set_->f_val->cmp(parent->value, value) > 0) { parent->left = ts_impl_new_node(_set_, value); if (!parent->left) { _set_->flag = CMC_FLAG_ALLOC; return 0; } parent->left->parent = parent; node = parent->left; } else { parent->right = ts_impl_new_node(_set_, value); if (!parent->right) { _set_->flag = CMC_FLAG_ALLOC; return 0; } parent->right->parent = parent; node = parent->right; } ts_impl_rebalance(_set_, node); } _set_->count++; _set_->flag = CMC_FLAG_OK; if ((_set_)->callbacks && (_set_)->callbacks->create) (_set_)->callbacks->create();; return 1; } _Bool ts_remove(struct treeset * _set_, size_t value) { if (ts_empty(_set_)) { _set_->flag = CMC_FLAG_EMPTY; return 0; } struct treeset_node *node = ts_impl_get_node(_set_, value); if (!node) { _set_->flag = CMC_FLAG_NOT_FOUND; return 0; } struct treeset_node *temp = ((void *)0), *unbalanced = ((void *)0); _Bool is_root = node->parent == ((void *)0); if (node->left == ((void *)0) && node->right == ((void *)0)) { if (is_root) _set_->root = ((void *)0); else { unbalanced = node->parent; if (node->parent->right == node) node->parent->right = ((void *)0); else node->parent->left = ((void *)0); } _set_->alloc->free(node); } else if (node->left == ((void *)0)) { if (is_root) { _set_->root = node->right; _set_->root->parent = ((void *)0); } else { unbalanced = node->parent; node->right->parent = node->parent; if (node->parent->right == node) node->parent->right = node->right; else node->parent->left = node->right; } _set_->alloc->free(node); } else if (node->right == ((void *)0)) { if (is_root) { _set_->root = node->left; _set_->root->parent = ((void *)0); } else { unbalanced = node->parent; node->left->parent = node->parent; if (node->parent->right == node) node->parent->right = node->left; else node->parent->left = node->left; } _set_->alloc->free(node); } else { temp = node->right; while (temp->left != ((void *)0)) temp = temp->left; size_t temp_value = temp->value; unbalanced = temp->parent; if (temp->left == ((void *)0) && temp->right == ((void *)0)) { if (temp->parent->right == temp) temp->parent->right = ((void *)0); else temp->parent->left = ((void *)0); } else if (temp->left == ((void *)0)) { temp->right->parent = temp->parent; if (temp->parent->right == temp) temp->parent->right = temp->right; else temp->parent->left = temp->right; } else if (temp->right == ((void *)0)) { temp->left->parent = temp->parent; if (temp->parent->right == temp) temp->parent->right = temp->left; else temp->parent->left = temp->left; } _set_->alloc->free(temp); node->value = temp_value; } if (unbalanced != ((void *)0)) ts_impl_rebalance(_set_, unbalanced); if (_set_->count == 0) _set_->root = ((void *)0); _set_->count--; _set_->flag = CMC_FLAG_OK; if ((_set_)->callbacks && (_set_)->callbacks->delete) (_set_)->callbacks->delete();; return 1; } _Bool ts_max(struct treeset * _set_, size_t * value) { if (ts_empty(_set_)) { _set_->flag = CMC_FLAG_EMPTY; return 0; } struct treeset_node *scan = _set_->root; while (scan->right != ((void *)0)) scan = scan->right; if (value) *value = scan->value; _set_->flag = CMC_FLAG_OK; if ((_set_)->callbacks && (_set_)->callbacks->read) (_set_)->callbacks->read();; return 1; } _Bool ts_min(struct treeset * _set_, size_t * value) { if (ts_empty(_set_)) { _set_->flag = CMC_FLAG_EMPTY; return 0; } struct treeset_node *scan = _set_->root; while (scan->left != ((void *)0)) scan = scan->left; if (value) *value = scan->value; _set_->flag = CMC_FLAG_OK; if ((_set_)->callbacks && (_set_)->callbacks->read) (_set_)->callbacks->read();; return 1; } _Bool ts_contains(struct treeset * _set_, size_t value) { _Bool result = ts_impl_get_node(_set_, value) != ((void *)0); if ((_set_)->callbacks && (_set_)->callbacks->read) (_set_)->callbacks->read();; return result; } _Bool ts_empty(struct treeset * _set_) { return _set_->count == 0; } size_t ts_count(struct treeset * _set_) { return _set_->count; } int ts_flag(struct treeset * _set_) { return _set_->flag; } struct treeset *ts_copy_of(struct treeset * _set_) { struct treeset *result = ts_new_custom(_set_->f_val, _set_->alloc, ((void *)0)); if (!result) { _set_->flag = CMC_FLAG_ERROR; return ((void *)0); } (result)->callbacks = _set_->callbacks; if (!ts_empty(_set_)) { struct treeset_iter iter = ts_iter_start(_set_); for (; !ts_iter_at_end(&iter); ts_iter_next(&iter)) { if (_set_->f_val->cpy) ts_insert (result, _set_->f_val->cpy(ts_iter_value(&iter))); else ts_insert(result, ts_iter_value(&iter)); } } _set_->flag = CMC_FLAG_OK; return result; } _Bool ts_equals(struct treeset * _set1_, struct treeset * _set2_) { _set1_->flag = CMC_FLAG_OK; _set2_->flag = CMC_FLAG_OK; if (_set1_->count != _set2_->count) return 0; struct treeset_iter iter = ts_iter_start(_set1_); for (; !ts_iter_at_end(&iter); ts_iter_next(&iter)) { if (ts_impl_get_node(_set2_, ts_iter_value(&iter)) == ((void *)0)) return 0; } return 1; } static struct treeset_node * ts_impl_new_node(struct treeset * _set_, size_t value) { struct treeset_node *node = _set_->alloc->malloc(sizeof(struct treeset_node)); if (!node) return ((void *)0); node->value = value; node->right = ((void *)0); node->left = ((void *)0); node->parent = ((void *)0); node->height = 0; return node; } static struct treeset_node * ts_impl_get_node(struct treeset * _set_, size_t value) { struct treeset_node *scan = _set_->root; while (scan != ((void *)0)) { if (_set_->f_val->cmp(scan->value, value) > 0) scan = scan->left; else if (_set_->f_val->cmp(scan->value, value) < 0) scan = scan->right; else return scan; } return ((void *)0); } static unsigned char ts_impl_h(struct treeset_node * node) { if (node == ((void *)0)) return 0; return node->height; } static unsigned char ts_impl_hupdate(struct treeset_node * node) { if (node == ((void *)0)) return 0; unsigned char h_l = ts_impl_h(node->left); unsigned char h_r = ts_impl_h(node->right); return 1 + (h_l > h_r ? h_l : h_r); } static void ts_impl_rotate_right(struct treeset_node * *Z) { struct treeset_node *root = *Z; struct treeset_node *new_root = root->left; if (root->parent != ((void *)0)) { if (root->parent->left == root) root->parent->left = new_root; else root->parent->right = new_root; } new_root->parent = root->parent; root->parent = new_root; root->left = new_root->right; if (root->left) root->left->parent = root; new_root->right = root; root->height = ts_impl_hupdate(root); new_root->height = ts_impl_hupdate(new_root); *Z = new_root; } static void ts_impl_rotate_left(struct treeset_node * *Z) { struct treeset_node *root = *Z; struct treeset_node *new_root = root->right; if (root->parent != ((void *)0)) { if (root->parent->right == root) root->parent->right = new_root; else root->parent->left = new_root; } new_root->parent = root->parent; root->parent = new_root; root->right = new_root->left; if (root->right) root->right->parent = root; new_root->left = root; root->height = ts_impl_hupdate(root); new_root->height = ts_impl_hupdate(new_root); *Z = new_root; } static void ts_impl_rebalance(struct treeset * _set_, struct treeset_node * node) { struct treeset_node *scan = node, *child = ((void *)0); int balance; _Bool is_root = 0; while (scan != ((void *)0)) { if (scan->parent == ((void *)0)) is_root = 1; scan->height = ts_impl_hupdate(scan); balance = ts_impl_h(scan->right) - ts_impl_h(scan->left); if (balance >= 2) { child = scan->right; if (ts_impl_h(child->right) < ts_impl_h(child->left)) ts_impl_rotate_right(&(scan->right)); ts_impl_rotate_left(&scan); } else if (balance <= -2) { child = scan->left; if (ts_impl_h(child->left) < ts_impl_h(child->right)) ts_impl_rotate_left(&(scan->left)); ts_impl_rotate_right(&scan); } if (is_root) { _set_->root = scan; is_root = 0; } scan = scan->parent; } } struct treeset_iter ts_iter_start(struct treeset * target) { struct treeset_iter iter; iter.target = target; iter.cursor = target->root; iter.first = ((void *)0); iter.last = ((void *)0); iter.index = 0; iter.start = 1; iter.end = ts_empty(target); if (!ts_empty(target)) { while (iter.cursor->left != ((void *)0)) iter.cursor = iter.cursor->left; iter.first = iter.cursor; iter.last = target->root; while (iter.last->right != ((void *)0)) iter.last = iter.last->right; } return iter; } struct treeset_iter ts_iter_end(struct treeset * target) { struct treeset_iter iter; iter.target = target; iter.cursor = target->root; iter.first = ((void *)0); iter.last = ((void *)0); iter.index = 0; iter.start = ts_empty(target); iter.end = 1; if (!ts_empty(target)) { while (iter.cursor->right != ((void *)0)) iter.cursor = iter.cursor->right; iter.last = iter.cursor; iter.first = target->root; while (iter.first->left != ((void *)0)) iter.first = iter.first->left; iter.index = target->count - 1; } return iter; } _Bool ts_iter_at_start(struct treeset_iter * iter) { return ts_empty(iter->target) || iter->start; } _Bool ts_iter_at_end(struct treeset_iter * iter) { return ts_empty(iter->target) || iter->end; } _Bool ts_iter_to_start(struct treeset_iter * iter) { if (!ts_empty(iter->target)) { iter->index = 0; iter->start = 1; iter->end = ts_empty(iter->target); iter->cursor = iter->first; return 1; } return 0; } _Bool ts_iter_to_end(struct treeset_iter * iter) { if (!ts_empty(iter->target)) { iter->index = iter->target->count - 1; iter->start = ts_empty(iter->target); iter->end = 1; iter->cursor = iter->last; return 1; } return 0; } _Bool ts_iter_next(struct treeset_iter * iter) { if (iter->end) return 0; if (iter->cursor == iter->last) { iter->end = 1; return 0; } iter->start = ts_empty(iter->target); if (iter->cursor->right != ((void *)0)) { iter->cursor = iter->cursor->right; while (iter->cursor->left != ((void *)0)) iter->cursor = iter->cursor->left; iter->index++; return 1; } while (1) { if (iter->cursor->parent->left == iter->cursor) { iter->cursor = iter->cursor->parent; iter->index++; return 1; } iter->cursor = iter->cursor->parent; } } _Bool ts_iter_prev(struct treeset_iter * iter) { if (iter->start) return 0; if (iter->cursor == iter->first) { iter->start = 1; return 0; } iter->end = ts_empty(iter->target); if (iter->cursor->left != ((void *)0)) { iter->cursor = iter->cursor->left; while (iter->cursor->right != ((void *)0)) iter->cursor = iter->cursor->right; iter->index--; return 1; } while (1) { if (iter->cursor->parent->right == iter->cursor) { iter->cursor = iter->cursor->parent; iter->index--; return 1; } iter->cursor = iter->cursor->parent; } } _Bool ts_iter_advance(struct treeset_iter * iter, size_t steps) { if (iter->end) return 0; if (iter->cursor == iter->last) { iter->end = 1; return 0; } if (steps == 0 || iter->index + steps >= iter->target->count) return 0; for (size_t i = 0; i < steps; i++) ts_iter_next(iter); return 1; } _Bool ts_iter_rewind(struct treeset_iter * iter, size_t steps) { if (iter->start) return 0; if (iter->cursor == iter->first) { iter->start = 1; return 0; } if (steps == 0 || iter->index < steps) return 0; for (size_t i = 0; i < steps; i++) ts_iter_prev(iter); return 1; } _Bool ts_iter_go_to(struct treeset_iter * iter, size_t index) { if (index >= iter->target->count) return 0; if (iter->index > index) return ts_iter_rewind(iter, iter->index - index); else if (iter->index < index) return ts_iter_advance(iter, index - iter->index); return 1; } size_t ts_iter_value(struct treeset_iter * iter) { if (ts_empty(iter->target)) return (size_t){ 0 }; return iter->cursor->value; } size_t ts_iter_index(struct treeset_iter * iter) { return iter->index; } struct treeset *ts_union(struct treeset * _set1_, struct treeset * _set2_) { struct treeset *_set_r_ = ts_new_custom(_set1_->f_val, _set1_->alloc, ((void *)0)); if (!_set_r_) return ((void *)0); struct treeset_iter iter1 = ts_iter_start(_set1_); struct treeset_iter iter2 = ts_iter_start(_set2_); for (; !ts_iter_at_end(&iter1); ts_iter_next(&iter1)) { ts_insert(_set_r_, ts_iter_value(&iter1)); } for (; !ts_iter_at_end(&iter2); ts_iter_next(&iter2)) { ts_insert(_set_r_, ts_iter_value(&iter2)); } (_set_r_)->callbacks = _set1_->callbacks; return _set_r_; } struct treeset *ts_intersection(struct treeset * _set1_, struct treeset * _set2_) { struct treeset *_set_r_ = ts_new_custom(_set1_->f_val, _set1_->alloc, ((void *)0)); if (!_set_r_) return ((void *)0); struct treeset *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; struct treeset *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; struct treeset_iter iter = ts_iter_start(_set_A_); for (; !ts_iter_at_end(&iter); ts_iter_next(&iter)) { size_t value = ts_iter_value(&iter); if (ts_impl_get_node(_set_B_, value) != ((void *)0)) ts_insert(_set_r_, value); } (_set_r_)->callbacks = _set1_->callbacks; return _set_r_; } struct treeset *ts_difference(struct treeset * _set1_, struct treeset * _set2_) { struct treeset *_set_r_ = ts_new_custom(_set1_->f_val, _set1_->alloc, ((void *)0)); if (!_set_r_) return ((void *)0); struct treeset_iter iter = ts_iter_start(_set1_); for (; !ts_iter_at_end(&iter); ts_iter_next(&iter)) { size_t value = ts_iter_value(&iter); if (ts_impl_get_node(_set2_, value) == ((void *)0)) ts_insert(_set_r_, value); } (_set_r_)->callbacks = _set1_->callbacks; return _set_r_; } struct treeset *ts_symmetric_difference(struct treeset * _set1_, struct treeset * _set2_) { struct treeset *_set_r_ = ts_new_custom(_set1_->f_val, _set1_->alloc, ((void *)0)); if (!_set_r_) return ((void *)0); struct treeset_iter iter1 = ts_iter_start(_set1_); struct treeset_iter iter2 = ts_iter_start(_set2_); for (; !ts_iter_at_end(&iter1); ts_iter_next(&iter1)) { size_t value = ts_iter_value(&iter1); if (ts_impl_get_node(_set2_, value) == ((void *)0)) ts_insert(_set_r_, value); } for (; !ts_iter_at_end(&iter2); ts_iter_next(&iter2)) { size_t value = ts_iter_value(&iter2); if (ts_impl_get_node(_set1_, value) == ((void *)0)) ts_insert(_set_r_, value); } (_set_r_)->callbacks = _set1_->callbacks; return _set_r_; } _Bool ts_is_subset(struct treeset * _set1_, struct treeset * _set2_) { if (_set1_->count > _set2_->count) return 0; if (ts_empty(_set1_)) return 1; struct treeset_iter iter = ts_iter_start(_set1_); for (; !ts_iter_at_end(&iter); ts_iter_next(&iter)) { size_t value = ts_iter_value(&iter); if (ts_impl_get_node(_set2_, value) == ((void *)0)) return 0; } return 1; } _Bool ts_is_superset(struct treeset * _set1_, struct treeset * _set2_) { return ts_is_subset(_set2_, _set1_); } _Bool ts_is_proper_subset(struct treeset * _set1_, struct treeset * _set2_) { if (_set1_->count >= _set2_->count) return 0; if (ts_empty(_set1_)) { if (!ts_empty(_set2_)) return 1; else return 0; } struct treeset_iter iter = ts_iter_start(_set1_); for (; !ts_iter_at_end(&iter); ts_iter_next(&iter)) { size_t value = ts_iter_value(&iter); if (ts_impl_get_node(_set2_, value) == ((void *)0)) return 0; } return 1; } _Bool ts_is_proper_superset(struct treeset * _set1_, struct treeset * _set2_) { return ts_is_proper_subset(_set2_, _set1_); } _Bool ts_is_disjointset(struct treeset * _set1_, struct treeset * _set2_) { if (ts_empty(_set1_)) return 1; struct treeset_iter iter = ts_iter_start(_set1_); for (; !ts_iter_at_end(&iter); ts_iter_next(&iter)) { size_t value = ts_iter_value(&iter); if (ts_impl_get_node(_set2_, value) != ((void *)0)) return 0; } return 1; } _Bool ts_to_string(struct treeset * _set_, FILE * fptr) { struct treeset *s_ = _set_; return 0 <= fprintf(fptr, "struct %s<%s> " "at %p { " "root:%p, " "count:%" "I64u" ", " "flag:%d, " "f_val:%p, " "alloc:%p, " "callbacks:%p }", "treeset", "size_t", s_, s_->root, s_->count, s_->flag, s_->f_val, s_->alloc, (s_)->callbacks); } _Bool ts_print(struct treeset * _set_, FILE * fptr, const char *start, const char *separator, const char *end) { fprintf(fptr, "%s", start); struct treeset_node *root = _set_->root; _Bool left_done = 0; size_t i = 0; while (root) { if (!left_done) { while (root->left) root = root->left; } if (!_set_->f_val->str(fptr, root->value)) return 0; if (++i < _set_->count) fprintf(fptr, "%s", separator); left_done = 1; if (root->right) { left_done = 0; root = root->right; } else if (root->parent) { while (root->parent && root == root->parent->right) root = root->parent; if (!root->parent) break; root = root->parent; } else break; } fprintf(fptr, "%s", end); return 1; } - - \ No newline at end of file +static struct treeset_node *ts_impl_new_node(struct treeset *_set_, size_t value); +static struct treeset_node *ts_impl_get_node(struct treeset *_set_, size_t value); +static unsigned char ts_impl_h(struct treeset_node *node); +static unsigned char ts_impl_hupdate(struct treeset_node *node); +static void ts_impl_rotate_right(struct treeset_node **Z); +static void ts_impl_rotate_left(struct treeset_node **Z); +static void ts_impl_rebalance(struct treeset *_set_, struct treeset_node *node); +struct treeset *ts_new(struct treeset_fval *f_val) +{ + return ts_new_custom(f_val, ((void *)0), ((void *)0)); +} +struct treeset *ts_new_custom(struct treeset_fval *f_val, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks) +{ + ; + if (!f_val) + return ((void *)0); + if (!alloc) + alloc = &cmc_alloc_node_default; + struct treeset *_set_ = alloc->malloc(sizeof(struct treeset)); + if (!_set_) + return ((void *)0); + _set_->count = 0; + _set_->root = ((void *)0); + _set_->flag = CMC_FLAG_OK; + _set_->f_val = f_val; + _set_->alloc = alloc; + (_set_)->callbacks = callbacks; + return _set_; +} +void ts_clear(struct treeset *_set_) +{ + struct treeset_node *scan = _set_->root; + struct treeset_node *up = ((void *)0); + while (scan != ((void *)0)) + { + if (scan->left != ((void *)0)) + { + struct treeset_node *left = scan->left; + scan->left = up; + up = scan; + scan = left; + } + else if (scan->right != ((void *)0)) + { + struct treeset_node *right = scan->right; + scan->left = up; + scan->right = ((void *)0); + up = scan; + scan = right; + } + else + { + if (up == ((void *)0)) + { + if (_set_->f_val->free) + _set_->f_val->free(scan->value); + _set_->alloc->free(scan); + scan = ((void *)0); + } + while (up != ((void *)0)) + { + if (_set_->f_val->free) + _set_->f_val->free(scan->value); + _set_->alloc->free(scan); + if (up->right != ((void *)0)) + { + scan = up->right; + up->right = ((void *)0); + break; + } + else + { + scan = up; + up = up->left; + } + } + } + } + _set_->count = 0; + _set_->root = ((void *)0); + _set_->flag = CMC_FLAG_OK; +} +void ts_free(struct treeset *_set_) +{ + ts_clear(_set_); + _set_->alloc->free(_set_); +} +void ts_customize(struct treeset *_set_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks) +{ + ; + if (!alloc) + _set_->alloc = &cmc_alloc_node_default; + else + _set_->alloc = alloc; + (_set_)->callbacks = callbacks; + _set_->flag = CMC_FLAG_OK; +} +_Bool ts_insert(struct treeset *_set_, size_t value) +{ + if (ts_empty(_set_)) + { + _set_->root = ts_impl_new_node(_set_, value); + if (!_set_->root) + { + _set_->flag = CMC_FLAG_ALLOC; + return 0; + } + } + else + { + struct treeset_node *scan = _set_->root; + struct treeset_node *parent = scan; + while (scan != ((void *)0)) + { + parent = scan; + if (_set_->f_val->cmp(scan->value, value) > 0) + scan = scan->left; + else if (_set_->f_val->cmp(scan->value, value) < 0) + scan = scan->right; + else + { + _set_->flag = CMC_FLAG_DUPLICATE; + return 0; + } + } + struct treeset_node *node; + if (_set_->f_val->cmp(parent->value, value) > 0) + { + parent->left = ts_impl_new_node(_set_, value); + if (!parent->left) + { + _set_->flag = CMC_FLAG_ALLOC; + return 0; + } + parent->left->parent = parent; + node = parent->left; + } + else + { + parent->right = ts_impl_new_node(_set_, value); + if (!parent->right) + { + _set_->flag = CMC_FLAG_ALLOC; + return 0; + } + parent->right->parent = parent; + node = parent->right; + } + ts_impl_rebalance(_set_, node); + } + _set_->count++; + _set_->flag = CMC_FLAG_OK; + if ((_set_)->callbacks && (_set_)->callbacks->create) + (_set_)->callbacks->create(); + ; + return 1; +} +_Bool ts_remove(struct treeset *_set_, size_t value) +{ + if (ts_empty(_set_)) + { + _set_->flag = CMC_FLAG_EMPTY; + return 0; + } + struct treeset_node *node = ts_impl_get_node(_set_, value); + if (!node) + { + _set_->flag = CMC_FLAG_NOT_FOUND; + return 0; + } + struct treeset_node *temp = ((void *)0), *unbalanced = ((void *)0); + _Bool is_root = node->parent == ((void *)0); + if (node->left == ((void *)0) && node->right == ((void *)0)) + { + if (is_root) + _set_->root = ((void *)0); + else + { + unbalanced = node->parent; + if (node->parent->right == node) + node->parent->right = ((void *)0); + else + node->parent->left = ((void *)0); + } + _set_->alloc->free(node); + } + else if (node->left == ((void *)0)) + { + if (is_root) + { + _set_->root = node->right; + _set_->root->parent = ((void *)0); + } + else + { + unbalanced = node->parent; + node->right->parent = node->parent; + if (node->parent->right == node) + node->parent->right = node->right; + else + node->parent->left = node->right; + } + _set_->alloc->free(node); + } + else if (node->right == ((void *)0)) + { + if (is_root) + { + _set_->root = node->left; + _set_->root->parent = ((void *)0); + } + else + { + unbalanced = node->parent; + node->left->parent = node->parent; + if (node->parent->right == node) + node->parent->right = node->left; + else + node->parent->left = node->left; + } + _set_->alloc->free(node); + } + else + { + temp = node->right; + while (temp->left != ((void *)0)) + temp = temp->left; + size_t temp_value = temp->value; + unbalanced = temp->parent; + if (temp->left == ((void *)0) && temp->right == ((void *)0)) + { + if (temp->parent->right == temp) + temp->parent->right = ((void *)0); + else + temp->parent->left = ((void *)0); + } + else if (temp->left == ((void *)0)) + { + temp->right->parent = temp->parent; + if (temp->parent->right == temp) + temp->parent->right = temp->right; + else + temp->parent->left = temp->right; + } + else if (temp->right == ((void *)0)) + { + temp->left->parent = temp->parent; + if (temp->parent->right == temp) + temp->parent->right = temp->left; + else + temp->parent->left = temp->left; + } + _set_->alloc->free(temp); + node->value = temp_value; + } + if (unbalanced != ((void *)0)) + ts_impl_rebalance(_set_, unbalanced); + if (_set_->count == 0) + _set_->root = ((void *)0); + _set_->count--; + _set_->flag = CMC_FLAG_OK; + if ((_set_)->callbacks && (_set_)->callbacks->delete) + (_set_)->callbacks->delete (); + ; + return 1; +} +_Bool ts_max(struct treeset *_set_, size_t *value) +{ + if (ts_empty(_set_)) + { + _set_->flag = CMC_FLAG_EMPTY; + return 0; + } + struct treeset_node *scan = _set_->root; + while (scan->right != ((void *)0)) + scan = scan->right; + if (value) + *value = scan->value; + _set_->flag = CMC_FLAG_OK; + if ((_set_)->callbacks && (_set_)->callbacks->read) + (_set_)->callbacks->read(); + ; + return 1; +} +_Bool ts_min(struct treeset *_set_, size_t *value) +{ + if (ts_empty(_set_)) + { + _set_->flag = CMC_FLAG_EMPTY; + return 0; + } + struct treeset_node *scan = _set_->root; + while (scan->left != ((void *)0)) + scan = scan->left; + if (value) + *value = scan->value; + _set_->flag = CMC_FLAG_OK; + if ((_set_)->callbacks && (_set_)->callbacks->read) + (_set_)->callbacks->read(); + ; + return 1; +} +_Bool ts_contains(struct treeset *_set_, size_t value) +{ + _Bool result = ts_impl_get_node(_set_, value) != ((void *)0); + if ((_set_)->callbacks && (_set_)->callbacks->read) + (_set_)->callbacks->read(); + ; + return result; +} +_Bool ts_empty(struct treeset *_set_) +{ + return _set_->count == 0; +} +size_t ts_count(struct treeset *_set_) +{ + return _set_->count; +} +int ts_flag(struct treeset *_set_) +{ + return _set_->flag; +} +struct treeset *ts_copy_of(struct treeset *_set_) +{ + struct treeset *result = ts_new_custom(_set_->f_val, _set_->alloc, ((void *)0)); + if (!result) + { + _set_->flag = CMC_FLAG_ERROR; + return ((void *)0); + } + (result)->callbacks = _set_->callbacks; + if (!ts_empty(_set_)) + { + struct treeset_iter iter = ts_iter_start(_set_); + for (; !ts_iter_at_end(&iter); ts_iter_next(&iter)) + { + if (_set_->f_val->cpy) + ts_insert(result, _set_->f_val->cpy(ts_iter_value(&iter))); + else + ts_insert(result, ts_iter_value(&iter)); + } + } + _set_->flag = CMC_FLAG_OK; + return result; +} +_Bool ts_equals(struct treeset *_set1_, struct treeset *_set2_) +{ + _set1_->flag = CMC_FLAG_OK; + _set2_->flag = CMC_FLAG_OK; + if (_set1_->count != _set2_->count) + return 0; + struct treeset_iter iter = ts_iter_start(_set1_); + for (; !ts_iter_at_end(&iter); ts_iter_next(&iter)) + { + if (ts_impl_get_node(_set2_, ts_iter_value(&iter)) == ((void *)0)) + return 0; + } + return 1; +} +static struct treeset_node *ts_impl_new_node(struct treeset *_set_, size_t value) +{ + struct treeset_node *node = _set_->alloc->malloc(sizeof(struct treeset_node)); + if (!node) + return ((void *)0); + node->value = value; + node->right = ((void *)0); + node->left = ((void *)0); + node->parent = ((void *)0); + node->height = 0; + return node; +} +static struct treeset_node *ts_impl_get_node(struct treeset *_set_, size_t value) +{ + struct treeset_node *scan = _set_->root; + while (scan != ((void *)0)) + { + if (_set_->f_val->cmp(scan->value, value) > 0) + scan = scan->left; + else if (_set_->f_val->cmp(scan->value, value) < 0) + scan = scan->right; + else + return scan; + } + return ((void *)0); +} +static unsigned char ts_impl_h(struct treeset_node *node) +{ + if (node == ((void *)0)) + return 0; + return node->height; +} +static unsigned char ts_impl_hupdate(struct treeset_node *node) +{ + if (node == ((void *)0)) + return 0; + unsigned char h_l = ts_impl_h(node->left); + unsigned char h_r = ts_impl_h(node->right); + return 1 + (h_l > h_r ? h_l : h_r); +} +static void ts_impl_rotate_right(struct treeset_node **Z) +{ + struct treeset_node *root = *Z; + struct treeset_node *new_root = root->left; + if (root->parent != ((void *)0)) + { + if (root->parent->left == root) + root->parent->left = new_root; + else + root->parent->right = new_root; + } + new_root->parent = root->parent; + root->parent = new_root; + root->left = new_root->right; + if (root->left) + root->left->parent = root; + new_root->right = root; + root->height = ts_impl_hupdate(root); + new_root->height = ts_impl_hupdate(new_root); + *Z = new_root; +} +static void ts_impl_rotate_left(struct treeset_node **Z) +{ + struct treeset_node *root = *Z; + struct treeset_node *new_root = root->right; + if (root->parent != ((void *)0)) + { + if (root->parent->right == root) + root->parent->right = new_root; + else + root->parent->left = new_root; + } + new_root->parent = root->parent; + root->parent = new_root; + root->right = new_root->left; + if (root->right) + root->right->parent = root; + new_root->left = root; + root->height = ts_impl_hupdate(root); + new_root->height = ts_impl_hupdate(new_root); + *Z = new_root; +} +static void ts_impl_rebalance(struct treeset *_set_, struct treeset_node *node) +{ + struct treeset_node *scan = node, *child = ((void *)0); + int balance; + _Bool is_root = 0; + while (scan != ((void *)0)) + { + if (scan->parent == ((void *)0)) + is_root = 1; + scan->height = ts_impl_hupdate(scan); + balance = ts_impl_h(scan->right) - ts_impl_h(scan->left); + if (balance >= 2) + { + child = scan->right; + if (ts_impl_h(child->right) < ts_impl_h(child->left)) + ts_impl_rotate_right(&(scan->right)); + ts_impl_rotate_left(&scan); + } + else if (balance <= -2) + { + child = scan->left; + if (ts_impl_h(child->left) < ts_impl_h(child->right)) + ts_impl_rotate_left(&(scan->left)); + ts_impl_rotate_right(&scan); + } + if (is_root) + { + _set_->root = scan; + is_root = 0; + } + scan = scan->parent; + } +} +struct treeset_iter ts_iter_start(struct treeset *target) +{ + struct treeset_iter iter; + iter.target = target; + iter.cursor = target->root; + iter.first = ((void *)0); + iter.last = ((void *)0); + iter.index = 0; + iter.start = 1; + iter.end = ts_empty(target); + if (!ts_empty(target)) + { + while (iter.cursor->left != ((void *)0)) + iter.cursor = iter.cursor->left; + iter.first = iter.cursor; + iter.last = target->root; + while (iter.last->right != ((void *)0)) + iter.last = iter.last->right; + } + return iter; +} +struct treeset_iter ts_iter_end(struct treeset *target) +{ + struct treeset_iter iter; + iter.target = target; + iter.cursor = target->root; + iter.first = ((void *)0); + iter.last = ((void *)0); + iter.index = 0; + iter.start = ts_empty(target); + iter.end = 1; + if (!ts_empty(target)) + { + while (iter.cursor->right != ((void *)0)) + iter.cursor = iter.cursor->right; + iter.last = iter.cursor; + iter.first = target->root; + while (iter.first->left != ((void *)0)) + iter.first = iter.first->left; + iter.index = target->count - 1; + } + return iter; +} +_Bool ts_iter_at_start(struct treeset_iter *iter) +{ + return ts_empty(iter->target) || iter->start; +} +_Bool ts_iter_at_end(struct treeset_iter *iter) +{ + return ts_empty(iter->target) || iter->end; +} +_Bool ts_iter_to_start(struct treeset_iter *iter) +{ + if (!ts_empty(iter->target)) + { + iter->index = 0; + iter->start = 1; + iter->end = ts_empty(iter->target); + iter->cursor = iter->first; + return 1; + } + return 0; +} +_Bool ts_iter_to_end(struct treeset_iter *iter) +{ + if (!ts_empty(iter->target)) + { + iter->index = iter->target->count - 1; + iter->start = ts_empty(iter->target); + iter->end = 1; + iter->cursor = iter->last; + return 1; + } + return 0; +} +_Bool ts_iter_next(struct treeset_iter *iter) +{ + if (iter->end) + return 0; + if (iter->cursor == iter->last) + { + iter->end = 1; + return 0; + } + iter->start = ts_empty(iter->target); + if (iter->cursor->right != ((void *)0)) + { + iter->cursor = iter->cursor->right; + while (iter->cursor->left != ((void *)0)) + iter->cursor = iter->cursor->left; + iter->index++; + return 1; + } + while (1) + { + if (iter->cursor->parent->left == iter->cursor) + { + iter->cursor = iter->cursor->parent; + iter->index++; + return 1; + } + iter->cursor = iter->cursor->parent; + } +} +_Bool ts_iter_prev(struct treeset_iter *iter) +{ + if (iter->start) + return 0; + if (iter->cursor == iter->first) + { + iter->start = 1; + return 0; + } + iter->end = ts_empty(iter->target); + if (iter->cursor->left != ((void *)0)) + { + iter->cursor = iter->cursor->left; + while (iter->cursor->right != ((void *)0)) + iter->cursor = iter->cursor->right; + iter->index--; + return 1; + } + while (1) + { + if (iter->cursor->parent->right == iter->cursor) + { + iter->cursor = iter->cursor->parent; + iter->index--; + return 1; + } + iter->cursor = iter->cursor->parent; + } +} +_Bool ts_iter_advance(struct treeset_iter *iter, size_t steps) +{ + if (iter->end) + return 0; + if (iter->cursor == iter->last) + { + iter->end = 1; + return 0; + } + if (steps == 0 || iter->index + steps >= iter->target->count) + return 0; + for (size_t i = 0; i < steps; i++) + ts_iter_next(iter); + return 1; +} +_Bool ts_iter_rewind(struct treeset_iter *iter, size_t steps) +{ + if (iter->start) + return 0; + if (iter->cursor == iter->first) + { + iter->start = 1; + return 0; + } + if (steps == 0 || iter->index < steps) + return 0; + for (size_t i = 0; i < steps; i++) + ts_iter_prev(iter); + return 1; +} +_Bool ts_iter_go_to(struct treeset_iter *iter, size_t index) +{ + if (index >= iter->target->count) + return 0; + if (iter->index > index) + return ts_iter_rewind(iter, iter->index - index); + else if (iter->index < index) + return ts_iter_advance(iter, index - iter->index); + return 1; +} +size_t ts_iter_value(struct treeset_iter *iter) +{ + if (ts_empty(iter->target)) + return (size_t){ 0 }; + return iter->cursor->value; +} +size_t ts_iter_index(struct treeset_iter *iter) +{ + return iter->index; +} +struct treeset *ts_union(struct treeset *_set1_, struct treeset *_set2_) +{ + struct treeset *_set_r_ = ts_new_custom(_set1_->f_val, _set1_->alloc, ((void *)0)); + if (!_set_r_) + return ((void *)0); + struct treeset_iter iter1 = ts_iter_start(_set1_); + struct treeset_iter iter2 = ts_iter_start(_set2_); + for (; !ts_iter_at_end(&iter1); ts_iter_next(&iter1)) + { + ts_insert(_set_r_, ts_iter_value(&iter1)); + } + for (; !ts_iter_at_end(&iter2); ts_iter_next(&iter2)) + { + ts_insert(_set_r_, ts_iter_value(&iter2)); + } + (_set_r_)->callbacks = _set1_->callbacks; + return _set_r_; +} +struct treeset *ts_intersection(struct treeset *_set1_, struct treeset *_set2_) +{ + struct treeset *_set_r_ = ts_new_custom(_set1_->f_val, _set1_->alloc, ((void *)0)); + if (!_set_r_) + return ((void *)0); + struct treeset *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; + struct treeset *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; + struct treeset_iter iter = ts_iter_start(_set_A_); + for (; !ts_iter_at_end(&iter); ts_iter_next(&iter)) + { + size_t value = ts_iter_value(&iter); + if (ts_impl_get_node(_set_B_, value) != ((void *)0)) + ts_insert(_set_r_, value); + } + (_set_r_)->callbacks = _set1_->callbacks; + return _set_r_; +} +struct treeset *ts_difference(struct treeset *_set1_, struct treeset *_set2_) +{ + struct treeset *_set_r_ = ts_new_custom(_set1_->f_val, _set1_->alloc, ((void *)0)); + if (!_set_r_) + return ((void *)0); + struct treeset_iter iter = ts_iter_start(_set1_); + for (; !ts_iter_at_end(&iter); ts_iter_next(&iter)) + { + size_t value = ts_iter_value(&iter); + if (ts_impl_get_node(_set2_, value) == ((void *)0)) + ts_insert(_set_r_, value); + } + (_set_r_)->callbacks = _set1_->callbacks; + return _set_r_; +} +struct treeset *ts_symmetric_difference(struct treeset *_set1_, struct treeset *_set2_) +{ + struct treeset *_set_r_ = ts_new_custom(_set1_->f_val, _set1_->alloc, ((void *)0)); + if (!_set_r_) + return ((void *)0); + struct treeset_iter iter1 = ts_iter_start(_set1_); + struct treeset_iter iter2 = ts_iter_start(_set2_); + for (; !ts_iter_at_end(&iter1); ts_iter_next(&iter1)) + { + size_t value = ts_iter_value(&iter1); + if (ts_impl_get_node(_set2_, value) == ((void *)0)) + ts_insert(_set_r_, value); + } + for (; !ts_iter_at_end(&iter2); ts_iter_next(&iter2)) + { + size_t value = ts_iter_value(&iter2); + if (ts_impl_get_node(_set1_, value) == ((void *)0)) + ts_insert(_set_r_, value); + } + (_set_r_)->callbacks = _set1_->callbacks; + return _set_r_; +} +_Bool ts_is_subset(struct treeset *_set1_, struct treeset *_set2_) +{ + if (_set1_->count > _set2_->count) + return 0; + if (ts_empty(_set1_)) + return 1; + struct treeset_iter iter = ts_iter_start(_set1_); + for (; !ts_iter_at_end(&iter); ts_iter_next(&iter)) + { + size_t value = ts_iter_value(&iter); + if (ts_impl_get_node(_set2_, value) == ((void *)0)) + return 0; + } + return 1; +} +_Bool ts_is_superset(struct treeset *_set1_, struct treeset *_set2_) +{ + return ts_is_subset(_set2_, _set1_); +} +_Bool ts_is_proper_subset(struct treeset *_set1_, struct treeset *_set2_) +{ + if (_set1_->count >= _set2_->count) + return 0; + if (ts_empty(_set1_)) + { + if (!ts_empty(_set2_)) + return 1; + else + return 0; + } + struct treeset_iter iter = ts_iter_start(_set1_); + for (; !ts_iter_at_end(&iter); ts_iter_next(&iter)) + { + size_t value = ts_iter_value(&iter); + if (ts_impl_get_node(_set2_, value) == ((void *)0)) + return 0; + } + return 1; +} +_Bool ts_is_proper_superset(struct treeset *_set1_, struct treeset *_set2_) +{ + return ts_is_proper_subset(_set2_, _set1_); +} +_Bool ts_is_disjointset(struct treeset *_set1_, struct treeset *_set2_) +{ + if (ts_empty(_set1_)) + return 1; + struct treeset_iter iter = ts_iter_start(_set1_); + for (; !ts_iter_at_end(&iter); ts_iter_next(&iter)) + { + size_t value = ts_iter_value(&iter); + if (ts_impl_get_node(_set2_, value) != ((void *)0)) + return 0; + } + return 1; +} +_Bool ts_to_string(struct treeset *_set_, FILE *fptr) +{ + struct treeset *s_ = _set_; + return 0 <= fprintf(fptr, + "struct %s<%s> " + "at %p { " + "root:%p, " + "count:%" + "I64u" + ", " + "flag:%d, " + "f_val:%p, " + "alloc:%p, " + "callbacks:%p }", + "treeset", "size_t", s_, s_->root, s_->count, s_->flag, s_->f_val, s_->alloc, (s_)->callbacks); +} +_Bool ts_print(struct treeset *_set_, FILE *fptr, const char *start, const char *separator, const char *end) +{ + fprintf(fptr, "%s", start); + struct treeset_node *root = _set_->root; + _Bool left_done = 0; + size_t i = 0; + while (root) + { + if (!left_done) + { + while (root->left) + root = root->left; + } + if (!_set_->f_val->str(fptr, root->value)) + return 0; + if (++i < _set_->count) + fprintf(fptr, "%s", separator); + left_done = 1; + if (root->right) + { + left_done = 0; + root = root->right; + } + else if (root->parent) + { + while (root->parent && root == root->parent->right) + root = root->parent; + if (!root->parent) + break; + root = root->parent; + } + else + break; + } + fprintf(fptr, "%s", end); + return 1; +}