From 122d012ffd0203cfc41e778dc9a72f069a7cebaa Mon Sep 17 00:00:00 2001 From: Leonardo Date: Wed, 23 Oct 2019 01:14:10 -0300 Subject: [PATCH] Fast forward codecov --- tests/codecov/main.c | 27 +- tests/codecov/src/bidimap.c | 511 +++++++++++++++++++++++++++ tests/codecov/src/deque.c | 341 +++++++++++------- tests/codecov/src/hashmap.c | 451 +++++++++++++++--------- tests/codecov/src/hashset.c | 441 ++++++++++++++--------- tests/codecov/src/heap.c | 309 ++++++++++------ tests/codecov/src/intervalheap.c | 588 +++++++++++++++++++++++++++++++ tests/codecov/src/linkedlist.c | 398 +++++++++++++-------- tests/codecov/src/list.c | 408 ++++++++++++--------- tests/codecov/src/multimap.c | 548 ++++++++++++++++++---------- tests/codecov/src/multiset.c | 475 +++++++++++++++---------- tests/codecov/src/queue.c | 310 ++++++++++------ tests/codecov/src/sortedlist.c | 431 ++++++++++++++++++++++ tests/codecov/src/stack.c | 270 ++++++++------ tests/codecov/src/treemap.c | 430 +++++++++++++--------- tests/codecov/src/treeset.c | 443 +++++++++++++---------- tests/codecov/unt/bidimap.c | 33 ++ tests/codecov/unt/deque.c | 588 ++++++++++++++++++++++++++++++- tests/codecov/unt/hashmap.c | 425 +++++++++++++++++++++- tests/codecov/unt/hashset.c | 330 ++++++++++++++++- tests/codecov/unt/heap.c | 124 ++++++- tests/codecov/unt/intervalheap.c | 132 +++++++ tests/codecov/unt/linkedlist.c | 26 +- tests/codecov/unt/list.c | 105 +++--- tests/codecov/unt/multimap.c | 87 ++--- tests/codecov/unt/multiset.c | 99 +++++- tests/codecov/unt/queue.c | 365 ++++++++++++++++++- tests/codecov/unt/sortedlist.c | 138 ++++++++ tests/codecov/unt/stack.c | 159 ++++----- tests/codecov/unt/treemap.c | 16 +- tests/codecov/unt/treeset.c | 16 +- tests/codecov/unt/utl.c | 21 ++ 32 files changed, 6944 insertions(+), 2101 deletions(-) create mode 100644 tests/codecov/src/bidimap.c create mode 100644 tests/codecov/src/intervalheap.c create mode 100644 tests/codecov/src/sortedlist.c create mode 100644 tests/codecov/unt/bidimap.c create mode 100644 tests/codecov/unt/intervalheap.c create mode 100644 tests/codecov/unt/sortedlist.c diff --git a/tests/codecov/main.c b/tests/codecov/main.c index 2303be1..8828fcf 100644 --- a/tests/codecov/main.c +++ b/tests/codecov/main.c @@ -1,35 +1,50 @@ +#include + +#include "unt/bidimap.c" #include "unt/deque.c" #include "unt/hashmap.c" #include "unt/hashset.c" #include "unt/heap.c" +#include "unt/intervalheap.c" #include "unt/linkedlist.c" #include "unt/list.c" +#include "unt/multimap.c" +#include "unt/multiset.c" #include "unt/queue.c" +#include "unt/sortedlist.c" #include "unt/stack.c" #include "unt/treemap.c" #include "unt/treeset.c" -#include "unt/multimap.c" -#include "unt/multiset.c" - int main(void) { + cmc_timer timer; + + cmc_timer_start(timer); uintmax_t failed = 0; + failed += bidimap_test(); failed += deque_test(); failed += hashmap_test(); failed += hashset_test(); failed += heap_test(); + failed += intervalheap_test(); failed += linkedlist_test(); failed += list_test(); + failed += multimap_test(); + failed += multiset_test(); failed += queue_test(); + failed += sortedlist_test(); failed += stack_test(); failed += treemap_test(); failed += treeset_test(); - /* ext */ - failed += multimap_test(); - failed += multiset_test(); + cmc_timer_stop(timer); + cmc_timer_calc(timer); + + printf("+--------------------------------------------------+\n"); + printf("| Total running time : %14.0lf milliseconds |\n", timer.result); + printf("+--------------------------------------------------+\n"); return failed; } diff --git a/tests/codecov/src/bidimap.c b/tests/codecov/src/bidimap.c new file mode 100644 index 0000000..fe5cce2 --- /dev/null +++ b/tests/codecov/src/bidimap.c @@ -0,0 +1,511 @@ +#include + +//CMC_GENERATE_BIDIMAP(bm, bidimap, size_t, size_t) + +typedef struct bidimap_s +{ + struct bidimap_entry_s **key_buffer; + struct bidimap_entry_s **val_buffer; + size_t capacity; + size_t count; + double load; + int (*key_cmp)(size_t, size_t); + int (*val_cmp)(size_t, size_t); + size_t (*key_hash)(size_t); + size_t (*val_hash)(size_t); + struct bidimap_iter_s (*it_start)(struct bidimap_s *); + struct bidimap_iter_s (*it_end)(struct bidimap_s *); +} bidimap, *bidimap_ptr; +typedef struct bidimap_entry_s +{ + size_t key; + size_t value; + size_t key_dist; + size_t val_dist; +} bidimap_entry, *bidimap_entry_ptr; +typedef struct bidimap_iter_s +{ + struct bidimap_s *target; + size_t cursor; + size_t index; + size_t first; + size_t last; + _Bool start; + _Bool end; +} bidimap_iter, *bidimap_iter_ptr; +bidimap *bm_new(size_t capacity, double load, int (*key_cmp)(size_t, size_t), size_t (*key_hash)(size_t), int (*val_cmp)(size_t, size_t), size_t (*val_hash)(size_t)); +void bm_clear(bidimap *_map_, void (*deallocator)(size_t, size_t)); +void bm_free(bidimap *_map_, void (*deallocator)(size_t, size_t)); +_Bool bm_insert(bidimap *_map_, size_t key, size_t value); +_Bool bm_update_key(bidimap *_map_, size_t key, size_t *old_key); +_Bool bm_update_val(bidimap *_map_, size_t val, size_t *old_val); +_Bool bm_remove_by_key(bidimap *_map_, size_t key, size_t *out_value); +_Bool bm_remove_by_val(bidimap *_map_, size_t value, size_t *out_key); +size_t bm_get_key(bidimap *_map_, size_t val); +size_t bm_get_val(bidimap *_map_, size_t key); +_Bool bm_contains_key(bidimap *_map_, size_t key); +_Bool bm_contains_val(bidimap *_map_, size_t val); +_Bool bm_empty(bidimap *_map_); +_Bool bm_full(bidimap *_map_); +size_t bm_count(bidimap *_map_); +size_t bm_capacity(bidimap *_map_); +double bm_load(bidimap *_map_); +bidimap *bm_copy_of(bidimap *_map_, size_t (*key_copy_func)(size_t), size_t (*value_copy_func)(size_t)); +_Bool bm_equals(bidimap *_map1_, bidimap *_map2_); +cmc_string bm_to_string(bidimap *_map_); +bidimap_iter *bm_iter_new(bidimap *target); +void bm_iter_free(bidimap_iter *iter); +void bm_iter_init(bidimap_iter *iter, bidimap *target); +_Bool bm_iter_start(bidimap_iter *iter); +_Bool bm_iter_end(bidimap_iter *iter); +void bm_iter_to_start(bidimap_iter *iter); +void bm_iter_to_end(bidimap_iter *iter); +_Bool bm_iter_next(bidimap_iter *iter); +_Bool bm_iter_prev(bidimap_iter *iter); +_Bool bm_iter_advance(bidimap_iter *iter, size_t steps); +_Bool bm_iter_rewind(bidimap_iter *iter, size_t steps); +_Bool bm_iter_go_to(bidimap_iter *iter, size_t index); +size_t bm_iter_key(bidimap_iter *iter); +size_t bm_iter_value(bidimap_iter *iter); +size_t bm_iter_index(bidimap_iter *iter); +static _Bool bm_impl_grow(bidimap *_map_); +static bidimap_entry *bm_impl_new_entry(size_t key, size_t value); +static bidimap_entry **bm_impl_get_entry_by_key(bidimap *_map_, size_t key); +static bidimap_entry **bm_impl_get_entry_by_val(bidimap *_map_, size_t val); +static bidimap_entry **bm_impl_add_entry_to_key(bidimap *_map_, bidimap_entry *entry); +static bidimap_entry **bm_impl_add_entry_to_val(bidimap *_map_, bidimap_entry *entry); +static size_t bm_impl_calculate_size(size_t required); +static bidimap_iter bm_impl_it_start(bidimap *_map_); +static bidimap_iter bm_impl_it_end(bidimap *_map_); +bidimap *bm_new(size_t capacity, double load, int (*key_cmp)(size_t, size_t), size_t (*key_hash)(size_t), int (*val_cmp)(size_t, size_t), size_t (*val_hash)(size_t)) +{ + if (capacity == 0 || load <= 0 || load >= 1) + return ((void *)0); + if (capacity >= 0xffffffffffffffff * load) + return ((void *)0); + size_t real_capacity = bm_impl_calculate_size(capacity / load); + bidimap *_map_ = malloc(sizeof(bidimap)); + if (!_map_) + return ((void *)0); + _map_->key_buffer = calloc(real_capacity, sizeof(bidimap_entry *)); + _map_->val_buffer = calloc(real_capacity, sizeof(bidimap_entry *)); + if (!_map_->key_buffer || !_map_->val_buffer) + { + free(_map_->key_buffer); + free(_map_->val_buffer); + free(_map_); + return ((void *)0); + } + _map_->count = 0; + _map_->capacity = real_capacity; + _map_->load = load; + _map_->key_cmp = key_cmp; + _map_->val_cmp = val_cmp; + _map_->key_hash = key_hash; + _map_->val_hash = val_hash; + _map_->it_start = bm_impl_it_start; + _map_->it_end = bm_impl_it_end; + return _map_; +} +void bm_clear(bidimap *_map_, void (*deallocator)(size_t, size_t)) +{ + for (size_t i = 0; i < _map_->capacity; i++) + { + bidimap_entry *entry = _map_->key_buffer[i]; + if (entry != ((void *)0) && entry != ((void *)1)) + { + if (deallocator) + deallocator(entry->key, entry->value); + free(entry); + } + _map_->key_buffer[i] = ((void *)0); + _map_->val_buffer[i] = ((void *)0); + } + _map_->count = 0; +} +void bm_free(bidimap *_map_, void (*deallocator)(size_t, size_t)) +{ + bm_clear(_map_, deallocator); + free(_map_->key_buffer); + free(_map_->val_buffer); + free(_map_); +} +_Bool bm_insert(bidimap *_map_, size_t key, size_t value) +{ + if (bm_full(_map_)) + { + if (!bm_impl_grow(_map_)) + return 0; + } + if (bm_impl_get_entry_by_key(_map_, key) != ((void *)0) || bm_impl_get_entry_by_val(_map_, value) != ((void *)0)) + return 0; + bidimap_entry *entry = bm_impl_new_entry(key, value); + bidimap_entry **key_entry = bm_impl_add_entry_to_key(_map_, entry); + bidimap_entry **val_entry = bm_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); + free(entry); + return 0; + } + _map_->count++; + return 1; +} +_Bool bm_update_key(bidimap *_map_, size_t key, size_t *old_key) +{ + if (bm_empty(_map_)) + return 0; + return 1; +} +_Bool bm_update_val(bidimap *_map_, size_t val, size_t *old_val) +{ + if (bm_empty(_map_)) + return 0; + return 1; +} +_Bool bm_remove_by_key(bidimap *_map_, size_t key, size_t *out_value) +{ + if (bm_empty(_map_)) + return 0; + return 1; +} +_Bool bm_remove_by_val(bidimap *_map_, size_t value, size_t *out_key) +{ + if (bm_empty(_map_)) + return 0; + return 1; +} +size_t bm_get_key(bidimap *_map_, size_t val) +{ + bidimap_entry **entry = bm_impl_get_entry_by_val(_map_, val); + if (!entry) + return (size_t){0}; + return (*entry)->key; +} +size_t bm_get_val(bidimap *_map_, size_t key) +{ + bidimap_entry **entry = bm_impl_get_entry_by_key(_map_, key); + if (!entry) + return (size_t){0}; + return (*entry)->value; +} +_Bool bm_contains_key(bidimap *_map_, size_t key) { return bm_impl_get_entry_by_key(_map_, key) != ((void *)0); } +_Bool bm_contains_val(bidimap *_map_, size_t val) { return bm_impl_get_entry_by_val(_map_, val) != ((void *)0); } +_Bool bm_empty(bidimap *_map_) { return _map_->count == 0; } +_Bool bm_full(bidimap *_map_) { return (double)bm_capacity(_map_) * bm_load(_map_) <= (double)bm_count(_map_); } +size_t bm_count(bidimap *_map_) { return _map_->count; } +size_t bm_capacity(bidimap *_map_) { return _map_->capacity; } +double bm_load(bidimap *_map_) { return _map_->load; } +bidimap *bm_copy_of(bidimap *_map_, size_t (*key_copy_func)(size_t), size_t (*value_copy_func)(size_t)) { return ((void *)0); } +_Bool bm_equals(bidimap *_map1_, bidimap *_map2_) { return 0; } +cmc_string bm_to_string(bidimap *_map_) +{ + cmc_string str; + bidimap *m_ = _map_; + const char *name = "bidimap"; + snprintf(str.s, cmc_string_len, cmc_string_fmt_bidimap, name, m_, m_->key_buffer, m_->val_buffer, m_->capacity, m_->count, m_->load, m_->key_cmp, m_->val_cmp, m_->key_hash, m_->val_hash); + return str; +} +bidimap_iter *bm_iter_new(bidimap *target) +{ + bidimap_iter *iter = malloc(sizeof(bidimap_iter)); + if (!iter) + return ((void *)0); + bm_iter_init(iter, target); + return iter; +} +void bm_iter_free(bidimap_iter *iter) { free(iter); } +void bm_iter_init(bidimap_iter *iter, bidimap *target) +{ + memset(iter, 0, sizeof(bidimap_iter)); + iter->target = target; + iter->start = 1; + iter->end = bm_empty(target); + if (!bm_empty(target)) + { + for (size_t i = 0; i < target->capacity; i++) + { + bidimap_entry *tmp = target->key_buffer[i]; + if (tmp != ((void *)0) && tmp != ((void *)1)) + { + iter->first = i; + break; + } + } + iter->cursor = iter->first; + for (size_t i = target->capacity; i > 0; i--) + { + bidimap_entry *tmp = target->key_buffer[i - 1]; + if (tmp != ((void *)0) && tmp != ((void *)1)) + { + iter->last = i - 1; + break; + } + } + } +} +_Bool bm_iter_start(bidimap_iter *iter) { return bm_empty(iter->target) || iter->start; } +_Bool bm_iter_end(bidimap_iter *iter) { return bm_empty(iter->target) || iter->end; } +void bm_iter_to_start(bidimap_iter *iter) +{ + if (!bm_empty(iter->target)) + { + iter->cursor = iter->first; + iter->index = 0; + iter->start = 1; + iter->end = 0; + } +} +void bm_iter_to_end(bidimap_iter *iter) +{ + if (!bm_empty(iter->target)) + { + iter->cursor = iter->last; + iter->index = bm_count(iter->target) - 1; + iter->start = 0; + iter->end = 1; + } +} +_Bool bm_iter_next(bidimap_iter *iter) +{ + if (iter->end) + return 0; + if (iter->index + 1 == bm_count(iter->target)) + { + iter->end = 1; + return 0; + } + iter->start = bm_empty(iter->target); + bidimap_entry *scan = iter->target->key_buffer[iter->cursor]; + iter->index++; + while (1) + { + iter->cursor++; + scan = iter->target->key_buffer[iter->cursor]; + if (scan != ((void *)0) && scan != ((void *)1)) + break; + } + return 1; +} +_Bool bm_iter_prev(bidimap_iter *iter) +{ + if (iter->start) + return 0; + if (iter->index == 0) + { + iter->start = 1; + return 0; + } + iter->end = bm_empty(iter->target); + bidimap_entry *scan = iter->target->key_buffer[iter->cursor]; + iter->index--; + while (1) + { + iter->cursor--; + scan = iter->target->key_buffer[iter->cursor]; + if (scan != ((void *)0) && scan != ((void *)1)) + break; + } + return 1; +} +_Bool bm_iter_advance(bidimap_iter *iter, size_t steps) +{ + if (iter->end) + return 0; + if (iter->index + 1 == bm_count(iter->target)) + { + iter->end = 1; + return 0; + } + if (steps == 0 || iter->index + steps >= bm_count(iter->target)) + return 0; + for (size_t i = 0; i < steps; i++) + bm_iter_next(iter); + return 1; +} +_Bool bm_iter_rewind(bidimap_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++) + bm_iter_prev(iter); + return 1; +} +_Bool bm_iter_go_to(bidimap_iter *iter, size_t index) +{ + if (index >= bm_count(iter->target)) + return 0; + if (iter->index > index) + return bm_iter_rewind(iter, iter->index - index); + else if (iter->index < index) + return bm_iter_advance(iter, index - iter->index); + return 1; +} +size_t bm_iter_key(bidimap_iter *iter) +{ + if (bm_empty(iter->target)) + return (size_t){0}; + return iter->target->key_buffer[iter->cursor]->key; +} +size_t bm_iter_value(bidimap_iter *iter) +{ + if (bm_empty(iter->target)) + return (size_t){0}; + return iter->target->key_buffer[iter->cursor]->value; +} +size_t bm_iter_index(bidimap_iter *iter) { return iter->index; } +static _Bool bm_impl_grow(bidimap *_map_) { return 0; } +static bidimap_entry *bm_impl_new_entry(size_t key, size_t value) +{ + bidimap_entry *entry = malloc(sizeof(bidimap_entry)); + if (!entry) + return ((void *)0); + entry->key = key; + entry->value = value; + entry->key_dist = 0; + entry->val_dist = 0; + return entry; +} +static bidimap_entry **bm_impl_get_entry_by_key(bidimap *_map_, size_t key) +{ + size_t hash = _map_->key_hash(key); + size_t pos = hash % _map_->capacity; + bidimap_entry *target = _map_->key_buffer[pos]; + while (target != ((void *)0)) + { + if (target != ((void *)1) && _map_->key_cmp(target->key, key) == 0) + return &(_map_->key_buffer[pos % _map_->capacity]); + pos++; + target = _map_->key_buffer[pos % _map_->capacity]; + } + return ((void *)0); +} +static bidimap_entry **bm_impl_get_entry_by_val(bidimap *_map_, size_t val) +{ + size_t hash = _map_->val_hash(val); + size_t pos = hash % _map_->capacity; + bidimap_entry *target = _map_->val_buffer[pos]; + while (target != ((void *)0)) + { + if (target != ((void *)1) && _map_->val_cmp(target->value, val) == 0) + return &(_map_->val_buffer[pos % _map_->capacity]); + pos++; + target = _map_->val_buffer[pos % _map_->capacity]; + } + return ((void *)0); +} +static bidimap_entry **bm_impl_add_entry_to_key(bidimap *_map_, bidimap_entry *entry) +{ + bidimap_entry **to_return = ((void *)0); + size_t hash = _map_->key_hash(entry->key); + size_t original_pos = hash % _map_->capacity; + size_t pos = original_pos; + bidimap_entry **scan = &(_map_->key_buffer[hash % _map_->capacity]); + if (*scan == ((void *)0)) + { + *scan = entry; + return scan; + } + else + { + while (1) + { + pos++; + scan = &(_map_->key_buffer[pos % _map_->capacity]); + if (*scan == ((void *)0) || *scan == ((void *)1)) + { + if (!to_return) + to_return = scan; + *scan = entry; + entry->key_dist = pos - original_pos; + return to_return; + } + else if ((*scan)->key_dist < pos - original_pos) + { + if (!to_return) + to_return = scan; + size_t tmp_dist = (*scan)->key_dist; + entry->key_dist = pos - original_pos; + original_pos = pos - tmp_dist; + bidimap_entry *_tmp_ = *scan; + *scan = entry; + entry = _tmp_; + } + } + } + return ((void *)0); +} +static bidimap_entry **bm_impl_add_entry_to_val(bidimap *_map_, bidimap_entry *entry) +{ + bidimap_entry **to_return = ((void *)0); + size_t hash = _map_->val_hash(entry->value); + size_t original_pos = hash % _map_->capacity; + size_t pos = original_pos; + bidimap_entry **scan = &(_map_->val_buffer[hash % _map_->capacity]); + if (*scan == ((void *)0)) + { + *scan = entry; + return scan; + } + else + { + while (1) + { + pos++; + scan = &(_map_->val_buffer[pos % _map_->capacity]); + if (*scan == ((void *)0) || *scan == ((void *)1)) + { + if (!to_return) + to_return = scan; + *scan = entry; + entry->val_dist = pos - original_pos; + return to_return; + } + else if ((*scan)->val_dist < pos - original_pos) + { + if (!to_return) + to_return = scan; + size_t tmp_dist = (*scan)->val_dist; + entry->val_dist = pos - original_pos; + original_pos = pos - tmp_dist; + bidimap_entry *_tmp_ = *scan; + *scan = entry; + entry = _tmp_; + } + } + } + return ((void *)0); +} +static size_t bm_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 bidimap_iter bm_impl_it_start(bidimap *_map_) +{ + bidimap_iter iter; + bm_iter_init(&iter, _map_); + return iter; +} +static bidimap_iter bm_impl_it_end(bidimap *_map_) +{ + bidimap_iter iter; + bm_iter_init(&iter, _map_); + bm_iter_to_end(&iter); + return iter; +} diff --git a/tests/codecov/src/deque.c b/tests/codecov/src/deque.c index cff7d58..e70d835 100644 --- a/tests/codecov/src/deque.c +++ b/tests/codecov/src/deque.c @@ -1,6 +1,6 @@ -#include "cmc/deque.h" +#include -//DEQUE_GENERATE(d, deque, , size_t) +//CMC_GENERATE_DEQUE(d, deque, size_t) typedef struct deque_s { @@ -17,60 +17,56 @@ typedef struct deque_iter_s struct deque_s *target; size_t cursor; size_t index; - bool start; - bool end; + _Bool start; + _Bool end; } deque_iter, *deque_iter_ptr; deque *d_new(size_t capacity); -void d_clear(deque *_deque_); -void d_free(deque *_deque_); -bool d_push_front(deque *_deque_, size_t element); -bool d_push_back(deque *_deque_, size_t element); -bool d_pop_front(deque *_deque_); -bool d_pop_back(deque *_deque_); -bool d_push_front_if(deque *_deque_, size_t element, bool condition); -bool d_push_back_if(deque *_deque_, size_t element, bool condition); -bool d_pop_front_if(deque *_deque_, bool condition); -bool d_pop_back_if(deque *_deque_, bool condition); +void d_clear(deque *_deque_, void (*deallocator)(size_t)); +void d_free(deque *_deque_, void (*deallocator)(size_t)); +_Bool d_push_front(deque *_deque_, size_t element); +_Bool d_push_back(deque *_deque_, size_t element); +_Bool d_pop_front(deque *_deque_); +_Bool d_pop_back(deque *_deque_); size_t d_front(deque *_deque_); size_t d_back(deque *_deque_); -bool d_contains(deque *_deque_, size_t element, int (*comparator)(size_t, size_t)); -bool d_empty(deque *_deque_); -bool d_full(deque *_deque_); +_Bool d_contains(deque *_deque_, size_t element, int (*comparator)(size_t, size_t)); +_Bool d_empty(deque *_deque_); +_Bool d_full(deque *_deque_); size_t d_count(deque *_deque_); size_t d_capacity(deque *_deque_); +_Bool d_resize(deque *_deque_, size_t capacity); +deque *d_copy_of(deque *_deque_, size_t (*copy_func)(size_t)); +_Bool d_equals(deque *_deque1_, deque *_deque2_, int (*comparator)(size_t, size_t)); +cmc_string d_to_string(deque *_deque_); deque_iter *d_iter_new(deque *target); void d_iter_free(deque_iter *iter); void d_iter_init(deque_iter *iter, deque *target); -bool d_iter_start(deque_iter *iter); -bool d_iter_end(deque_iter *iter); +_Bool d_iter_start(deque_iter *iter); +_Bool d_iter_end(deque_iter *iter); void d_iter_to_start(deque_iter *iter); void d_iter_to_end(deque_iter *iter); -bool d_iter_next(deque_iter *iter); -bool d_iter_prev(deque_iter *iter); +_Bool d_iter_next(deque_iter *iter); +_Bool d_iter_prev(deque_iter *iter); +_Bool d_iter_advance(deque_iter *iter, size_t steps); +_Bool d_iter_rewind(deque_iter *iter, size_t steps); +_Bool d_iter_go_to(deque_iter *iter, size_t index); size_t d_iter_value(deque_iter *iter); size_t *d_iter_rvalue(deque_iter *iter); size_t d_iter_index(deque_iter *iter); -static inline size_t d_impl_default_value(void) -{ - size_t _empty_value_; - memset(&_empty_value_, 0, sizeof(size_t)); - return _empty_value_; -} -static bool d_impl_grow(deque *_deque_); static deque_iter d_impl_it_start(deque *_deque_); static deque_iter d_impl_it_end(deque *_deque_); deque *d_new(size_t capacity) { if (capacity < 1) - return NULL; + return ((void *)0); deque *_deque_ = malloc(sizeof(deque)); if (!_deque_) - return NULL; + return ((void *)0); _deque_->buffer = malloc(sizeof(size_t) * capacity); if (!_deque_->buffer) { free(_deque_); - return NULL; + return ((void *)0); } memset(_deque_->buffer, 0, sizeof(size_t) * capacity); _deque_->capacity = capacity; @@ -81,114 +77,174 @@ deque *d_new(size_t capacity) _deque_->it_end = d_impl_it_end; return _deque_; } -void d_clear(deque *_deque_) +void d_clear(deque *_deque_, void (*deallocator)(size_t)) { + if (deallocator) + { + for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) + { + deallocator(_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; } -void d_free(deque *_deque_) +void d_free(deque *_deque_, void (*deallocator)(size_t)) { + if (deallocator) + { + for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) + { + deallocator(_deque_->buffer[i]); + i = (i + 1) % _deque_->capacity; + } + } free(_deque_->buffer); free(_deque_); } -bool d_push_front(deque *_deque_, size_t element) +_Bool d_push_front(deque *_deque_, size_t element) { if (d_full(_deque_)) { - if (!d_impl_grow(_deque_)) - return false; + if (!d_resize(_deque_, d_capacity(_deque_) * 2)) + return 0; } _deque_->front = (_deque_->front == 0) ? _deque_->capacity - 1 : _deque_->front - 1; _deque_->buffer[_deque_->front] = element; _deque_->count++; - return true; + return 1; } -bool d_push_back(deque *_deque_, size_t element) +_Bool d_push_back(deque *_deque_, size_t element) { if (d_full(_deque_)) { - if (!d_impl_grow(_deque_)) - return false; + if (!d_resize(_deque_, d_capacity(_deque_) * 2)) + return 0; } _deque_->buffer[_deque_->back] = element; _deque_->back = (_deque_->back == _deque_->capacity - 1) ? 0 : _deque_->back + 1; _deque_->count++; - return true; + return 1; } -bool d_pop_front(deque *_deque_) +_Bool d_pop_front(deque *_deque_) { if (d_empty(_deque_)) - return false; - _deque_->buffer[_deque_->front] = d_impl_default_value(); + return 0; + _deque_->buffer[_deque_->front] = (size_t){0}; _deque_->front = (_deque_->front == _deque_->capacity - 1) ? 0 : _deque_->front + 1; _deque_->count--; - return true; + return 1; } -bool d_pop_back(deque *_deque_) +_Bool d_pop_back(deque *_deque_) { if (d_empty(_deque_)) - return false; + return 0; _deque_->back = (_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1; - _deque_->buffer[_deque_->back] = d_impl_default_value(); + _deque_->buffer[_deque_->back] = (size_t){0}; _deque_->count--; - return true; -} -bool d_push_front_if(deque *_deque_, size_t element, bool condition) -{ - if (condition) - return d_push_front(_deque_, element); - return false; -} -bool d_push_back_if(deque *_deque_, size_t element, bool condition) -{ - if (condition) - return d_push_back(_deque_, element); - return false; -} -bool d_pop_front_if(deque *_deque_, bool condition) -{ - if (condition) - return d_pop_front(_deque_); - return false; -} -bool d_pop_back_if(deque *_deque_, bool condition) -{ - if (condition) - return d_pop_back(_deque_); - return false; + return 1; } size_t d_front(deque *_deque_) { if (d_empty(_deque_)) - return d_impl_default_value(); + return (size_t){0}; return _deque_->buffer[_deque_->front]; } size_t d_back(deque *_deque_) { if (d_empty(_deque_)) - return d_impl_default_value(); + return (size_t){0}; return _deque_->buffer[(_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1]; } -bool d_contains(deque *_deque_, size_t element, int (*comparator)(size_t, size_t)) +_Bool d_contains(deque *_deque_, size_t element, int (*comparator)(size_t, size_t)) { - for (size_t i = _deque_->front, j = 0; j < _deque_->count; i = (i + 1) % _deque_->count, j++) + for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) { if (comparator(_deque_->buffer[i], element) == 0) - return true; + return 1; + i = (i + 1) % _deque_->capacity; } - return false; + return 0; } -bool d_empty(deque *_deque_) { return _deque_->count == 0; } -bool d_full(deque *_deque_) { return _deque_->count >= _deque_->capacity; } +_Bool d_empty(deque *_deque_) { return _deque_->count == 0; } +_Bool d_full(deque *_deque_) { return _deque_->count >= _deque_->capacity; } size_t d_count(deque *_deque_) { return _deque_->count; } size_t d_capacity(deque *_deque_) { return _deque_->capacity; } +_Bool d_resize(deque *_deque_, size_t capacity) +{ + if (d_capacity(_deque_) == capacity) + return 1; + if (capacity < d_count(_deque_)) + return 0; + size_t *new_buffer = malloc(sizeof(size_t) * capacity); + if (!new_buffer) + return 0; + for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) + { + new_buffer[j] = _deque_->buffer[i]; + i = (i + 1) % d_capacity(_deque_); + } + free(_deque_->buffer); + _deque_->buffer = new_buffer; + _deque_->capacity = capacity; + _deque_->front = 0; + _deque_->back = _deque_->count; + return 1; +} +deque *d_copy_of(deque *_deque_, size_t (*copy_func)(size_t)) +{ + deque *result = d_new(_deque_->capacity); + if (!result) + return ((void *)0); + if (copy_func) + { + for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) + { + result->buffer[j] = copy_func(_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; + return result; +} +_Bool d_equals(deque *_deque1_, deque *_deque2_, int (*comparator)(size_t, size_t)) +{ + if (d_count(_deque1_) != d_count(_deque2_)) + return 0; + size_t i, j, k; + for (i = _deque1_->front, j = _deque2_->front, k = 0; k < d_count(_deque1_); k++) + { + if (comparator(_deque1_->buffer[i], _deque2_->buffer[j]) != 0) + return 0; + i = (i + 1) % _deque1_->capacity; + j = (j + 1) % _deque2_->capacity; + } + return 1; +} +cmc_string d_to_string(deque *_deque_) +{ + cmc_string str; + deque *d_ = _deque_; + const char *name = "deque"; + snprintf(str.s, cmc_string_len, cmc_string_fmt_deque, name, d_, d_->buffer, d_->capacity, d_->count, d_->front, d_->back); + return str; +} deque_iter *d_iter_new(deque *target) { deque_iter *iter = malloc(sizeof(deque_iter)); if (!iter) - return NULL; + return ((void *)0); d_iter_init(iter, target); return iter; } @@ -198,86 +254,121 @@ void d_iter_init(deque_iter *iter, deque *target) iter->target = target; iter->cursor = target->front; iter->index = 0; - iter->start = true; + iter->start = 1; iter->end = d_empty(target); } -bool d_iter_start(deque_iter *iter) { return d_empty(iter->target) || iter->start; } -bool d_iter_end(deque_iter *iter) { return d_empty(iter->target) || iter->end; } +_Bool d_iter_start(deque_iter *iter) { return d_empty(iter->target) || iter->start; } +_Bool d_iter_end(deque_iter *iter) { return d_empty(iter->target) || iter->end; } void d_iter_to_start(deque_iter *iter) { iter->cursor = iter->target->front; iter->index = 0; - iter->start = true; + iter->start = 1; iter->end = d_empty(iter->target); } void d_iter_to_end(deque_iter *iter) { if (d_empty(iter->target)) + { iter->cursor = 0; + iter->index = 0; + } else - iter->cursor = (iter->target->back == 0) ? iter->target->capacity - 1 : iter->target->back - 1; - iter->index = iter->target->count - 1; + { + if (iter->target->back == 0) + iter->cursor = iter->target->capacity - 1; + else + iter->cursor = iter->target->back - 1; + iter->index = d_count(iter->target) - 1; + } iter->start = d_empty(iter->target); - iter->end = true; + iter->end = 1; } -bool d_iter_next(deque_iter *iter) +_Bool d_iter_next(deque_iter *iter) { if (iter->end) - return false; - iter->start = d_empty(iter->target); - if (iter->index == iter->target->count - 1) - iter->end = true; - else + return 0; + if (iter->index + 1 == d_count(iter->target)) { - iter->cursor = (iter->cursor + 1) % (iter->target->capacity); - iter->index++; + iter->end = 1; + return 0; } - return true; + iter->start = d_empty(iter->target); + iter->cursor = (iter->cursor + 1) % (iter->target->capacity); + iter->index++; + return 1; } -bool d_iter_prev(deque_iter *iter) +_Bool d_iter_prev(deque_iter *iter) { if (iter->start) - return false; - iter->end = d_empty(iter->target); + return 0; if (iter->index == 0) - iter->start = true; - else { - iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; - iter->index--; + iter->start = 1; + return 0; } - return true; + 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(deque_iter *iter, size_t steps) +{ + if (iter->end) + return 0; + if (iter->index + 1 == d_count(iter->target)) + { + iter->end = 1; + return 0; + } + if (steps == 0 || iter->index + steps >= d_count(iter->target)) + 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(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 += d_capacity(iter->target); + iter->cursor -= steps; + return 1; +} +_Bool d_iter_go_to(deque_iter *iter, size_t index) +{ + if (index >= d_count(iter->target)) + 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(deque_iter *iter) { if (d_empty(iter->target)) - return d_impl_default_value(); + return (size_t){0}; return iter->target->buffer[iter->cursor]; } size_t *d_iter_rvalue(deque_iter *iter) { if (d_empty(iter->target)) - return NULL; + return ((void *)0); return &(iter->target->buffer[iter->cursor]); } size_t d_iter_index(deque_iter *iter) { return iter->index; } -static bool d_impl_grow(deque *_deque_) -{ - size_t new_capacity = _deque_->capacity * 2; - size_t *new_buffer = malloc(sizeof(size_t) * new_capacity); - if (!new_buffer) - return false; - for (size_t i = _deque_->front, j = 0; j < _deque_->count; i = (i + 1) % _deque_->capacity, j++) - { - new_buffer[j] = _deque_->buffer[i]; - } - free(_deque_->buffer); - _deque_->buffer = new_buffer; - _deque_->capacity = new_capacity; - _deque_->front = 0; - _deque_->back = _deque_->count; - return true; -} static deque_iter d_impl_it_start(deque *_deque_) { deque_iter iter; diff --git a/tests/codecov/src/hashmap.c b/tests/codecov/src/hashmap.c index 816b9bc..cc41969 100644 --- a/tests/codecov/src/hashmap.c +++ b/tests/codecov/src/hashmap.c @@ -1,6 +1,6 @@ -#include "cmc/hashmap.h" +#include -//HASHMAP_GENERATE(hm, hashmap, , size_t, size_t) +//CMC_GENERATE_HASHMAP(hm, hashmap, size_t, size_t) typedef struct hashmap_s { @@ -27,51 +27,45 @@ typedef struct hashmap_iter_s size_t index; size_t first; size_t last; - bool start; - bool end; + _Bool start; + _Bool end; } hashmap_iter, *hashmap_iter_ptr; hashmap *hm_new(size_t capacity, double load, int (*compare)(size_t, size_t), size_t (*hash)(size_t)); -void hm_clear(hashmap *_map_); -void hm_free(hashmap *_map_); -bool hm_insert(hashmap *_map_, size_t key, size_t value); -bool hm_remove(hashmap *_map_, size_t key, size_t *value); -bool hm_insert_if(hashmap *_map_, size_t key, size_t value, bool condition); -bool hm_remove_if(hashmap *_map_, size_t key, size_t *value, bool condition); -bool hm_max(hashmap *_map_, size_t *key, size_t *value); -bool hm_min(hashmap *_map_, size_t *key, size_t *value); +void hm_clear(hashmap *_map_, void (*deallocator)(size_t, size_t)); +void hm_free(hashmap *_map_, void (*deallocator)(size_t, size_t)); +_Bool hm_insert(hashmap *_map_, size_t key, size_t value); +_Bool hm_update(hashmap *_map_, size_t key, size_t new_value, size_t *old_value); +_Bool hm_remove(hashmap *_map_, size_t key, size_t *out_value); +_Bool hm_max(hashmap *_map_, size_t *key, size_t *value); +_Bool hm_min(hashmap *_map_, size_t *key, size_t *value); size_t hm_get(hashmap *_map_, size_t key); size_t *hm_get_ref(hashmap *_map_, size_t key); -bool hm_contains(hashmap *_map_, size_t key); -bool hm_empty(hashmap *_map_); +_Bool hm_contains(hashmap *_map_, size_t key); +_Bool hm_empty(hashmap *_map_); +_Bool hm_full(hashmap *_map_); size_t hm_count(hashmap *_map_); size_t hm_capacity(hashmap *_map_); +double hm_load(hashmap *_map_); +_Bool hm_resize(hashmap *_map_, size_t capacity); +hashmap *hm_copy_of(hashmap *_map_, size_t (*key_copy_func)(size_t), size_t (*value_copy_func)(size_t)); +_Bool hm_equals(hashmap *_map1_, hashmap *_map2_, int (*value_comparator)(size_t, size_t)); cmc_string hm_to_string(hashmap *_map_); hashmap_iter *hm_iter_new(hashmap *target); void hm_iter_free(hashmap_iter *iter); void hm_iter_init(hashmap_iter *iter, hashmap *target); -bool hm_iter_start(hashmap_iter *iter); -bool hm_iter_end(hashmap_iter *iter); +_Bool hm_iter_start(hashmap_iter *iter); +_Bool hm_iter_end(hashmap_iter *iter); void hm_iter_to_start(hashmap_iter *iter); void hm_iter_to_end(hashmap_iter *iter); -bool hm_iter_next(hashmap_iter *iter); -bool hm_iter_prev(hashmap_iter *iter); +_Bool hm_iter_next(hashmap_iter *iter); +_Bool hm_iter_prev(hashmap_iter *iter); +_Bool hm_iter_advance(hashmap_iter *iter, size_t steps); +_Bool hm_iter_rewind(hashmap_iter *iter, size_t steps); +_Bool hm_iter_go_to(hashmap_iter *iter, size_t index); size_t hm_iter_key(hashmap_iter *iter); size_t hm_iter_value(hashmap_iter *iter); size_t *hm_iter_rvalue(hashmap_iter *iter); size_t hm_iter_index(hashmap_iter *iter); -static inline size_t hm_impl_default_key(void) -{ - size_t _empty_key_; - memset(&_empty_key_, 0, sizeof(size_t)); - return _empty_key_; -} -static inline size_t hm_impl_default_value(void) -{ - size_t _empty_value_; - memset(&_empty_value_, 0, sizeof(size_t)); - return _empty_value_; -} -static bool hm_impl_grow(hashmap *_map_); static hashmap_entry *hm_impl_get_entry(hashmap *_map_, size_t key); static size_t hm_impl_calculate_size(size_t required); static hashmap_iter hm_impl_it_start(hashmap *_map_); @@ -79,18 +73,18 @@ static hashmap_iter hm_impl_it_end(hashmap *_map_); hashmap *hm_new(size_t capacity, double load, int (*compare)(size_t, size_t), size_t (*hash)(size_t)) { if (capacity == 0 || load <= 0 || load >= 1) - return NULL; - if (capacity >= UINTMAX_MAX * load) - return NULL; + return ((void *)0); + if (capacity >= 0xffffffffffffffff * load) + return ((void *)0); size_t real_capacity = hm_impl_calculate_size(capacity / load); hashmap *_map_ = malloc(sizeof(hashmap)); if (!_map_) - return NULL; + return ((void *)0); _map_->buffer = malloc(sizeof(hashmap_entry) * real_capacity); if (!_map_->buffer) { free(_map_); - return NULL; + return ((void *)0); } memset(_map_->buffer, 0, sizeof(hashmap_entry) * real_capacity); _map_->count = 0; @@ -102,39 +96,61 @@ hashmap *hm_new(size_t capacity, double load, int (*compare)(size_t, size_t), si _map_->it_end = hm_impl_it_end; return _map_; } -void hm_clear(hashmap *_map_) +void hm_clear(hashmap *_map_, void (*deallocator)(size_t, size_t)) { + if (deallocator) + { + for (size_t i = 0; i < _map_->capacity; i++) + { + hashmap_entry *entry = &(_map_->buffer[i]); + if (entry->state == CMC_ES_FILLED) + { + deallocator(entry->key, entry->value); + } + } + } memset(_map_->buffer, 0, sizeof(hashmap_entry) * _map_->capacity); _map_->count = 0; } -void hm_free(hashmap *_map_) +void hm_free(hashmap *_map_, void (*deallocator)(size_t, size_t)) { + if (deallocator) + { + for (size_t i = 0; i < _map_->capacity; i++) + { + hashmap_entry *entry = &(_map_->buffer[i]); + if (entry->state == CMC_ES_FILLED) + { + deallocator(entry->key, entry->value); + } + } + } free(_map_->buffer); free(_map_); } -bool hm_insert(hashmap *_map_, size_t key, size_t value) +_Bool hm_insert(hashmap *_map_, size_t key, size_t value) { - if ((double)_map_->capacity * _map_->load <= (double)_map_->count) + if (hm_full(_map_)) { - if (!hm_impl_grow(_map_)) - return false; + if (!hm_resize(_map_, hm_capacity(_map_) + 1)) + return 0; } size_t hash = _map_->hash(key); size_t original_pos = hash % _map_->capacity; size_t pos = original_pos; hashmap_entry *target = &(_map_->buffer[pos]); - if (hm_impl_get_entry(_map_, key) != NULL) - return false; + if (hm_impl_get_entry(_map_, key) != ((void *)0)) + return 0; if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) { target->key = key; target->value = value; - target->dist = original_pos - pos; + target->dist = 0; target->state = CMC_ES_FILLED; } else { - while (true) + while (1) { pos++; target = &(_map_->buffer[pos % _map_->capacity]); @@ -146,7 +162,7 @@ bool hm_insert(hashmap *_map_, size_t key, size_t value) target->state = CMC_ES_FILLED; break; } - else if (target->dist < original_pos - pos) + else if (target->dist < pos - original_pos) { size_t tmp_k = target->key; size_t tmp_v = target->value; @@ -161,97 +177,192 @@ bool hm_insert(hashmap *_map_, size_t key, size_t value) } } _map_->count++; - return true; + return 1; } -bool hm_remove(hashmap *_map_, size_t key, size_t *value) +_Bool hm_update(hashmap *_map_, size_t key, size_t new_value, size_t *old_value) +{ + hashmap_entry *entry = hm_impl_get_entry(_map_, key); + if (!entry) + return 0; + if (old_value) + *old_value = entry->value; + entry->value = new_value; + return 1; +} +_Bool hm_remove(hashmap *_map_, size_t key, size_t *out_value) { hashmap_entry *result = hm_impl_get_entry(_map_, key); - if (result == NULL) - return false; - *value = result->value; - result->key = hm_impl_default_key(); - result->value = hm_impl_default_value(); + if (result == ((void *)0)) + 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--; - return true; + return 1; } -bool hm_insert_if(hashmap *_map_, size_t key, size_t value, bool condition) -{ - if (condition) - return hm_insert(_map_, key, value); - return false; -} -bool hm_remove_if(hashmap *_map_, size_t key, size_t *value, bool condition) -{ - if (condition) - return hm_remove(_map_, key, value); - return false; -} -bool hm_max(hashmap *_map_, size_t *key, size_t *value) +_Bool hm_max(hashmap *_map_, size_t *key, size_t *value) { if (hm_empty(_map_)) - return false; + return 0; hashmap_iter iter; - for (hm_iter_init(&iter, _map_); !hm_iter_end(&iter); hm_iter_next(&iter)) + hm_iter_init(&iter, _map_); + size_t max_key = hm_iter_key(&iter); + size_t max_val = hm_iter_value(&iter); + hm_iter_next(&iter); + for (; !hm_iter_end(&iter); hm_iter_next(&iter)) { - size_t result_key = hm_iter_key(&iter); - size_t result_value = hm_iter_value(&iter); - size_t index = hm_iter_index(&iter); - if (index == 0) + size_t iter_key = hm_iter_key(&iter); + size_t iter_val = hm_iter_value(&iter); + if (_map_->cmp(iter_key, max_key) > 0) { - *key = result_key; - *value = result_value; - } - else if (_map_->cmp(result_key, *key) > 0) - { - *key = result_key; - *value = result_value; + max_key = iter_key; + max_val = iter_val; } } - return true; + if (key) + *key = max_key; + if (value) + *value = max_val; + return 1; } -bool hm_min(hashmap *_map_, size_t *key, size_t *value) +_Bool hm_min(hashmap *_map_, size_t *key, size_t *value) { if (hm_empty(_map_)) - return false; + return 0; hashmap_iter iter; - for (hm_iter_init(&iter, _map_); !hm_iter_end(&iter); hm_iter_next(&iter)) + hm_iter_init(&iter, _map_); + size_t min_key = hm_iter_key(&iter); + size_t min_val = hm_iter_value(&iter); + hm_iter_next(&iter); + for (; !hm_iter_end(&iter); hm_iter_next(&iter)) { - size_t result_key = hm_iter_key(&iter); - size_t result_value = hm_iter_value(&iter); - size_t index = hm_iter_index(&iter); - if (index == 0) + size_t iter_key = hm_iter_key(&iter); + size_t iter_val = hm_iter_value(&iter); + if (_map_->cmp(iter_key, min_key) < 0) { - *key = result_key; - *value = result_value; - } - else if (_map_->cmp(result_key, *key) < 0) - { - *key = result_key; - *value = result_value; + min_key = iter_key; + min_val = iter_val; } } - return true; + if (key) + *key = min_key; + if (value) + *value = min_val; + return 1; } size_t hm_get(hashmap *_map_, size_t key) { hashmap_entry *entry = hm_impl_get_entry(_map_, key); if (!entry) - return hm_impl_default_value(); + return (size_t){0}; return entry->value; } size_t *hm_get_ref(hashmap *_map_, size_t key) { hashmap_entry *entry = hm_impl_get_entry(_map_, key); if (!entry) - return NULL; + return ((void *)0); return &(entry->value); } -bool hm_contains(hashmap *_map_, size_t key) { return hm_impl_get_entry(_map_, key) != NULL; } -bool hm_empty(hashmap *_map_) { return _map_->count == 0; } +_Bool hm_contains(hashmap *_map_, size_t key) { return hm_impl_get_entry(_map_, key) != ((void *)0); } +_Bool hm_empty(hashmap *_map_) { return _map_->count == 0; } +_Bool hm_full(hashmap *_map_) { return (double)hm_capacity(_map_) * hm_load(_map_) <= (double)hm_count(_map_); } size_t hm_count(hashmap *_map_) { return _map_->count; } size_t hm_capacity(hashmap *_map_) { return _map_->capacity; } +double hm_load(hashmap *_map_) { return _map_->load; } +_Bool hm_resize(hashmap *_map_, size_t capacity) +{ + if (hm_capacity(_map_) == capacity) + return 1; + if (hm_capacity(_map_) > capacity / hm_load(_map_)) + return 1; + if (capacity >= 0xffffffffffffffff * hm_load(_map_)) + return 0; + size_t theoretical_size = hm_impl_calculate_size(capacity); + if (theoretical_size < hm_count(_map_) / hm_load(_map_)) + return 0; + hashmap *_new_map_ = hm_new(capacity, hm_load(_map_), _map_->cmp, _map_->hash); + if (!_new_map_) + return 0; + hashmap_iter iter; + for (hm_iter_init(&iter, _map_); !hm_iter_end(&iter); hm_iter_next(&iter)) + { + size_t key = hm_iter_key(&iter); + size_t value = hm_iter_value(&iter); + hm_insert(_new_map_, key, value); + } + if (hm_count(_map_) != hm_count(_new_map_)) + { + hm_free(_new_map_, ((void *)0)); + return 0; + } + 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; + hm_free(_new_map_, ((void *)0)); + return 1; +} +hashmap *hm_copy_of(hashmap *_map_, size_t (*key_copy_func)(size_t), size_t (*value_copy_func)(size_t)) +{ + hashmap *result = hm_new(_map_->capacity, _map_->load, _map_->cmp, _map_->hash); + if (!result) + return ((void *)0); + if (key_copy_func || value_copy_func) + { + for (size_t i = 0; i < _map_->capacity; i++) + { + hashmap_entry *scan = &(_map_->buffer[i]); + if (scan->state != CMC_ES_EMPTY) + { + 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 (key_copy_func) + target->key = key_copy_func(scan->key); + else + target->key = scan->key; + if (value_copy_func) + target->value = value_copy_func(scan->value); + else + target->value = scan->value; + } + } + } + } + else + memcpy(result->buffer, _map_->buffer, sizeof(hashmap_entry) * _map_->capacity); + result->count = _map_->count; + return result; +} +_Bool hm_equals(hashmap *_map1_, hashmap *_map2_, int (*value_comparator)(size_t, size_t)) +{ + if (hm_count(_map1_) != hm_count(_map2_)) + return 0; + hashmap_iter iter; + hm_iter_init(&iter, _map1_); + for (hm_iter_to_start(&iter); !hm_iter_end(&iter); hm_iter_next(&iter)) + { + hashmap_entry *entry = hm_impl_get_entry(_map2_, hm_iter_key(&iter)); + if (entry == ((void *)0)) + return 0; + if (value_comparator) + { + if (value_comparator(entry->value, hm_iter_value(&iter)) != 0) + return 0; + } + } + return 1; +} cmc_string hm_to_string(hashmap *_map_) { cmc_string str; @@ -264,17 +375,16 @@ hashmap_iter *hm_iter_new(hashmap *target) { hashmap_iter *iter = malloc(sizeof(hashmap_iter)); if (!iter) - return NULL; + return ((void *)0); hm_iter_init(iter, target); return iter; } void hm_iter_free(hashmap_iter *iter) { free(iter); } void hm_iter_init(hashmap_iter *iter, hashmap *target) { + memset(iter, 0, sizeof(hashmap_iter)); iter->target = target; - iter->cursor = 0; - iter->index = 0; - iter->start = true; + iter->start = 1; iter->end = hm_empty(target); if (!hm_empty(target)) { @@ -297,32 +407,39 @@ void hm_iter_init(hashmap_iter *iter, hashmap *target) } } } -bool hm_iter_start(hashmap_iter *iter) { return hm_empty(iter->target) || iter->start; } -bool hm_iter_end(hashmap_iter *iter) { return hm_empty(iter->target) || iter->end; } +_Bool hm_iter_start(hashmap_iter *iter) { return hm_empty(iter->target) || iter->start; } +_Bool hm_iter_end(hashmap_iter *iter) { return hm_empty(iter->target) || iter->end; } void hm_iter_to_start(hashmap_iter *iter) { - iter->cursor = iter->first; - iter->index = 0; - iter->start = true; - iter->end = hm_empty(iter->target); + if (!hm_empty(iter->target)) + { + iter->cursor = iter->first; + iter->index = 0; + iter->start = 1; + iter->end = hm_empty(iter->target); + } } void hm_iter_to_end(hashmap_iter *iter) { - iter->cursor = iter->last; - iter->index = iter->target->count - 1; - iter->start = hm_empty(iter->target); - iter->end = true; + if (!hm_empty(iter->target)) + { + iter->cursor = iter->last; + iter->index = hm_count(iter->target) - 1; + iter->start = hm_empty(iter->target); + iter->end = 1; + } } -bool hm_iter_next(hashmap_iter *iter) +_Bool hm_iter_next(hashmap_iter *iter) { if (iter->end) - return false; - hashmap_entry *scan = &(iter->target->buffer[iter->cursor]); - if (iter->cursor == iter->last) + return 0; + if (iter->index + 1 == hm_count(iter->target)) { - iter->end = true; - return false; + iter->end = 1; + return 0; } + iter->start = hm_empty(iter->target); + hashmap_entry *scan = &(iter->target->buffer[iter->cursor]); iter->index++; while (1) { @@ -331,19 +448,19 @@ bool hm_iter_next(hashmap_iter *iter) if (scan->state == CMC_ES_FILLED) break; } - iter->start = hm_empty(iter->target); - return true; + return 1; } -bool hm_iter_prev(hashmap_iter *iter) +_Bool hm_iter_prev(hashmap_iter *iter) { if (iter->start) - return false; - hashmap_entry *scan = &(iter->target->buffer[iter->cursor]); - if (iter->cursor == iter->first) + return 0; + if (iter->index == 0) { - iter->start = true; - return false; + iter->start = 1; + return 0; } + iter->end = hm_empty(iter->target); + hashmap_entry *scan = &(iter->target->buffer[iter->cursor]); iter->index--; while (1) { @@ -352,53 +469,67 @@ bool hm_iter_prev(hashmap_iter *iter) if (scan->state == CMC_ES_FILLED) break; } - iter->end = hm_empty(iter->target); - return true; + return 1; +} +_Bool hm_iter_advance(hashmap_iter *iter, size_t steps) +{ + if (iter->end) + return 0; + if (iter->index + 1 == hm_count(iter->target)) + { + iter->end = 1; + return 0; + } + if (steps == 0 || iter->index + steps >= hm_count(iter->target)) + return 0; + for (size_t i = 0; i < steps; i++) + hm_iter_next(iter); + return 1; +} +_Bool hm_iter_rewind(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(hashmap_iter *iter, size_t index) +{ + if (index >= hm_count(iter->target)) + 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(hashmap_iter *iter) { if (hm_empty(iter->target)) - return hm_impl_default_key(); + return (size_t){0}; return iter->target->buffer[iter->cursor].key; } size_t hm_iter_value(hashmap_iter *iter) { if (hm_empty(iter->target)) - return hm_impl_default_value(); + return (size_t){0}; return iter->target->buffer[iter->cursor].value; } size_t *hm_iter_rvalue(hashmap_iter *iter) { if (hm_empty(iter->target)) - return NULL; + return ((void *)0); return &(iter->target->buffer[iter->cursor].value); } size_t hm_iter_index(hashmap_iter *iter) { return iter->index; } -static bool hm_impl_grow(hashmap *_map_) -{ - size_t new_size = hm_impl_calculate_size(_map_->capacity + _map_->capacity / 2); - hashmap *_new_map_ = hm_new(new_size, _map_->load, _map_->cmp, _map_->hash); - if (!_new_map_) - return false; - hashmap_iter iter; - for (hm_iter_init(&iter, _map_); !hm_iter_end(&iter); hm_iter_next(&iter)) - { - size_t key = hm_iter_key(&iter); - size_t value = hm_iter_value(&iter); - hm_insert(_new_map_, key, value); - } - if (_map_->count != _new_map_->count) - { - hm_free(_new_map_); - return false; - } - hashmap_entry *tmp = _map_->buffer; - _map_->buffer = _new_map_->buffer; - _new_map_->buffer = tmp; - _map_->capacity = _new_map_->capacity; - hm_free(_new_map_); - return true; -} static hashmap_entry *hm_impl_get_entry(hashmap *_map_, size_t key) { size_t hash = _map_->hash(key); @@ -411,7 +542,7 @@ static hashmap_entry *hm_impl_get_entry(hashmap *_map_, size_t key) pos++; target = &(_map_->buffer[pos % _map_->capacity]); } - return NULL; + return ((void *)0); } static size_t hm_impl_calculate_size(size_t required) { diff --git a/tests/codecov/src/hashset.c b/tests/codecov/src/hashset.c index 78070ed..6c9f80d 100644 --- a/tests/codecov/src/hashset.c +++ b/tests/codecov/src/hashset.c @@ -1,6 +1,6 @@ -#include "cmc/hashset.h" +#include -//HASHSET_GENERATE(hs, hashset, , size_t) +//CMC_GENERATE_HASHSET(hs, hashset, size_t) typedef struct hashset_s { @@ -26,50 +26,49 @@ typedef struct hashset_iter_s size_t index; size_t first; size_t last; - bool start; - bool end; + _Bool start; + _Bool end; } hashset_iter, *hashset_iter_ptr; hashset *hs_new(size_t capacity, double load, int (*compare)(size_t, size_t), size_t (*hash)(size_t)); -void hs_clear(hashset *_set_); -void hs_free(hashset *_set_); -bool hs_insert(hashset *_set_, size_t element); -bool hs_remove(hashset *_set_, size_t element); -bool hs_insert_if(hashset *_set_, size_t element, bool condition); -bool hs_remove_if(hashset *_set_, size_t element, bool condition); -bool hs_max(hashset *_set_, size_t *value); -bool hs_min(hashset *_set_, size_t *value); -bool hs_contains(hashset *_set_, size_t element); -bool hs_empty(hashset *_set_); +void hs_clear(hashset *_set_, void (*deallocator)(size_t)); +void hs_free(hashset *_set_, void (*deallocator)(size_t)); +_Bool hs_insert(hashset *_set_, size_t element); +_Bool hs_remove(hashset *_set_, size_t element); +_Bool hs_max(hashset *_set_, size_t *value); +_Bool hs_min(hashset *_set_, size_t *value); +_Bool hs_contains(hashset *_set_, size_t element); +_Bool hs_empty(hashset *_set_); +_Bool hs_full(hashset *_set_); size_t hs_count(hashset *_set_); size_t hs_capacity(hashset *_set_); +double hs_load(hashset *_set_); +_Bool hs_resize(hashset *_set_, size_t capacity); +hashset *hs_copy_of(hashset *_set_, size_t (*copy_func)(size_t)); +_Bool hs_equals(hashset *_set1_, hashset *_set2_); cmc_string hs_to_string(hashset *_set_); hashset *hs_union(hashset *_set1_, hashset *_set2_); hashset *hs_intersection(hashset *_set1_, hashset *_set2_); hashset *hs_difference(hashset *_set1_, hashset *_set2_); hashset *hs_symmetric_difference(hashset *_set1_, hashset *_set2_); -bool hs_is_subset(hashset *_set1_, hashset *_set2_); -bool hs_is_superset(hashset *_set1_, hashset *_set2_); -bool hs_is_proper_subset(hashset *_set1_, hashset *_set2_); -bool hs_is_proper_superset(hashset *_set1_, hashset *_set2_); -bool hs_is_disjointset(hashset *_set1_, hashset *_set2_); +_Bool hs_is_subset(hashset *_set1_, hashset *_set2_); +_Bool hs_is_superset(hashset *_set1_, hashset *_set2_); +_Bool hs_is_proper_subset(hashset *_set1_, hashset *_set2_); +_Bool hs_is_proper_superset(hashset *_set1_, hashset *_set2_); +_Bool hs_is_disjointset(hashset *_set1_, hashset *_set2_); hashset_iter *hs_iter_new(hashset *target); void hs_iter_free(hashset_iter *iter); void hs_iter_init(hashset_iter *iter, hashset *target); -bool hs_iter_start(hashset_iter *iter); -bool hs_iter_end(hashset_iter *iter); +_Bool hs_iter_start(hashset_iter *iter); +_Bool hs_iter_end(hashset_iter *iter); void hs_iter_to_start(hashset_iter *iter); void hs_iter_to_end(hashset_iter *iter); -bool hs_iter_next(hashset_iter *iter); -bool hs_iter_prev(hashset_iter *iter); +_Bool hs_iter_next(hashset_iter *iter); +_Bool hs_iter_prev(hashset_iter *iter); +_Bool hs_iter_advance(hashset_iter *iter, size_t steps); +_Bool hs_iter_rewind(hashset_iter *iter, size_t steps); +_Bool hs_iter_go_to(hashset_iter *iter, size_t index); size_t hs_iter_value(hashset_iter *iter); size_t hs_iter_index(hashset_iter *iter); -static inline size_t hs_impl_default_value(void) -{ - size_t _empty_value_; - memset(&_empty_value_, 0, sizeof(size_t)); - return _empty_value_; -} -static bool hs_impl_grow(hashset *_set_); static hashset_entry *hs_impl_get_entry(hashset *_set_, size_t element); static size_t hs_impl_calculate_size(size_t required); static hashset_iter hs_impl_it_start(hashset *_set_); @@ -77,18 +76,18 @@ static hashset_iter hs_impl_it_end(hashset *_set_); hashset *hs_new(size_t capacity, double load, int (*compare)(size_t, size_t), size_t (*hash)(size_t)) { if (capacity == 0 || load <= 0 || load >= 1) - return NULL; - if (capacity >= UINTMAX_MAX * load) - return NULL; + return ((void *)0); + if (capacity >= 0xffffffffffffffff * load) + return ((void *)0); size_t real_capacity = hs_impl_calculate_size(capacity / load); hashset *_set_ = malloc(sizeof(hashset)); if (!_set_) - return NULL; + return ((void *)0); _set_->buffer = malloc(sizeof(hashset_entry) * real_capacity); if (!_set_->buffer) { free(_set_); - return NULL; + return ((void *)0); } memset(_set_->buffer, 0, sizeof(hashset_entry) * real_capacity); _set_->count = 0; @@ -100,38 +99,60 @@ hashset *hs_new(size_t capacity, double load, int (*compare)(size_t, size_t), si _set_->it_end = hs_impl_it_end; return _set_; } -void hs_clear(hashset *_set_) +void hs_clear(hashset *_set_, void (*deallocator)(size_t)) { + if (deallocator) + { + for (size_t i = 0; i < _set_->capacity; i++) + { + hashset_entry *entry = &(_set_->buffer[i]); + if (entry->state == CMC_ES_FILLED) + { + deallocator(entry->value); + } + } + } memset(_set_->buffer, 0, sizeof(hashset_entry) * _set_->capacity); _set_->count = 0; } -void hs_free(hashset *_set_) +void hs_free(hashset *_set_, void (*deallocator)(size_t)) { + if (deallocator) + { + for (size_t i = 0; i < _set_->capacity; i++) + { + hashset_entry *entry = &(_set_->buffer[i]); + if (entry->state == CMC_ES_FILLED) + { + deallocator(entry->value); + } + } + } free(_set_->buffer); free(_set_); } -bool hs_insert(hashset *_set_, size_t element) +_Bool hs_insert(hashset *_set_, size_t element) { - if ((double)_set_->capacity * _set_->load <= (double)_set_->count) + if (hs_full(_set_)) { - if (!hs_impl_grow(_set_)) - return false; + if (!hs_resize(_set_, hs_capacity(_set_) + 1)) + return 0; } size_t hash = _set_->hash(element); size_t original_pos = hash % _set_->capacity; size_t pos = original_pos; hashset_entry *target = &(_set_->buffer[pos]); - if (hs_impl_get_entry(_set_, element) != NULL) - return false; + if (hs_impl_get_entry(_set_, element) != ((void *)0)) + return 0; if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) { target->value = element; - target->dist = pos - original_pos; + target->dist = 0; target->state = CMC_ES_FILLED; } else { - while (true) + while (1) { pos++; target = &(_set_->buffer[pos % _set_->capacity]); @@ -154,35 +175,23 @@ bool hs_insert(hashset *_set_, size_t element) } } _set_->count++; - return true; + return 1; } -bool hs_remove(hashset *_set_, size_t element) +_Bool hs_remove(hashset *_set_, size_t element) { hashset_entry *result = hs_impl_get_entry(_set_, element); - if (result == NULL) - return false; - result->value = hs_impl_default_value(); + if (result == ((void *)0)) + return 0; + result->value = (size_t){0}; result->dist = 0; result->state = CMC_ES_DELETED; _set_->count--; - return true; + return 1; } -bool hs_insert_if(hashset *_set_, size_t element, bool condition) -{ - if (condition) - return hs_insert(_set_, element); - return false; -} -bool hs_remove_if(hashset *_set_, size_t element, bool condition) -{ - if (condition) - return hs_remove(_set_, element); - return false; -} -bool hs_max(hashset *_set_, size_t *value) +_Bool hs_max(hashset *_set_, size_t *value) { if (hs_empty(_set_)) - return false; + return 0; hashset_iter iter; for (hs_iter_init(&iter, _set_); !hs_iter_end(&iter); hs_iter_next(&iter)) { @@ -193,12 +202,12 @@ bool hs_max(hashset *_set_, size_t *value) else if (_set_->cmp(result, *value) > 0) *value = result; } - return true; + return 1; } -bool hs_min(hashset *_set_, size_t *value) +_Bool hs_min(hashset *_set_, size_t *value) { if (hs_empty(_set_)) - return false; + return 0; hashset_iter iter; for (hs_iter_init(&iter, _set_); !hs_iter_end(&iter); hs_iter_next(&iter)) { @@ -209,12 +218,92 @@ bool hs_min(hashset *_set_, size_t *value) else if (_set_->cmp(result, *value) < 0) *value = result; } - return true; + return 1; } -bool hs_contains(hashset *_set_, size_t element) { return hs_impl_get_entry(_set_, element) != NULL; } -bool hs_empty(hashset *_set_) { return _set_->count == 0; } +_Bool hs_contains(hashset *_set_, size_t element) { return hs_impl_get_entry(_set_, element) != ((void *)0); } +_Bool hs_empty(hashset *_set_) { return _set_->count == 0; } +_Bool hs_full(hashset *_set_) { return (double)hs_capacity(_set_) * hs_load(_set_) <= (double)hs_count(_set_); } size_t hs_count(hashset *_set_) { return _set_->count; } size_t hs_capacity(hashset *_set_) { return _set_->capacity; } +double hs_load(hashset *_set_) { return _set_->load; } +_Bool hs_resize(hashset *_set_, size_t capacity) +{ + if (hs_capacity(_set_) == capacity) + return 1; + if (hs_capacity(_set_) > capacity / hs_load(_set_)) + return 1; + if (capacity >= 0xffffffffffffffff * hs_load(_set_)) + return 0; + size_t theoretical_size = hs_impl_calculate_size(capacity); + if (theoretical_size < hs_count(_set_) / hs_load(_set_)) + return 0; + hashset *_new_set_ = hs_new(capacity, hs_load(_set_), _set_->cmp, _set_->hash); + if (!_new_set_) + return 0; + hashset_iter iter; + for (hs_iter_init(&iter, _set_); !hs_iter_end(&iter); hs_iter_next(&iter)) + { + size_t value = hs_iter_value(&iter); + hs_insert(_new_set_, value); + } + if (hs_count(_set_) != hs_count(_new_set_)) + { + hs_free(_new_set_, ((void *)0)); + return 0; + } + 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; + hs_free(_new_set_, ((void *)0)); + return 1; +} +hashset *hs_copy_of(hashset *_set_, size_t (*copy_func)(size_t)) +{ + hashset *result = hs_new(_set_->capacity, _set_->load, _set_->cmp, _set_->hash); + if (!result) + return ((void *)0); + if (copy_func) + { + for (size_t i = 0; i < _set_->capacity; i++) + { + hashset_entry *scan = &(_set_->buffer[i]); + if (scan->state != CMC_ES_EMPTY) + { + 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 = copy_func(scan->value); + } + } + } + } + else + memcpy(result->buffer, _set_->buffer, sizeof(hashset_entry) * _set_->capacity); + result->count = _set_->count; + return result; +} +_Bool hs_equals(hashset *_set1_, hashset *_set2_) +{ + if (hs_count(_set1_) != hs_count(_set2_)) + return 0; + if (hs_count(_set1_) == 0) + return 1; + hashset_iter iter; + hs_iter_init(&iter, _set1_); + for (hs_iter_to_start(&iter); !hs_iter_end(&iter); hs_iter_next(&iter)) + { + if (hs_impl_get_entry(_set2_, hs_iter_value(&iter)) == ((void *)0)) + return 0; + } + return 1; +} cmc_string hs_to_string(hashset *_set_) { cmc_string str; @@ -227,7 +316,7 @@ hashset *hs_union(hashset *_set1_, hashset *_set2_) { hashset *_set_r_ = hs_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); if (!_set_r_) - return NULL; + return ((void *)0); hashset_iter iter1, iter2; hs_iter_init(&iter1, _set1_); hs_iter_init(&iter2, _set2_); @@ -245,7 +334,7 @@ hashset *hs_intersection(hashset *_set1_, hashset *_set2_) { hashset *_set_r_ = hs_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); if (!_set_r_) - return NULL; + return ((void *)0); hashset *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; hashset *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; hashset_iter iter; @@ -253,7 +342,7 @@ hashset *hs_intersection(hashset *_set1_, hashset *_set2_) for (hs_iter_to_start(&iter); !hs_iter_end(&iter); hs_iter_next(&iter)) { size_t value = hs_iter_value(&iter); - if (hs_impl_get_entry(_set_B_, value) != NULL) + if (hs_impl_get_entry(_set_B_, value) != ((void *)0)) hs_insert(_set_r_, value); } return _set_r_; @@ -262,13 +351,13 @@ hashset *hs_difference(hashset *_set1_, hashset *_set2_) { hashset *_set_r_ = hs_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); if (!_set_r_) - return NULL; + return ((void *)0); hashset_iter iter; hs_iter_init(&iter, _set1_); for (hs_iter_to_start(&iter); !hs_iter_end(&iter); hs_iter_next(&iter)) { size_t value = hs_iter_value(&iter); - if (hs_impl_get_entry(_set2_, value) == NULL) + if (hs_impl_get_entry(_set2_, value) == ((void *)0)) hs_insert(_set_r_, value); } return _set_r_; @@ -278,50 +367,50 @@ hashset *hs_symmetric_difference(hashset *_set1_, hashset *_set2_) hashset_iter iter1, iter2; hashset *_set_r_ = hs_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); if (!_set_r_) - return NULL; + return ((void *)0); hs_iter_init(&iter1, _set1_); hs_iter_init(&iter2, _set2_); for (hs_iter_to_start(&iter1); !hs_iter_end(&iter1); hs_iter_next(&iter1)) { size_t value = hs_iter_value(&iter1); - if (hs_impl_get_entry(_set2_, value) == NULL) + if (hs_impl_get_entry(_set2_, value) == ((void *)0)) hs_insert(_set_r_, value); } for (hs_iter_to_start(&iter2); !hs_iter_end(&iter2); hs_iter_next(&iter2)) { size_t value = hs_iter_value(&iter2); - if (hs_impl_get_entry(_set1_, value) == NULL) + if (hs_impl_get_entry(_set1_, value) == ((void *)0)) hs_insert(_set_r_, value); } return _set_r_; } -bool hs_is_subset(hashset *_set1_, hashset *_set2_) +_Bool hs_is_subset(hashset *_set1_, hashset *_set2_) { if (hs_count(_set1_) > hs_count(_set2_)) - return false; + return 0; if (hs_empty(_set1_)) - return true; + return 1; hashset_iter iter; hs_iter_init(&iter, _set1_); for (hs_iter_to_start(&iter); !hs_iter_end(&iter); hs_iter_next(&iter)) { size_t value = hs_iter_value(&iter); if (!hs_contains(_set2_, value)) - return false; + return 0; } - return true; + return 1; } -bool hs_is_superset(hashset *_set1_, hashset *_set2_) { return hs_is_subset(_set2_, _set1_); } -bool hs_is_proper_subset(hashset *_set1_, hashset *_set2_) +_Bool hs_is_superset(hashset *_set1_, hashset *_set2_) { return hs_is_subset(_set2_, _set1_); } +_Bool hs_is_proper_subset(hashset *_set1_, hashset *_set2_) { if (hs_count(_set1_) >= hs_count(_set2_)) - return false; + return 0; if (hs_empty(_set1_)) { if (!hs_empty(_set2_)) - return true; + return 1; else - return false; + return 0; } hashset_iter iter; hs_iter_init(&iter, _set1_); @@ -329,40 +418,39 @@ bool hs_is_proper_subset(hashset *_set1_, hashset *_set2_) { size_t value = hs_iter_value(&iter); if (!hs_contains(_set2_, value)) - return false; + return 0; } - return true; + return 1; } -bool hs_is_proper_superset(hashset *_set1_, hashset *_set2_) { return hs_is_proper_subset(_set2_, _set1_); } -bool hs_is_disjointset(hashset *_set1_, hashset *_set2_) +_Bool hs_is_proper_superset(hashset *_set1_, hashset *_set2_) { return hs_is_proper_subset(_set2_, _set1_); } +_Bool hs_is_disjointset(hashset *_set1_, hashset *_set2_) { if (hs_empty(_set1_)) - return true; + return 1; hashset_iter iter; hs_iter_init(&iter, _set1_); for (hs_iter_to_start(&iter); !hs_iter_end(&iter); hs_iter_next(&iter)) { size_t value = hs_iter_value(&iter); if (hs_contains(_set2_, value)) - return false; + return 0; } - return true; + return 1; } hashset_iter *hs_iter_new(hashset *target) { hashset_iter *iter = malloc(sizeof(hashset_iter)); if (!iter) - return NULL; + return ((void *)0); hs_iter_init(iter, target); return iter; } void hs_iter_free(hashset_iter *iter) { free(iter); } void hs_iter_init(hashset_iter *iter, hashset *target) { + memset(iter, 0, sizeof(hashset_iter)); iter->target = target; - iter->cursor = 0; - iter->index = 0; - iter->start = true; + iter->start = 1; iter->end = hs_empty(target); if (!hs_empty(target)) { @@ -385,94 +473,117 @@ void hs_iter_init(hashset_iter *iter, hashset *target) } } } -bool hs_iter_start(hashset_iter *iter) { return hs_empty(iter->target) || iter->start; } -bool hs_iter_end(hashset_iter *iter) { return hs_empty(iter->target) || iter->end; } +_Bool hs_iter_start(hashset_iter *iter) { return hs_empty(iter->target) || iter->start; } +_Bool hs_iter_end(hashset_iter *iter) { return hs_empty(iter->target) || iter->end; } void hs_iter_to_start(hashset_iter *iter) { - iter->cursor = iter->first; - iter->index = 0; - iter->start = true; - iter->end = hs_empty(iter->target); + if (!hs_empty(iter->target)) + { + iter->cursor = iter->first; + iter->index = 0; + iter->start = 1; + iter->end = hs_empty(iter->target); + } } void hs_iter_to_end(hashset_iter *iter) { - iter->cursor = iter->last; - iter->index = iter->target->count - 1; - iter->start = hs_empty(iter->target); - iter->end = true; + if (!hs_empty(iter->target)) + { + iter->cursor = iter->last; + iter->index = hs_count(iter->target) - 1; + iter->start = hs_empty(iter->target); + iter->end = 1; + } } -bool hs_iter_next(hashset_iter *iter) +_Bool hs_iter_next(hashset_iter *iter) { if (iter->end) - return false; - hashset_entry *scan = &(iter->target->buffer[iter->cursor]); - if (iter->cursor == iter->last) - iter->end = true; - else + return 0; + if (iter->index + 1 == hs_count(iter->target)) { - iter->index++; - while (1) - { - iter->cursor++; - scan = &(iter->target->buffer[iter->cursor]); - if (scan->state == CMC_ES_FILLED) - break; - } + iter->end = 1; + return 0; } iter->start = hs_empty(iter->target); - return true; + 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(hashset_iter *iter) +_Bool hs_iter_prev(hashset_iter *iter) { if (iter->start) - return false; - hashset_entry *scan = &(iter->target->buffer[iter->cursor]); - if (iter->cursor == iter->first) - iter->start = true; - else + return 0; + if (iter->index == 0) { - iter->index--; - while (1) - { - iter->cursor--; - scan = &(iter->target->buffer[iter->cursor]); - if (scan->state == CMC_ES_FILLED) - break; - } + iter->start = 1; + return 0; } iter->end = hs_empty(iter->target); - return true; + 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(hashset_iter *iter, size_t steps) +{ + if (iter->end) + return 0; + if (iter->index + 1 == hs_count(iter->target)) + { + iter->end = 1; + return 0; + } + if (steps == 0 || iter->index + steps >= hs_count(iter->target)) + return 0; + for (size_t i = 0; i < steps; i++) + hs_iter_next(iter); + return 1; +} +_Bool hs_iter_rewind(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(hashset_iter *iter, size_t index) +{ + if (index >= hs_count(iter->target)) + 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(hashset_iter *iter) { if (hs_empty(iter->target)) - return hs_impl_default_value(); + return (size_t){0}; return iter->target->buffer[iter->cursor].value; } size_t hs_iter_index(hashset_iter *iter) { return iter->index; } -static bool hs_impl_grow(hashset *_set_) -{ - size_t new_size = hs_impl_calculate_size(_set_->capacity + _set_->capacity / 2); - hashset *_new_set_ = hs_new(new_size, _set_->load, _set_->cmp, _set_->hash); - if (!_new_set_) - return false; - hashset_iter iter; - for (hs_iter_init(&iter, _set_); !hs_iter_end(&iter); hs_iter_next(&iter)) - { - hs_insert(_new_set_, hs_iter_value(&iter)); - } - if (_set_->count != _new_set_->count) - { - hs_free(_new_set_); - return false; - } - hashset_entry *tmp = _set_->buffer; - _set_->buffer = _new_set_->buffer; - _new_set_->buffer = tmp; - _set_->capacity = _new_set_->capacity; - hs_free(_new_set_); - return true; -} static hashset_entry *hs_impl_get_entry(hashset *_set_, size_t element) { size_t hash = _set_->hash(element); @@ -485,7 +596,7 @@ static hashset_entry *hs_impl_get_entry(hashset *_set_, size_t element) pos++; target = &(_set_->buffer[pos % _set_->capacity]); } - return NULL; + return ((void *)0); } static size_t hs_impl_calculate_size(size_t required) { diff --git a/tests/codecov/src/heap.c b/tests/codecov/src/heap.c index cc20d09..fb385f0 100644 --- a/tests/codecov/src/heap.c +++ b/tests/codecov/src/heap.c @@ -1,6 +1,6 @@ -#include "cmc/heap.h" +#include -//HEAP_GENERATE(h, heap, , size_t) +//CMC_GENERATE_HEAP(h, heap, size_t) typedef struct heap_s { @@ -16,59 +16,56 @@ typedef struct heap_iter_s { struct heap_s *target; size_t cursor; - bool start; - bool end; + _Bool start; + _Bool end; } heap_iter, *heap_iter_ptr; heap *h_new(size_t capacity, cmc_heap_order HO, int (*compare)(size_t, size_t)); -void h_clear(heap *_heap_); -void h_free(heap *_heap_); -bool h_insert(heap *_heap_, size_t element); -bool h_remove(heap *_heap_, size_t *result); -bool h_insert_if(heap *_heap_, size_t element, bool condition); -bool h_remove_if(heap *_heap_, size_t *result, bool condition); +void h_clear(heap *_heap_, void (*deallocator)(size_t)); +void h_free(heap *_heap_, void (*deallocator)(size_t)); +_Bool h_insert(heap *_heap_, size_t element); +_Bool h_remove(heap *_heap_, size_t *result); size_t h_peek(heap *_heap_); -size_t *h_peek_ref(heap *_heap_); -bool h_contains(heap *_heap_, size_t element); -bool h_empty(heap *_heap_); -bool h_full(heap *_heap_); +_Bool h_contains(heap *_heap_, size_t element); +_Bool h_empty(heap *_heap_); +_Bool h_full(heap *_heap_); size_t h_count(heap *_heap_); size_t h_capacity(heap *_heap_); +_Bool h_resize(heap *_heap_, size_t capacity); +heap *h_copy_of(heap *_heap_, size_t (*copy_func)(size_t)); +_Bool h_equals(heap *_heap1_, heap *_heap2_); +cmc_string h_to_string(heap *_heap_); heap_iter *h_iter_new(heap *target); void h_iter_free(heap_iter *iter); void h_iter_init(heap_iter *iter, heap *target); -bool h_iter_start(heap_iter *iter); -bool h_iter_end(heap_iter *iter); +_Bool h_iter_start(heap_iter *iter); +_Bool h_iter_end(heap_iter *iter); void h_iter_to_start(heap_iter *iter); void h_iter_to_end(heap_iter *iter); -bool h_iter_next(heap_iter *iter); -bool h_iter_prev(heap_iter *iter); +_Bool h_iter_next(heap_iter *iter); +_Bool h_iter_prev(heap_iter *iter); +_Bool h_iter_advance(heap_iter *iter, size_t steps); +_Bool h_iter_rewind(heap_iter *iter, size_t steps); +_Bool h_iter_go_to(heap_iter *iter, size_t index); size_t h_iter_value(heap_iter *iter); size_t h_iter_index(heap_iter *iter); -static inline size_t h_impl_default_value(void) -{ - size_t _empty_value_; - memset(&_empty_value_, 0, sizeof(size_t)); - return _empty_value_; -} -static bool h_impl_grow(heap *_heap_); -static bool h_impl_float_up(heap *_heap_, size_t index); -static bool h_impl_float_down(heap *_heap_, size_t index); +static _Bool h_impl_float_up(heap *_heap_, size_t index); +static _Bool h_impl_float_down(heap *_heap_, size_t index); static heap_iter h_impl_it_start(heap *_heap_); static heap_iter h_impl_it_end(heap *_heap_); heap *h_new(size_t capacity, cmc_heap_order HO, int (*compare)(size_t, size_t)) { if (capacity < 1) - return NULL; + return ((void *)0); if (HO != cmc_min_heap && HO != cmc_max_heap) - return NULL; + return ((void *)0); heap *_heap_ = malloc(sizeof(heap)); if (!_heap_) - return NULL; + return ((void *)0); _heap_->buffer = malloc(sizeof(size_t) * capacity); if (!_heap_->buffer) { free(_heap_); - return NULL; + return ((void *)0); } memset(_heap_->buffer, 0, sizeof(size_t) * capacity); _heap_->capacity = capacity; @@ -79,87 +76,131 @@ heap *h_new(size_t capacity, cmc_heap_order HO, int (*compare)(size_t, size_t)) _heap_->it_end = h_impl_it_end; return _heap_; } -void h_clear(heap *_heap_) +void h_clear(heap *_heap_, void (*deallocator)(size_t)) { + if (deallocator) + { + for (size_t i = 0; i < _heap_->count; i++) + { + deallocator(_heap_->buffer[i]); + } + } memset(_heap_->buffer, 0, sizeof(size_t) * _heap_->capacity); _heap_->count = 0; } -void h_free(heap *_heap_) +void h_free(heap *_heap_, void (*deallocator)(size_t)) { + if (deallocator) + { + for (size_t i = 0; i < _heap_->count; i++) + { + deallocator(_heap_->buffer[i]); + } + } free(_heap_->buffer); free(_heap_); } -bool h_insert(heap *_heap_, size_t element) +_Bool h_insert(heap *_heap_, size_t element) { if (h_full(_heap_)) { - if (!h_impl_grow(_heap_)) - return false; + if (!h_resize(_heap_, h_count(_heap_) * 2)) + return 0; } - if (_heap_->count == 0) + if (h_empty(_heap_)) { _heap_->buffer[_heap_->count++] = element; - return true; + return 1; } _heap_->buffer[_heap_->count++] = element; if (!h_impl_float_up(_heap_, _heap_->count - 1)) - return false; - return true; + return 0; + return 1; } -bool h_remove(heap *_heap_, size_t *result) +_Bool h_remove(heap *_heap_, size_t *result) { if (h_empty(_heap_)) - return false; + return 0; *result = _heap_->buffer[0]; _heap_->buffer[0] = _heap_->buffer[_heap_->count - 1]; - _heap_->buffer[_heap_->count - 1] = h_impl_default_value(); + _heap_->buffer[_heap_->count - 1] = (size_t){0}; _heap_->count--; if (!h_impl_float_down(_heap_, 0)) - return false; - return true; -} -bool h_insert_if(heap *_heap_, size_t element, bool condition) -{ - if (condition) - return h_insert(_heap_, element); - return false; -} -bool h_remove_if(heap *_heap_, size_t *result, bool condition) -{ - if (condition) - return h_remove(_heap_, result); - return false; + return 0; + return 1; } size_t h_peek(heap *_heap_) { if (h_empty(_heap_)) - return h_impl_default_value(); + return (size_t){0}; return _heap_->buffer[0]; } -size_t *h_peek_ref(heap *_heap_) -{ - if (h_empty(_heap_)) - return NULL; - return &(_heap_->buffer[0]); -} -bool h_contains(heap *_heap_, size_t element) +_Bool h_contains(heap *_heap_, size_t element) { for (size_t i = 0; i < _heap_->count; i++) { if (_heap_->cmp(_heap_->buffer[i], element) == 0) - return true; + return 1; } - return false; + return 0; } -bool h_empty(heap *_heap_) { return _heap_->count == 0; } -bool h_full(heap *_heap_) { return _heap_->count >= _heap_->capacity; } +_Bool h_empty(heap *_heap_) { return _heap_->count == 0; } +_Bool h_full(heap *_heap_) { return _heap_->count >= _heap_->capacity; } size_t h_count(heap *_heap_) { return _heap_->count; } size_t h_capacity(heap *_heap_) { return _heap_->capacity; } +_Bool h_resize(heap *_heap_, size_t capacity) +{ + if (h_capacity(_heap_) == capacity) + return 1; + if (capacity < h_count(_heap_)) + return 0; + size_t *new_buffer = realloc(_heap_->buffer, sizeof(size_t) * capacity); + if (!new_buffer) + return 0; + _heap_->buffer = new_buffer; + _heap_->capacity = capacity; + return 1; +} +heap *h_copy_of(heap *_heap_, size_t (*copy_func)(size_t)) +{ + heap *result = h_new(_heap_->capacity, _heap_->HO, _heap_->cmp); + if (!result) + return ((void *)0); + if (copy_func) + { + for (size_t i = 0; i < _heap_->count; i++) + result->buffer[i] = copy_func(_heap_->buffer[i]); + } + else + memcpy(result->buffer, _heap_->buffer, sizeof(size_t) * _heap_->count); + result->count = _heap_->count; + return result; +} +_Bool h_equals(heap *_heap1_, heap *_heap2_) +{ + if (h_count(_heap1_) != h_count(_heap2_)) + return 0; + for (size_t i = 0; i < h_count(_heap1_); i++) + { + if (_heap1_->cmp(_heap1_->buffer[i], _heap2_->buffer[i]) != 0) + return 0; + } + return 1; +} +cmc_string h_to_string(heap *_heap_) +{ + cmc_string str; + heap *h_ = _heap_; + const char *name = "heap"; + const char *t = h_->HO == 1 ? "MaxHeap" : "MinHeap"; + snprintf(str.s, cmc_string_len, cmc_string_fmt_heap, name, h_, h_->buffer, h_->capacity, h_->count, t, h_->cmp); + return str; +} heap_iter *h_iter_new(heap *target) { heap_iter *iter = malloc(sizeof(heap_iter)); if (!iter) - return NULL; + return ((void *)0); h_iter_init(iter, target); return iter; } @@ -168,63 +209,105 @@ void h_iter_init(heap_iter *iter, heap *target) { iter->target = target; iter->cursor = 0; - iter->start = true; + iter->start = 1; iter->end = h_empty(target); } -bool h_iter_start(heap_iter *iter) { return h_empty(iter->target) || iter->start; } -bool h_iter_end(heap_iter *iter) { return h_empty(iter->target) || iter->end; } +_Bool h_iter_start(heap_iter *iter) { return h_empty(iter->target) || iter->start; } +_Bool h_iter_end(heap_iter *iter) { return h_empty(iter->target) || iter->end; } void h_iter_to_start(heap_iter *iter) { - iter->cursor = 0; - iter->start = true; - iter->end = h_empty(iter->target); + if (!h_empty(iter->target)) + { + iter->cursor = 0; + iter->start = 1; + iter->end = h_empty(iter->target); + } } void h_iter_to_end(heap_iter *iter) { - iter->cursor = iter->target->count - 1; - iter->start = h_empty(iter->target); - iter->end = true; + if (!h_empty(iter->target)) + { + iter->cursor = h_count(iter->target) - 1; + iter->start = h_empty(iter->target); + iter->end = 1; + } } -bool h_iter_next(heap_iter *iter) +_Bool h_iter_next(heap_iter *iter) { if (iter->end) - return false; - iter->start = false; - if (iter->cursor == iter->target->count - 1) - iter->end = true; - else - iter->cursor++; - return true; + return 0; + if (iter->cursor + 1 == h_count(iter->target)) + { + iter->end = 1; + return 0; + } + iter->start = h_empty(iter->target); + iter->cursor++; + return 1; } -bool h_iter_prev(heap_iter *iter) +_Bool h_iter_prev(heap_iter *iter) { if (iter->start) - return false; - iter->end = false; + return 0; if (iter->cursor == 0) - iter->start = true; - else - iter->cursor--; - return true; + { + iter->start = 1; + return 0; + } + iter->end = h_empty(iter->target); + iter->cursor--; + return 1; +} +_Bool h_iter_advance(heap_iter *iter, size_t steps) +{ + if (iter->start) + return 0; + if (iter->cursor + 1 == h_count(iter->target)) + { + iter->end = 1; + return 0; + } + if (steps == 0 || iter->cursor + steps >= h_count(iter->target)) + return 0; + iter->start = h_empty(iter->target); + if (iter->end) + return 0; + iter->cursor += steps; + return 1; +} +_Bool h_iter_rewind(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(heap_iter *iter, size_t index) +{ + if (index >= h_count(iter->target)) + 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(heap_iter *iter) { if (h_empty(iter->target)) - return h_impl_default_value(); + return (size_t){0}; return iter->target->buffer[iter->cursor]; } size_t h_iter_index(heap_iter *iter) { return iter->cursor; } -static bool h_impl_grow(heap *_heap_) -{ - size_t new_capacity = _heap_->capacity * 2; - size_t *new_buffer = realloc(_heap_->buffer, sizeof(size_t) * new_capacity); - if (!new_buffer) - return false; - _heap_->buffer = new_buffer; - _heap_->capacity = new_capacity; - return true; -} -static bool h_impl_float_up(heap *_heap_, size_t index) +static _Bool h_impl_float_up(heap *_heap_, size_t index) { size_t C = index; size_t child = _heap_->buffer[C]; @@ -233,15 +316,15 @@ static bool h_impl_float_up(heap *_heap_, size_t index) while (C > 0 && _heap_->cmp(child, parent) * mod > 0) { size_t tmp = _heap_->buffer[C]; - _heap_->buffer[C] = _heap_->buffer[(index - 1) / 2]; - _heap_->buffer[(index - 1) / 2] = tmp; - C = (index - 1) / 2; + _heap_->buffer[C] = _heap_->buffer[(C - 1) / 2]; + _heap_->buffer[(C - 1) / 2] = tmp; + C = (C - 1) / 2; child = _heap_->buffer[C]; - parent = _heap_->buffer[(index - 1) / 2]; + parent = _heap_->buffer[(C - 1) / 2]; } - return true; + return 1; } -static bool h_impl_float_down(heap *_heap_, size_t index) +static _Bool h_impl_float_down(heap *_heap_, size_t index) { int mod = _heap_->HO; while (index < _heap_->count) @@ -267,7 +350,7 @@ static bool h_impl_float_down(heap *_heap_, size_t index) else break; } - return true; + return 1; } static heap_iter h_impl_it_start(heap *_heap_) { diff --git a/tests/codecov/src/intervalheap.c b/tests/codecov/src/intervalheap.c new file mode 100644 index 0000000..9186b2a --- /dev/null +++ b/tests/codecov/src/intervalheap.c @@ -0,0 +1,588 @@ +#include + +//CMC_GENERATE_INTERVALHEAP(ih, intervalheap, size_t) + +typedef struct intervalheap_s +{ + struct intervalheap_node_s *buffer; + size_t capacity; + size_t size; + size_t count; + int (*cmp)(size_t, size_t); + struct intervalheap_iter_s (*it_start)(struct intervalheap_s *); + struct intervalheap_iter_s (*it_end)(struct intervalheap_s *); +} intervalheap, *intervalheap_ptr; +typedef struct intervalheap_node_s +{ + size_t data[2]; +} intervalheap_node, *intervalheap_node_ptr; +typedef struct intervalheap_iter_s +{ + struct intervalheap_s *target; + size_t cursor; + _Bool start; + _Bool end; +} intervalheap_iter, *intervalheap_iter_ptr; +intervalheap *ih_new(size_t capacity, int (*compare)(size_t, size_t)); +void ih_clear(intervalheap *_heap_, void (*deallocator)(size_t)); +void ih_free(intervalheap *_heap_, void (*deallocator)(size_t)); +_Bool ih_insert(intervalheap *_heap_, size_t element); +_Bool ih_remove_max(intervalheap *_heap_, size_t *result); +_Bool ih_remove_min(intervalheap *_heap_, size_t *result); +_Bool ih_update_max(intervalheap *_heap_, size_t element); +_Bool ih_update_min(intervalheap *_heap_, size_t element); +_Bool ih_max(intervalheap *_heap_, size_t *value); +_Bool ih_min(intervalheap *_heap_, size_t *value); +_Bool ih_contains(intervalheap *_heap_, size_t element); +_Bool ih_empty(intervalheap *_heap_); +_Bool ih_full(intervalheap *_heap_); +size_t ih_count(intervalheap *_heap_); +size_t ih_capacity(intervalheap *_heap_); +_Bool ih_resize(intervalheap *_heap_, size_t capacity); +intervalheap *ih_copy_of(intervalheap *_set_, size_t (*copy_func)(size_t)); +_Bool ih_equals(intervalheap *_heap1_, intervalheap *_heap2_); +cmc_string ih_to_string(intervalheap *_heap_); +intervalheap_iter *ih_iter_new(intervalheap *target); +void ih_iter_free(intervalheap_iter *iter); +void ih_iter_init(intervalheap_iter *iter, intervalheap *target); +_Bool ih_iter_start(intervalheap_iter *iter); +_Bool ih_iter_end(intervalheap_iter *iter); +void ih_iter_to_start(intervalheap_iter *iter); +void ih_iter_to_end(intervalheap_iter *iter); +_Bool ih_iter_next(intervalheap_iter *iter); +_Bool ih_iter_prev(intervalheap_iter *iter); +_Bool ih_iter_advance(intervalheap_iter *iter, size_t steps); +_Bool ih_iter_rewind(intervalheap_iter *iter, size_t steps); +_Bool ih_iter_go_to(intervalheap_iter *iter, size_t index); +size_t ih_iter_value(intervalheap_iter *iter); +size_t ih_iter_index(intervalheap_iter *iter); +static void ih_impl_float_up_max(intervalheap *_heap_); +static void ih_impl_float_up_min(intervalheap *_heap_); +static void ih_impl_float_down_max(intervalheap *_heap_); +static void ih_impl_float_down_min(intervalheap *_heap_); +static intervalheap_iter ih_impl_it_start(intervalheap *_heap_); +static intervalheap_iter ih_impl_it_end(intervalheap *_heap_); +intervalheap *ih_new(size_t capacity, int (*compare)(size_t, size_t)) +{ + if (capacity == 0 || capacity == 0xffffffffffffffff) + return ((void *)0); + intervalheap *_heap_ = malloc(sizeof(intervalheap)); + if (!_heap_) + return ((void *)0); + capacity = capacity % 2 == 0 ? capacity / 2 : (capacity + 1) / 2; + _heap_->buffer = malloc(sizeof(intervalheap_node) * capacity); + if (!_heap_->buffer) + { + free(_heap_); + return ((void *)0); + } + memset(_heap_->buffer, 0, sizeof(intervalheap_node) * capacity); + _heap_->capacity = capacity; + _heap_->size = 0; + _heap_->count = 0; + _heap_->cmp = compare; + _heap_->it_start = ih_impl_it_start; + _heap_->it_end = ih_impl_it_end; + return _heap_; +} +void ih_clear(intervalheap *_heap_, void (*deallocator)(size_t)) +{ + if (deallocator) + { + for (size_t i = 0; i < _heap_->count; i++) + { + deallocator(_heap_->buffer[i / 2].data[i % 2]); + } + } + memset(_heap_->buffer, 0, sizeof(size_t) * _heap_->capacity); + _heap_->size = 0; + _heap_->count = 0; +} +void ih_free(intervalheap *_heap_, void (*deallocator)(size_t)) +{ + if (deallocator) + { + for (size_t i = 0; i < _heap_->count; i++) + { + deallocator(_heap_->buffer[i / 2].data[i % 2]); + } + } + free(_heap_->buffer); + free(_heap_); +} +_Bool ih_insert(intervalheap *_heap_, size_t element) +{ + if (ih_full(_heap_)) + { + if (!ih_resize(_heap_, ih_capacity(_heap_) * 4)) + return 0; + } + if (ih_count(_heap_) % 2 == 0) + { + _heap_->buffer[_heap_->size].data[0] = element; + _heap_->buffer[_heap_->size].data[1] = (size_t){0}; + _heap_->size++; + } + else + { + intervalheap_node *curr_node = &(_heap_->buffer[_heap_->size - 1]); + if (_heap_->cmp(curr_node->data[0], element) > 0) + { + curr_node->data[1] = curr_node->data[0]; + curr_node->data[0] = element; + } + else + { + curr_node->data[1] = element; + } + } + _heap_->count++; + if (ih_count(_heap_) <= 2) + return 1; + intervalheap_node *parent = &(_heap_->buffer[(_heap_->size - 1) / 2]); + if (_heap_->cmp(parent->data[0], element) > 0) + ih_impl_float_up_min(_heap_); + else if (_heap_->cmp(parent->data[1], element) < 0) + ih_impl_float_up_max(_heap_); + return 1; +} +_Bool ih_remove_max(intervalheap *_heap_, size_t *result) +{ + if (ih_empty(_heap_)) + return 0; + if (ih_count(_heap_) == 1) + { + *result = _heap_->buffer[0].data[0]; + _heap_->buffer[0].data[0] = (size_t){0}; + _heap_->count--; + return 1; + } + else + *result = _heap_->buffer[0].data[1]; + intervalheap_node *last_node = &(_heap_->buffer[_heap_->size - 1]); + if (ih_count(_heap_) % 2 == 1) + { + _heap_->buffer[0].data[1] = last_node->data[0]; + last_node->data[0] = (size_t){0}; + _heap_->size--; + } + else + { + _heap_->buffer[0].data[1] = last_node->data[1]; + last_node->data[1] = (size_t){0}; + } + _heap_->count--; + ih_impl_float_down_max(_heap_); + return 1; +} +_Bool ih_remove_min(intervalheap *_heap_, size_t *result) +{ + if (ih_empty(_heap_)) + return 0; + *result = _heap_->buffer[0].data[0]; + if (ih_count(_heap_) == 1) + { + _heap_->buffer[0].data[0] = (size_t){0}; + _heap_->count--; + return 1; + } + intervalheap_node *last_node = &(_heap_->buffer[_heap_->size - 1]); + _heap_->buffer[0].data[0] = last_node->data[0]; + if (ih_count(_heap_) % 2 == 1) + { + last_node->data[0] = (size_t){0}; + _heap_->size--; + } + else + { + last_node->data[0] = last_node->data[1]; + last_node->data[1] = (size_t){0}; + } + _heap_->count--; + ih_impl_float_down_min(_heap_); + return 1; +} +_Bool ih_update_max(intervalheap *_heap_, size_t element) +{ + if (ih_empty(_heap_)) + return 0; + if (ih_count(_heap_) == 1) + { + _heap_->buffer[0].data[0] = element; + } + else if (_heap_->cmp(element, _heap_->buffer[0].data[0]) < 0) + { + _heap_->buffer[0].data[1] = _heap_->buffer[0].data[0]; + _heap_->buffer[0].data[0] = element; + ih_impl_float_down_max(_heap_); + } + else + { + _heap_->buffer[0].data[1] = element; + ih_impl_float_down_max(_heap_); + } + return 1; +} +_Bool ih_update_min(intervalheap *_heap_, size_t element) +{ + if (ih_empty(_heap_)) + return 0; + if (ih_count(_heap_) == 1) + { + _heap_->buffer[0].data[0] = element; + } + else if (_heap_->cmp(element, _heap_->buffer[0].data[1]) > 0) + { + _heap_->buffer[0].data[0] = _heap_->buffer[0].data[1]; + _heap_->buffer[0].data[1] = element; + ih_impl_float_down_min(_heap_); + } + else + { + _heap_->buffer[0].data[0] = element; + ih_impl_float_down_min(_heap_); + } + return 1; +} +_Bool ih_max(intervalheap *_heap_, size_t *value) +{ + if (ih_empty(_heap_)) + return 0; + if (ih_count(_heap_) == 1) + *value = _heap_->buffer[0].data[0]; + else + *value = _heap_->buffer[0].data[1]; + return 1; +} +_Bool ih_min(intervalheap *_heap_, size_t *value) +{ + if (ih_empty(_heap_)) + return 0; + *value = _heap_->buffer[0].data[0]; + return 1; +} +_Bool ih_contains(intervalheap *_heap_, size_t element) +{ + for (size_t i = 0; i < _heap_->count; i++) + { + if (_heap_->cmp(_heap_->buffer[i / 2].data[i % 2], element) == 0) + return 1; + } + return 0; +} +_Bool ih_empty(intervalheap *_heap_) { return _heap_->count == 0; } +_Bool ih_full(intervalheap *_heap_) { return _heap_->size >= _heap_->capacity && _heap_->count % 2 == 0; } +size_t ih_count(intervalheap *_heap_) { return _heap_->count; } +size_t ih_capacity(intervalheap *_heap_) { return _heap_->capacity; } +_Bool ih_resize(intervalheap *_heap_, size_t capacity) +{ + if (ih_capacity(_heap_) == capacity) + return 1; + if (capacity < ih_count(_heap_)) + return 0; + capacity = capacity % 2 == 0 ? capacity / 2 : (capacity + 1) / 2; + intervalheap_node *new_buffer = realloc(_heap_->buffer, sizeof(intervalheap_node) * capacity); + if (!new_buffer) + return 0; + memset(new_buffer + _heap_->capacity, 0, sizeof(intervalheap_node) * _heap_->capacity); + _heap_->buffer = new_buffer; + _heap_->capacity = capacity; + return 1; +} +intervalheap *ih_copy_of(intervalheap *_heap_, size_t (*copy_func)(size_t)) +{ + intervalheap *result = malloc(sizeof(intervalheap)); + if (!result) + return ((void *)0); + memcpy(result, _heap_, sizeof(intervalheap)); + result->buffer = malloc(sizeof(intervalheap_node) * _heap_->capacity); + if (!result->buffer) + { + free(result); + return ((void *)0); + } + if (copy_func) + { + for (size_t i = 0; i < _heap_->count; i++) + result->buffer[i / 2].data[i % 2] = copy_func(_heap_->buffer[i / 2].data[i % 2]); + } + else + memcpy(result->buffer, _heap_->buffer, sizeof(intervalheap_node) * _heap_->capacity); + return result; +} +_Bool ih_equals(intervalheap *_heap1_, intervalheap *_heap2_) +{ + if (ih_count(_heap1_) != ih_count(_heap2_)) + return 0; + for (size_t i = 0; i < _heap1_->count; i++) + { + size_t element1 = _heap1_->buffer[i / 2].data[i % 2]; + size_t element2 = _heap2_->buffer[i / 2].data[i % 2]; + if (_heap1_->cmp(element1, element2) == 0) + return 1; + } + return 0; +} +cmc_string ih_to_string(intervalheap *_heap_) +{ + cmc_string str; + intervalheap *h_ = _heap_; + const char *name = "intervalheap"; + snprintf(str.s, cmc_string_len, cmc_string_fmt_intervalheap, name, h_, h_->buffer, h_->capacity, h_->size, h_->count, h_->cmp); + return str; +} +intervalheap_iter *ih_iter_new(intervalheap *target) +{ + intervalheap_iter *iter = malloc(sizeof(intervalheap_iter)); + if (!iter) + return ((void *)0); + ih_iter_init(iter, target); + return iter; +} +void ih_iter_free(intervalheap_iter *iter) { free(iter); } +void ih_iter_init(intervalheap_iter *iter, intervalheap *target) +{ + iter->target = target; + iter->cursor = 0; + iter->start = 1; + iter->end = ih_empty(target); +} +_Bool ih_iter_start(intervalheap_iter *iter) { return ih_empty(iter->target) || iter->start; } +_Bool ih_iter_end(intervalheap_iter *iter) { return ih_empty(iter->target) || iter->end; } +void ih_iter_to_start(intervalheap_iter *iter) +{ + if (!ih_empty(iter->target)) + { + iter->cursor = 0; + iter->start = 1; + iter->end = ih_empty(iter->target); + } +} +void ih_iter_to_end(intervalheap_iter *iter) +{ + if (!ih_empty(iter->target)) + { + iter->cursor = iter->target->count - 1; + iter->start = ih_empty(iter->target); + iter->end = 1; + } +} +_Bool ih_iter_next(intervalheap_iter *iter) +{ + if (iter->end) + return 0; + if (iter->cursor + 1 == ih_count(iter->target)) + { + iter->end = 1; + return 0; + } + iter->start = ih_empty(iter->target); + iter->cursor++; + return 1; +} +_Bool ih_iter_prev(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(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 >= ih_count(iter->target)) + return 0; + iter->start = ih_empty(iter->target); + iter->cursor += steps; + return 1; +} +_Bool ih_iter_rewind(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(intervalheap_iter *iter, size_t index) +{ + if (index >= ih_count(iter->target)) + 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(intervalheap_iter *iter) +{ + if (ih_empty(iter->target)) + return (size_t){0}; + return iter->target->buffer[iter->cursor / 2].data[iter->cursor % 2]; +} +size_t ih_iter_index(intervalheap_iter *iter) { return iter->cursor; } +static void ih_impl_float_up_max(intervalheap *_heap_) +{ + size_t index = _heap_->size - 1; + intervalheap_node *curr_node = &(_heap_->buffer[index]); + while (index > 0) + { + size_t P_index = (index - 1) / 2; + intervalheap_node *parent = &(_heap_->buffer[P_index]); + if (index == _heap_->size - 1 && ih_count(_heap_) % 2 != 0) + { + if (_heap_->cmp(curr_node->data[0], parent->data[1]) < 0) + break; + size_t tmp = curr_node->data[0]; + curr_node->data[0] = parent->data[1]; + parent->data[1] = tmp; + } + else + { + if (_heap_->cmp(curr_node->data[1], parent->data[1]) < 0) + break; + size_t tmp = curr_node->data[1]; + curr_node->data[1] = parent->data[1]; + parent->data[1] = tmp; + } + index = P_index; + curr_node = parent; + } +} +static void ih_impl_float_up_min(intervalheap *_heap_) +{ + size_t index = _heap_->size - 1; + intervalheap_node *curr_node = &(_heap_->buffer[index]); + while (index > 0) + { + size_t P_index = (index - 1) / 2; + intervalheap_node *parent = &(_heap_->buffer[P_index]); + if (_heap_->cmp(curr_node->data[0], parent->data[0]) >= 0) + break; + size_t tmp = curr_node->data[0]; + curr_node->data[0] = parent->data[0]; + parent->data[0] = tmp; + index = P_index; + curr_node = parent; + } +} +static void ih_impl_float_down_max(intervalheap *_heap_) +{ + size_t index = 0; + intervalheap_node *curr_node = &(_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) + { + intervalheap_node *L = &(_heap_->buffer[L_index]); + intervalheap_node *R = &(_heap_->buffer[R_index]); + if (R_index == _heap_->size - 1 && ih_count(_heap_) % 2 != 0) + child = _heap_->cmp(L->data[1], R->data[0]) > 0 ? L_index : R_index; + else + child = _heap_->cmp(L->data[1], R->data[1]) > 0 ? L_index : R_index; + } + else + child = L_index; + intervalheap_node *child_node = &(_heap_->buffer[child]); + if (child == _heap_->size - 1 && ih_count(_heap_) % 2 != 0) + { + if (_heap_->cmp(curr_node->data[1], child_node->data[0]) >= 0) + break; + size_t tmp = child_node->data[0]; + child_node->data[0] = curr_node->data[1]; + curr_node->data[1] = tmp; + } + else + { + if (_heap_->cmp(curr_node->data[1], child_node->data[1]) >= 0) + break; + size_t tmp = child_node->data[1]; + child_node->data[1] = curr_node->data[1]; + curr_node->data[1] = tmp; + if (_heap_->cmp(child_node->data[0], child_node->data[1]) > 0) + { + tmp = child_node->data[0]; + child_node->data[0] = child_node->data[1]; + child_node->data[1] = tmp; + } + } + index = child; + curr_node = child_node; + } +} +static void ih_impl_float_down_min(intervalheap *_heap_) +{ + size_t index = 0; + intervalheap_node *curr_node = &(_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) + { + intervalheap_node *L = &(_heap_->buffer[L_index]); + intervalheap_node *R = &(_heap_->buffer[R_index]); + child = _heap_->cmp(L->data[0], R->data[0]) < 0 ? L_index : R_index; + } + else + child = L_index; + intervalheap_node *child_node = &(_heap_->buffer[child]); + if (_heap_->cmp(curr_node->data[0], child_node->data[0]) < 0) + break; + size_t tmp = child_node->data[0]; + child_node->data[0] = curr_node->data[0]; + curr_node->data[0] = tmp; + if (child != _heap_->size - 1 || ih_count(_heap_) % 2 == 0) + { + if (_heap_->cmp(child_node->data[0], child_node->data[1]) > 0) + { + tmp = child_node->data[0]; + child_node->data[0] = child_node->data[1]; + child_node->data[1] = tmp; + } + } + index = child; + curr_node = child_node; + } +} +static intervalheap_iter ih_impl_it_start(intervalheap *_heap_) +{ + intervalheap_iter iter; + ih_iter_init(&iter, _heap_); + ih_iter_to_start(&iter); + return iter; +} +static intervalheap_iter ih_impl_it_end(intervalheap *_heap_) +{ + intervalheap_iter iter; + ih_iter_init(&iter, _heap_); + ih_iter_to_end(&iter); + return iter; +} diff --git a/tests/codecov/src/linkedlist.c b/tests/codecov/src/linkedlist.c index e9f0c60..cf52034 100644 --- a/tests/codecov/src/linkedlist.c +++ b/tests/codecov/src/linkedlist.c @@ -1,6 +1,6 @@ -#include "cmc/linkedlist.h" +#include -//LINKEDLIST_GENERATE(ll, linkedlist, , size_t) +//CMC_GENERATE_LINKEDLIST(ll, linkedlist, size_t) typedef struct linkedlist_s { @@ -21,95 +21,97 @@ typedef struct linkedlist_iter_s struct linkedlist_s *target; struct linkedlist_node_s *cursor; size_t index; - bool start; - bool end; + _Bool start; + _Bool end; } linkedlist_iter, *linkedlist_iter_ptr; linkedlist *ll_new(void); -void ll_clear(linkedlist *_list_); -void ll_free(linkedlist *_list_); -bool ll_push_front(linkedlist *_list_, size_t element); -bool ll_push(linkedlist *_list_, size_t element, size_t index); -bool ll_push_back(linkedlist *_list_, size_t element); -bool ll_pop_front(linkedlist *_list_); -bool ll_pop(linkedlist *_list_, size_t index); -bool ll_pop_back(linkedlist *_list_); -bool ll_push_if(linkedlist *_list_, size_t element, size_t index, bool condition); -bool ll_pop_if(linkedlist *_list_, size_t index, bool condition); +void ll_clear(linkedlist *_list_, void (*deallocator)(size_t)); +void ll_free(linkedlist *_list_, void (*deallocator)(size_t)); +_Bool ll_push_front(linkedlist *_list_, size_t element); +_Bool ll_push_at(linkedlist *_list_, size_t element, size_t index); +_Bool ll_push_back(linkedlist *_list_, size_t element); +_Bool ll_pop_front(linkedlist *_list_); +_Bool ll_pop_at(linkedlist *_list_, size_t index); +_Bool ll_pop_back(linkedlist *_list_); size_t ll_front(linkedlist *_list_); size_t ll_get(linkedlist *_list_, size_t index); size_t *ll_get_ref(linkedlist *_list_, size_t index); size_t ll_back(linkedlist *_list_); -bool ll_contains(linkedlist *_list_, size_t element, int (*comparator)(size_t, size_t)); -bool ll_empty(linkedlist *_list_); +_Bool ll_contains(linkedlist *_list_, size_t element, int (*comparator)(size_t, size_t)); +_Bool ll_empty(linkedlist *_list_); size_t ll_count(linkedlist *_list_); +linkedlist *ll_copy_of(linkedlist *_list_, size_t (*copy_func)(size_t)); +_Bool ll_equals(linkedlist *_list1_, linkedlist *_list2_, int (*comparator)(size_t, size_t)); +cmc_string ll_to_string(linkedlist *_list_); linkedlist_node *ll_new_node(size_t element); void ll_free_node(linkedlist_node *_node_); linkedlist_node *ll_head(linkedlist *_list_); linkedlist_node *ll_get_node(linkedlist *_list_, size_t index); linkedlist_node *ll_tail(linkedlist *_list_); -bool ll_insert_after(linkedlist *_owner_, linkedlist_node *_node_, size_t element); -bool ll_insert_before(linkedlist *_owner_, linkedlist_node *_node_, size_t element); -bool ll_remove_after(linkedlist *_owner_, linkedlist_node *_node_); -bool ll_remove_current(linkedlist *_owner_, linkedlist_node *_node_); -bool ll_remove_before(linkedlist *_owner_, linkedlist_node *_node_); +_Bool ll_insert_after(linkedlist *_owner_, linkedlist_node *_node_, size_t element); +_Bool ll_insert_before(linkedlist *_owner_, linkedlist_node *_node_, size_t element); +_Bool ll_remove_after(linkedlist *_owner_, linkedlist_node *_node_); +_Bool ll_remove_current(linkedlist *_owner_, linkedlist_node *_node_); +_Bool ll_remove_before(linkedlist *_owner_, linkedlist_node *_node_); linkedlist_node *ll_next_node(linkedlist_node *_node_); linkedlist_node *ll_prev_node(linkedlist_node *_node_); linkedlist_iter *ll_iter_new(linkedlist *target); void ll_iter_free(linkedlist_iter *iter); void ll_iter_init(linkedlist_iter *iter, linkedlist *target); -bool ll_iter_start(linkedlist_iter *iter); -bool ll_iter_end(linkedlist_iter *iter); +_Bool ll_iter_start(linkedlist_iter *iter); +_Bool ll_iter_end(linkedlist_iter *iter); void ll_iter_to_start(linkedlist_iter *iter); void ll_iter_to_end(linkedlist_iter *iter); -bool ll_iter_next(linkedlist_iter *iter); -bool ll_iter_prev(linkedlist_iter *iter); +_Bool ll_iter_next(linkedlist_iter *iter); +_Bool ll_iter_prev(linkedlist_iter *iter); +_Bool ll_iter_advance(linkedlist_iter *iter, size_t steps); +_Bool ll_iter_rewind(linkedlist_iter *iter, size_t steps); +_Bool ll_iter_go_to(linkedlist_iter *iter, size_t index); size_t ll_iter_value(linkedlist_iter *iter); size_t *ll_iter_rvalue(linkedlist_iter *iter); size_t ll_iter_index(linkedlist_iter *iter); linkedlist_node *ll_iter_node(linkedlist_iter *iter); -static inline size_t ll_impl_default_value(void) -{ - size_t _empty_value_; - memset(&_empty_value_, 0, sizeof(size_t)); - return _empty_value_; -} static linkedlist_iter ll_impl_it_start(linkedlist *_list_); static linkedlist_iter ll_impl_it_end(linkedlist *_list_); linkedlist *ll_new(void) { linkedlist *_list_ = malloc(sizeof(linkedlist)); if (!_list_) - return NULL; + return ((void *)0); _list_->count = 0; - _list_->head = NULL; - _list_->tail = NULL; + _list_->head = ((void *)0); + _list_->tail = ((void *)0); _list_->it_start = ll_impl_it_start; _list_->it_end = ll_impl_it_end; return _list_; } -void ll_clear(linkedlist *_list_) +void ll_clear(linkedlist *_list_, void (*deallocator)(size_t)) { linkedlist_node *scan = _list_->head; - while (_list_->head != NULL) + while (_list_->head != ((void *)0)) { _list_->head = _list_->head->next; + if (deallocator) + { + deallocator(scan->data); + } free(scan); scan = _list_->head; } _list_->count = 0; - _list_->head = NULL; - _list_->tail = NULL; + _list_->head = ((void *)0); + _list_->tail = ((void *)0); } -void ll_free(linkedlist *_list_) +void ll_free(linkedlist *_list_, void (*deallocator)(size_t)) { - ll_clear(_list_); + ll_clear(_list_, deallocator); free(_list_); } -bool ll_push_front(linkedlist *_list_, size_t element) +_Bool ll_push_front(linkedlist *_list_, size_t element) { linkedlist_node *_node_ = ll_new_node(element); if (!_node_) - return false; + return 0; if (ll_empty(_list_)) { _list_->head = _node_; @@ -122,12 +124,12 @@ bool ll_push_front(linkedlist *_list_, size_t element) _list_->head = _node_; } _list_->count++; - return true; + return 1; } -bool ll_push(linkedlist *_list_, size_t element, size_t index) +_Bool ll_push_at(linkedlist *_list_, size_t element, size_t index) { if (index > _list_->count) - return false; + return 0; if (index == 0) { return ll_push_front(_list_, element); @@ -138,20 +140,20 @@ bool ll_push(linkedlist *_list_, size_t element, size_t index) } linkedlist_node *_node_ = ll_new_node(element); if (!_node_) - return false; + return 0; 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++; - return true; + return 1; } -bool ll_push_back(linkedlist *_list_, size_t element) +_Bool ll_push_back(linkedlist *_list_, size_t element) { linkedlist_node *_node_ = ll_new_node(element); if (!_node_) - return false; + return 0; if (ll_empty(_list_)) { _list_->head = _node_; @@ -164,28 +166,28 @@ bool ll_push_back(linkedlist *_list_, size_t element) _list_->tail = _node_; } _list_->count++; - return true; + return 1; } -bool ll_pop_front(linkedlist *_list_) +_Bool ll_pop_front(linkedlist *_list_) { if (ll_empty(_list_)) - return false; + return 0; linkedlist_node *_node_ = _list_->head; _list_->head = _list_->head->next; free(_node_); - if (_list_->head == NULL) - _list_->tail = NULL; + if (_list_->head == ((void *)0)) + _list_->tail = ((void *)0); else - _list_->head->prev = NULL; + _list_->head->prev = ((void *)0); _list_->count--; - return true; + return 1; } -bool ll_pop(linkedlist *_list_, size_t index) +_Bool ll_pop_at(linkedlist *_list_, size_t index) { if (ll_empty(_list_)) - return false; + return 0; if (index >= _list_->count) - return false; + return 0; if (index == 0) { return ll_pop_front(_list_); @@ -196,92 +198,132 @@ bool ll_pop(linkedlist *_list_, size_t index) } linkedlist_node *_node_ = ll_get_node(_list_, index); if (!_node_) - return false; + return 0; _node_->next->prev = _node_->prev; _node_->prev->next = _node_->next; free(_node_); _list_->count--; - return true; + return 1; } -bool ll_pop_back(linkedlist *_list_) +_Bool ll_pop_back(linkedlist *_list_) { if (ll_empty(_list_)) - return false; + return 0; linkedlist_node *_node_ = _list_->tail; _list_->tail = _list_->tail->prev; free(_node_); - if (_list_->tail == NULL) - _list_->head = NULL; + if (_list_->tail == ((void *)0)) + _list_->head = ((void *)0); else - _list_->tail->next = NULL; + _list_->tail->next = ((void *)0); _list_->count--; - return true; -} -bool ll_push_if(linkedlist *_list_, size_t element, size_t index, bool condition) -{ - if (condition) - return ll_push(_list_, element, index); - return false; -} -bool ll_pop_if(linkedlist *_list_, size_t index, bool condition) -{ - if (condition) - return ll_pop(_list_, index); - return false; + return 1; } size_t ll_front(linkedlist *_list_) { if (ll_empty(_list_)) - return ll_impl_default_value(); + return (size_t){0}; return _list_->head->data; } size_t ll_get(linkedlist *_list_, size_t index) { if (index >= _list_->count || ll_empty(_list_)) - return ll_impl_default_value(); + return (size_t){0}; linkedlist_node *scan = ll_get_node(_list_, index); - if (scan == NULL) - return ll_impl_default_value(); + if (scan == ((void *)0)) + return (size_t){0}; return scan->data; } size_t *ll_get_ref(linkedlist *_list_, size_t index) { if (index >= _list_->count) - return NULL; + return ((void *)0); if (ll_empty(_list_)) - return NULL; + return ((void *)0); linkedlist_node *scan = ll_get_node(_list_, index); - if (scan == NULL) - return NULL; + if (scan == ((void *)0)) + return ((void *)0); return &(scan->data); } size_t ll_back(linkedlist *_list_) { if (ll_empty(_list_)) - return ll_impl_default_value(); + return (size_t){0}; return _list_->tail->data; } -bool ll_contains(linkedlist *_list_, size_t element, int (*comparator)(size_t, size_t)) +_Bool ll_contains(linkedlist *_list_, size_t element, int (*comparator)(size_t, size_t)) { linkedlist_node *scan = _list_->head; - while (scan != NULL) + while (scan != ((void *)0)) { if (comparator(scan->data, element) == 0) - return true; + return 1; scan = scan->next; } - return false; + return 0; } -bool ll_empty(linkedlist *_list_) { return _list_->count == 0; } +_Bool ll_empty(linkedlist *_list_) { return _list_->count == 0; } size_t ll_count(linkedlist *_list_) { return _list_->count; } +linkedlist *ll_copy_of(linkedlist *_list_, size_t (*copy_func)(size_t)) +{ + linkedlist *result = ll_new(); + if (!result) + return ((void *)0); + linkedlist_node *scan = _list_->head; + while (scan != ((void *)0)) + { + linkedlist_node *new_node; + if (copy_func) + new_node = ll_new_node(copy_func(scan->data)); + else + new_node = ll_new_node(scan->data); + 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; + return result; +} +_Bool ll_equals(linkedlist *_list1_, linkedlist *_list2_, int (*comparator)(size_t, size_t)) +{ + if (ll_count(_list1_) != ll_count(_list2_)) + return 0; + linkedlist_node *scan1 = _list1_->head; + linkedlist_node *scan2 = _list2_->head; + while (scan1 != ((void *)0) && scan2 != ((void *)0)) + { + if (comparator(scan1->data, scan2->data) != 0) + return 0; + scan1 = scan1->next; + scan2 = scan2->next; + } + return 1; +} +cmc_string ll_to_string(linkedlist *_list_) +{ + cmc_string str; + linkedlist *l_ = _list_; + const char *name = "linkedlist"; + snprintf(str.s, cmc_string_len, cmc_string_fmt_linkedlist, name, l_, l_->count, l_->head, l_->tail); + return str; +} linkedlist_node *ll_new_node(size_t element) { linkedlist_node *_node_ = malloc(sizeof(linkedlist_node)); if (!_node_) - return NULL; + return ((void *)0); _node_->data = element; - _node_->next = NULL; - _node_->prev = NULL; + _node_->next = ((void *)0); + _node_->prev = ((void *)0); return _node_; } void ll_free_node(linkedlist_node *_node_) { free(_node_); } @@ -289,10 +331,10 @@ linkedlist_node *ll_head(linkedlist *_list_) { return _list_->head; } linkedlist_node *ll_get_node(linkedlist *_list_, size_t index) { if (index >= _list_->count) - return NULL; + return ((void *)0); if (ll_empty(_list_)) - return NULL; - linkedlist_node *_node_ = NULL; + return ((void *)0); + linkedlist_node *_node_ = ((void *)0); if (index <= _list_->count / 2) { _node_ = _list_->head; @@ -312,42 +354,42 @@ linkedlist_node *ll_get_node(linkedlist *_list_, size_t index) return _node_; } linkedlist_node *ll_tail(linkedlist *_list_) { return _list_->tail; } -bool ll_insert_after(linkedlist *_owner_, linkedlist_node *_node_, size_t element) +_Bool ll_insert_after(linkedlist *_owner_, linkedlist_node *_node_, size_t element) { linkedlist_node *new_node = ll_new_node(element); if (!new_node) - return false; + return 0; new_node->next = _node_->next; - if (_node_->next != NULL) + 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++; - return true; + return 1; } -bool ll_insert_before(linkedlist *_owner_, linkedlist_node *_node_, size_t element) +_Bool ll_insert_before(linkedlist *_owner_, linkedlist_node *_node_, size_t element) { linkedlist_node *new_node = ll_new_node(element); if (!new_node) - return false; + return 0; new_node->prev = _node_->prev; - if (_node_->prev != NULL) + 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++; - return true; + return 1; } -bool ll_remove_after(linkedlist *_owner_, linkedlist_node *_node_) +_Bool ll_remove_after(linkedlist *_owner_, linkedlist_node *_node_) { - if (_node_->next == NULL) - return false; + if (_node_->next == ((void *)0)) + return 0; linkedlist_node *tmp = _node_->next; - if (tmp->next != NULL) + if (tmp->next != ((void *)0)) { _node_->next = _node_->next->next; _node_->next->prev = _node_; @@ -356,28 +398,28 @@ bool ll_remove_after(linkedlist *_owner_, linkedlist_node *_node_) _owner_->tail = _node_; free(tmp); _owner_->count--; - return true; + return 1; } -bool ll_remove_current(linkedlist *_owner_, linkedlist_node *_node_) +_Bool ll_remove_current(linkedlist *_owner_, linkedlist_node *_node_) { - if (_node_->prev != NULL) + if (_node_->prev != ((void *)0)) _node_->prev->next = _node_->next; else _owner_->head = _node_->next; - if (_node_->next != NULL) + if (_node_->next != ((void *)0)) _node_->next->prev = _node_->prev; else _owner_->tail = _node_->prev; free(_node_); _owner_->count--; - return true; + return 1; } -bool ll_remove_before(linkedlist *_owner_, linkedlist_node *_node_) +_Bool ll_remove_before(linkedlist *_owner_, linkedlist_node *_node_) { - if (_node_->prev == NULL) - return false; + if (_node_->prev == ((void *)0)) + return 0; linkedlist_node *tmp = _node_->prev; - if (tmp->prev != NULL) + if (tmp->prev != ((void *)0)) { _node_->prev = _node_->prev->prev; _node_->prev->next = _node_; @@ -386,7 +428,7 @@ bool ll_remove_before(linkedlist *_owner_, linkedlist_node *_node_) _owner_->head = _node_; free(tmp); _owner_->count--; - return true; + return 1; } linkedlist_node *ll_next_node(linkedlist_node *_node_) { return _node_->next; } linkedlist_node *ll_prev_node(linkedlist_node *_node_) { return _node_->prev; } @@ -394,7 +436,7 @@ linkedlist_iter *ll_iter_new(linkedlist *target) { linkedlist_iter *iter = malloc(sizeof(linkedlist_iter)); if (!iter) - return NULL; + return ((void *)0); ll_iter_init(iter, target); return iter; } @@ -404,63 +446,113 @@ void ll_iter_init(linkedlist_iter *iter, linkedlist *target) iter->target = target; iter->cursor = target->head; iter->index = 0; - iter->start = true; + iter->start = 1; iter->end = ll_empty(target); } -bool ll_iter_start(linkedlist_iter *iter) { return ll_empty(iter->target) || iter->start; } -bool ll_iter_end(linkedlist_iter *iter) { return ll_empty(iter->target) || iter->end; } +_Bool ll_iter_start(linkedlist_iter *iter) { return ll_empty(iter->target) || iter->start; } +_Bool ll_iter_end(linkedlist_iter *iter) { return ll_empty(iter->target) || iter->end; } void ll_iter_to_start(linkedlist_iter *iter) { - iter->cursor = iter->target->head; - iter->index = 0; - iter->start = true; - iter->end = ll_empty(iter->target); + if (!ll_empty(iter->target)) + { + iter->cursor = iter->target->head; + iter->index = 0; + iter->start = 1; + iter->end = ll_empty(iter->target); + } } void ll_iter_to_end(linkedlist_iter *iter) { - iter->cursor = iter->target->tail; - iter->index = iter->target->count - 1; - iter->start = ll_empty(iter->target); - iter->end = true; + 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; + } } -bool ll_iter_next(linkedlist_iter *iter) +_Bool ll_iter_next(linkedlist_iter *iter) { if (iter->end) - return false; - iter->start = ll_empty(iter->target); - if (iter->cursor->next == NULL) - iter->end = true; - else + return 0; + if (iter->cursor->next == ((void *)0)) { - iter->cursor = iter->cursor->next; - iter->index++; + iter->end = 1; + return 0; } - return true; + iter->start = ll_empty(iter->target); + iter->cursor = iter->cursor->next; + iter->index++; + return 1; } -bool ll_iter_prev(linkedlist_iter *iter) +_Bool ll_iter_prev(linkedlist_iter *iter) { if (iter->start) - return false; - iter->end = ll_empty(iter->target); - if (iter->cursor->prev == NULL) - iter->start = true; - else + return 0; + if (iter->cursor->prev == ((void *)0)) { - iter->cursor = iter->cursor->prev; - iter->index--; + iter->start = 1; + return 0; } - return true; + iter->end = ll_empty(iter->target); + iter->cursor = iter->cursor->prev; + iter->index--; + return 1; +} +_Bool ll_iter_advance(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 >= ll_count(iter->target)) + 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(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(linkedlist_iter *iter, size_t index) +{ + if (index >= ll_count(iter->target)) + 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(linkedlist_iter *iter) { if (ll_empty(iter->target)) - return ll_impl_default_value(); + return (size_t){0}; return iter->cursor->data; } size_t *ll_iter_rvalue(linkedlist_iter *iter) { if (ll_empty(iter->target)) - return NULL; + return ((void *)0); return &(iter->cursor->data); } size_t ll_iter_index(linkedlist_iter *iter) { return iter->index; } diff --git a/tests/codecov/src/list.c b/tests/codecov/src/list.c index 32cb6a1..d8d9831 100644 --- a/tests/codecov/src/list.c +++ b/tests/codecov/src/list.c @@ -1,6 +1,6 @@ -#include "cmc/list.h" +#include -//LIST_GENERATE(l, list, , size_t) +//CMC_GENERATE_LIST(l, list, size_t) typedef struct list_s { @@ -14,71 +14,68 @@ typedef struct list_iter_s { struct list_s *target; size_t cursor; - bool start; - bool end; + _Bool start; + _Bool end; } list_iter, *list_iter_ptr; list *l_new(size_t capacity); list *l_new_from(size_t *elements, size_t size); -void l_clear(list *_list_); -void l_free(list *_list_); -bool l_push_front(list *_list_, size_t element); -bool l_push(list *_list_, size_t element, size_t index); -bool l_push_back(list *_list_, size_t element); -bool l_pop_front(list *_list_); -bool l_pop(list *_list_, size_t index); -bool l_pop_back(list *_list_); -bool l_push_if(list *_list_, size_t element, size_t index, bool condition); -bool l_pop_if(list *_list_, size_t index, bool condition); -bool l_prepend(list *_list_, size_t *elements, size_t size); -bool l_insert(list *_list_, size_t *elements, size_t size, size_t index); -bool l_append(list *_list_, size_t *elements, size_t size); -bool l_remove(list *_list_, size_t from, size_t to); -list *l_extract(list *_list_, size_t from, size_t to); +void l_clear(list *_list_, void (*deallocator)(size_t)); +void l_free(list *_list_, void (*deallocator)(size_t)); +_Bool l_push_front(list *_list_, size_t element); +_Bool l_push_at(list *_list_, size_t element, size_t index); +_Bool l_push_back(list *_list_, size_t element); +_Bool l_pop_front(list *_list_); +_Bool l_pop_at(list *_list_, size_t index); +_Bool l_pop_back(list *_list_); +_Bool l_seq_push_front(list *_list_, size_t *elements, size_t size); +_Bool l_seq_push_at(list *_list_, size_t *elements, size_t size, size_t index); +_Bool l_seq_push_back(list *_list_, size_t *elements, size_t size); +_Bool l_seq_pop_at(list *_list_, size_t from, size_t to); +list *l_seq_sublist(list *_list_, size_t from, size_t to); size_t l_front(list *_list_); size_t l_get(list *_list_, size_t index); size_t *l_get_ref(list *_list_, size_t index); size_t l_back(list *_list_); -size_t l_indexof(list *_list_, size_t element, int (*comparator)(size_t, size_t), bool from_start); -bool l_contains(list *_list_, size_t element, int (*comparator)(size_t, size_t)); -bool l_empty(list *_list_); -bool l_full(list *_list_); +size_t l_indexof(list *_list_, size_t element, int (*comparator)(size_t, size_t), _Bool from_start); +_Bool l_contains(list *_list_, size_t element, int (*comparator)(size_t, size_t)); +_Bool l_empty(list *_list_); +_Bool l_full(list *_list_); size_t l_count(list *_list_); -bool l_fits(list *_list_, size_t size); +_Bool l_fits(list *_list_, size_t size); size_t l_capacity(list *_list_); +_Bool l_resize(list *_list_, size_t capacity); +list *l_copy_of(list *_list_, size_t (*copy_func)(size_t)); +_Bool l_equals(list *_list1_, list *_list2_, int (*comparator)(size_t, size_t)); +cmc_string l_to_string(list *_list_); list_iter *l_iter_new(list *target); void l_iter_free(list_iter *iter); void l_iter_init(list_iter *iter, list *target); -bool l_iter_start(list_iter *iter); -bool l_iter_end(list_iter *iter); +_Bool l_iter_start(list_iter *iter); +_Bool l_iter_end(list_iter *iter); void l_iter_to_start(list_iter *iter); void l_iter_to_end(list_iter *iter); -bool l_iter_next(list_iter *iter); -bool l_iter_prev(list_iter *iter); +_Bool l_iter_next(list_iter *iter); +_Bool l_iter_prev(list_iter *iter); +_Bool l_iter_advance(list_iter *iter, size_t steps); +_Bool l_iter_rewind(list_iter *iter, size_t steps); +_Bool l_iter_go_to(list_iter *iter, size_t index); size_t l_iter_value(list_iter *iter); size_t *l_iter_rvalue(list_iter *iter); size_t l_iter_index(list_iter *iter); -static inline size_t l_impl_default_value(void) -{ - size_t _empty_value_; - memset(&_empty_value_, 0, sizeof(size_t)); - return _empty_value_; -} - -static bool l_impl_grow(list *_list_, size_t required); static list_iter l_impl_it_start(list *_list_); static list_iter l_impl_it_end(list *_list_); list *l_new(size_t capacity) { if (capacity < 1) - return NULL; + return ((void *)0); list *_list_ = malloc(sizeof(list)); if (!_list_) - return NULL; + return ((void *)0); _list_->buffer = malloc(capacity * sizeof(size_t)); if (!_list_->buffer) { free(_list_); - return NULL; + return ((void *)0); } memset(_list_->buffer, 0, capacity * sizeof(size_t)); _list_->capacity = capacity; @@ -90,30 +87,40 @@ list *l_new(size_t capacity) list *l_new_from(size_t *elements, size_t size) { if (size == 0) - return NULL; + return ((void *)0); list *_list_ = l_new(size + size / 2); if (!_list_) - return NULL; + return ((void *)0); memcpy(_list_->buffer, elements, size * sizeof(size_t)); _list_->count = size; return _list_; } -void l_clear(list *_list_) +void l_clear(list *_list_, void (*deallocator)(size_t)) { + if (deallocator) + { + for (size_t i = 0; i < _list_->count; i++) + deallocator(_list_->buffer[i]); + } memset(_list_->buffer, 0, sizeof(size_t) * _list_->capacity); _list_->count = 0; } -void l_free(list *_list_) +void l_free(list *_list_, void (*deallocator)(size_t)) { + if (deallocator) + { + for (size_t i = 0; i < _list_->count; i++) + deallocator(_list_->buffer[i]); + } free(_list_->buffer); free(_list_); } -bool l_push_front(list *_list_, size_t element) +_Bool l_push_front(list *_list_, size_t element) { if (l_full(_list_)) { - if (!l_impl_grow(_list_, _list_->count + 1)) - return false; + if (!l_resize(_list_, l_count(_list_) * 2)) + return 0; } if (!l_empty(_list_)) { @@ -121,183 +128,155 @@ bool l_push_front(list *_list_, size_t element) } _list_->buffer[0] = element; _list_->count++; - return true; + return 1; } -bool l_push(list *_list_, size_t element, size_t index) +_Bool l_push_at(list *_list_, size_t element, size_t index) { if (index > _list_->count) - return false; - if (index == 0) - { - return l_push_front(_list_, element); - } - else if (index == _list_->count) - { - return l_push_back(_list_, element); - } + return 0; if (l_full(_list_)) { - if (!l_impl_grow(_list_, _list_->count + 1)) - return false; + if (!l_resize(_list_, l_count(_list_) * 2)) + return 0; } memmove(_list_->buffer + index + 1, _list_->buffer + index, (_list_->count - index) * sizeof(size_t)); _list_->buffer[index] = element; _list_->count++; - return true; + return 1; } -bool l_push_back(list *_list_, size_t element) +_Bool l_push_back(list *_list_, size_t element) { if (l_full(_list_)) { - if (!l_impl_grow(_list_, _list_->count + 1)) - return false; + if (!l_resize(_list_, l_count(_list_) * 2)) + return 0; } _list_->buffer[_list_->count++] = element; - return true; + return 1; } -bool l_pop_front(list *_list_) +_Bool l_pop_front(list *_list_) { if (l_empty(_list_)) - return false; + return 0; memmove(_list_->buffer, _list_->buffer + 1, _list_->count * sizeof(size_t)); - _list_->buffer[--_list_->count] = l_impl_default_value(); - return true; + _list_->buffer[--_list_->count] = (size_t){0}; + return 1; } -bool l_pop(list *_list_, size_t index) +_Bool l_pop_at(list *_list_, size_t index) { - if (l_empty(_list_)) - return false; if (index >= _list_->count) - return false; - if (index == 0) - { - return l_pop_front(_list_); - } - else if (index == _list_->count - 1) - { - return l_pop_back(_list_); - } + return 0; memmove(_list_->buffer + index, _list_->buffer + index + 1, (_list_->count - index) * sizeof(size_t)); - _list_->buffer[--_list_->count] = l_impl_default_value(); - return true; + _list_->buffer[--_list_->count] = (size_t){0}; + return 1; } -bool l_pop_back(list *_list_) +_Bool l_pop_back(list *_list_) { if (l_empty(_list_)) - return false; - _list_->buffer[--_list_->count] = l_impl_default_value(); - return true; + return 0; + _list_->buffer[--_list_->count] = (size_t){0}; + return 1; } -bool l_push_if(list *_list_, size_t element, size_t index, bool condition) -{ - if (condition) - return l_push(_list_, element, index); - return false; -} -bool l_pop_if(list *_list_, size_t index, bool condition) -{ - if (condition) - return l_pop(_list_, index); - return false; -} -bool l_prepend(list *_list_, size_t *elements, size_t size) +_Bool l_seq_push_front(list *_list_, size_t *elements, size_t size) { if (size == 0) - return false; + return 0; if (!l_fits(_list_, size)) { - if (!l_impl_grow(_list_, _list_->count + size)) - return false; + if (!l_resize(_list_, l_count(_list_) + size)) + return 0; } memmove(_list_->buffer + size, _list_->buffer, _list_->count * sizeof(size_t)); memcpy(_list_->buffer, elements, size * sizeof(size_t)); _list_->count += size; - return true; + return 1; } -bool l_insert(list *_list_, size_t *elements, size_t size, size_t index) +_Bool l_seq_push_at(list *_list_, size_t *elements, size_t size, size_t index) { if (size == 0 || index > _list_->count) - return false; + return 0; if (index == 0) - return l_prepend(_list_, elements, size); + return l_seq_push_front(_list_, elements, size); else if (index == _list_->count) - return l_append(_list_, elements, size); + return l_seq_push_back(_list_, elements, size); else { if (!l_fits(_list_, size)) { - if (!l_impl_grow(_list_, _list_->count + size)) - return false; + if (!l_resize(_list_, l_count(_list_) + size)) + return 0; } memmove(_list_->buffer + index + size, _list_->buffer + index, (_list_->count - index) * sizeof(size_t)); memcpy(_list_->buffer + index, elements, size * sizeof(size_t)); _list_->count += size; } - return true; + return 1; } -bool l_append(list *_list_, size_t *elements, size_t size) +_Bool l_seq_push_back(list *_list_, size_t *elements, size_t size) { if (size == 0) - return false; + return 0; if (!l_fits(_list_, size)) { - if (!l_impl_grow(_list_, _list_->count + size)) - return false; + if (!l_resize(_list_, _list_->count + size)) + return 0; } memcpy(_list_->buffer + _list_->count, elements, size * sizeof(size_t)); _list_->count += size; - return true; + return 1; } -bool l_remove(list *_list_, size_t from, size_t to) +_Bool l_seq_pop_at(list *_list_, size_t from, size_t to) { if (from > to || to >= _list_->count) - return false; + 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; - return true; + return 1; } -list *l_extract(list *_list_, size_t from, size_t to) +list *l_seq_sublist(list *_list_, size_t from, size_t to) { if (from > to || to >= _list_->count) - return false; + return 0; size_t length = to - from + 1; - list *result = l_new_from(_list_->buffer + from, length); + list *result = l_new(length); if (!result) - return NULL; + return ((void *)0); + memcpy(result->buffer, _list_->buffer, _list_->count * 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; return result; } size_t l_front(list *_list_) { if (l_empty(_list_)) - return l_impl_default_value(); + return (size_t){0}; return _list_->buffer[0]; } size_t l_get(list *_list_, size_t index) { if (index >= _list_->count || l_empty(_list_)) - return l_impl_default_value(); + return (size_t){0}; return _list_->buffer[index]; } size_t *l_get_ref(list *_list_, size_t index) { if (index >= _list_->count) - return NULL; + return ((void *)0); if (l_empty(_list_)) - return NULL; + return ((void *)0); return &(_list_->buffer[index]); } size_t l_back(list *_list_) { if (l_empty(_list_)) - return l_impl_default_value(); + return (size_t){0}; return _list_->buffer[_list_->count - 1]; } -size_t l_indexof(list *_list_, size_t element, int (*comparator)(size_t, size_t), bool from_start) +size_t l_indexof(list *_list_, size_t element, int (*comparator)(size_t, size_t), _Bool from_start) { if (from_start) { @@ -317,25 +296,72 @@ size_t l_indexof(list *_list_, size_t element, int (*comparator)(size_t, size_t) } return _list_->count; } -bool l_contains(list *_list_, size_t element, int (*comparator)(size_t, size_t)) +_Bool l_contains(list *_list_, size_t element, int (*comparator)(size_t, size_t)) { for (size_t i = 0; i < _list_->count; i++) { if (comparator(_list_->buffer[i], element) == 0) - return true; + return 1; } - return false; + return 0; } -bool l_empty(list *_list_) { return _list_->count == 0; } -bool l_full(list *_list_) { return _list_->count >= _list_->capacity; } +_Bool l_empty(list *_list_) { return _list_->count == 0; } +_Bool l_full(list *_list_) { return _list_->count >= _list_->capacity; } size_t l_count(list *_list_) { return _list_->count; } -bool l_fits(list *_list_, size_t size) { return _list_->count + size <= _list_->capacity; } +_Bool l_fits(list *_list_, size_t size) { return _list_->count + size <= _list_->capacity; } size_t l_capacity(list *_list_) { return _list_->capacity; } +_Bool l_resize(list *_list_, size_t capacity) +{ + if (l_capacity(_list_) == capacity) + return 1; + if (capacity < l_count(_list_)) + return 0; + size_t *new_buffer = realloc(_list_->buffer, sizeof(size_t) * capacity); + if (!new_buffer) + return 0; + _list_->buffer = new_buffer; + _list_->capacity = capacity; + return 1; +} +list *l_copy_of(list *_list_, size_t (*copy_func)(size_t)) +{ + list *result = l_new(_list_->capacity); + if (!result) + return ((void *)0); + if (copy_func) + { + for (size_t i = 0; i < _list_->count; i++) + result->buffer[i] = copy_func(_list_->buffer[i]); + } + else + memcpy(result->buffer, _list_->buffer, sizeof(size_t) * _list_->count); + result->count = _list_->count; + return result; +} +_Bool l_equals(list *_list1_, list *_list2_, int (*comparator)(size_t, size_t)) +{ + if (l_count(_list1_) != l_count(_list2_)) + return 0; + for (size_t i = 0; i < l_count(_list1_); i++) + { + if (comparator(_list1_->buffer[i], _list2_->buffer[i]) != 0) + return 0; + } + return 0; +} +cmc_string l_to_string(list *_list_) +{ + cmc_string str; + list *l_ = _list_; + const char *name = "list"; + snprintf(str.s, cmc_string_len, cmc_string_fmt_list, name, l_, l_->buffer, l_->capacity, l_->count); + return str; +} list_iter *l_iter_new(list *target) { list_iter *iter = malloc(sizeof(list_iter)); if (!iter) - return NULL; + return ((void *)0); l_iter_init(iter, target); return iter; } @@ -344,70 +370,108 @@ void l_iter_init(list_iter *iter, list *target) { iter->target = target; iter->cursor = 0; - iter->start = true; + iter->start = 1; iter->end = l_empty(target); } -bool l_iter_start(list_iter *iter) { return l_empty(iter->target) || iter->start; } -bool l_iter_end(list_iter *iter) { return l_empty(iter->target) || iter->end; } +_Bool l_iter_start(list_iter *iter) { return l_empty(iter->target) || iter->start; } +_Bool l_iter_end(list_iter *iter) { return l_empty(iter->target) || iter->end; } void l_iter_to_start(list_iter *iter) { - iter->cursor = 0; - iter->start = true; - iter->end = l_empty(iter->target); + if (!l_empty(iter->target)) + { + iter->cursor = 0; + iter->start = 1; + iter->end = l_empty(iter->target); + } } void l_iter_to_end(list_iter *iter) { - iter->start = l_empty(iter->target); - iter->cursor = l_empty(iter->target) ? 0 : iter->target->count - 1; - iter->end = true; + if (!l_empty(iter->target)) + { + iter->start = l_empty(iter->target); + iter->cursor = l_empty(iter->target) ? 0 : iter->target->count - 1; + iter->end = 1; + } } -bool l_iter_next(list_iter *iter) +_Bool l_iter_next(list_iter *iter) { if (iter->end) - return false; + return 0; + if (iter->cursor + 1 == l_count(iter->target)) + { + iter->end = 1; + return 0; + } iter->start = l_empty(iter->target); - if (iter->cursor == iter->target->count - 1) - iter->end = true; - else - iter->cursor++; - return true; + iter->cursor++; + return 1; } -bool l_iter_prev(list_iter *iter) +_Bool l_iter_prev(list_iter *iter) { if (iter->start) - return false; - iter->end = l_empty(iter->target); + return 0; if (iter->cursor == 0) - iter->start = true; - else - iter->cursor--; - return true; + { + iter->start = 1; + return 0; + } + iter->end = l_empty(iter->target); + iter->cursor--; + return 1; +} +_Bool l_iter_advance(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 >= l_count(iter->target)) + return 0; + iter->start = l_empty(iter->target); + iter->cursor += steps; + return 1; +} +_Bool l_iter_rewind(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(list_iter *iter, size_t index) +{ + if (index >= l_count(iter->target)) + 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(list_iter *iter) { if (l_empty(iter->target)) - return l_impl_default_value(); + return (size_t){0}; return iter->target->buffer[iter->cursor]; } size_t *l_iter_rvalue(list_iter *iter) { if (l_empty(iter->target)) - return NULL; + return ((void *)0); return &(iter->target->buffer[iter->cursor]); } size_t l_iter_index(list_iter *iter) { return iter->cursor; } -static bool l_impl_grow(list *_list_, size_t required) -{ - size_t new_capacity = _list_->capacity * 2; - if (new_capacity < required) - new_capacity = required; - size_t *new_buffer = realloc(_list_->buffer, sizeof(size_t) * new_capacity); - if (!new_buffer) - return false; - _list_->buffer = new_buffer; - _list_->capacity = new_capacity; - return true; -} static list_iter l_impl_it_start(list *_list_) { list_iter iter; diff --git a/tests/codecov/src/multimap.c b/tests/codecov/src/multimap.c index 87b2224..9f598b5 100644 --- a/tests/codecov/src/multimap.c +++ b/tests/codecov/src/multimap.c @@ -1,6 +1,6 @@ -#include "ext/multimap.h" +#include -//MULTIMAP_GENERATE(mm, multimap, , size_t, size_t) +//CMC_GENERATE_MULTIMAP(mm, multimap, size_t, size_t) typedef struct multimap_s { @@ -28,51 +28,48 @@ typedef struct multimap_iter_s size_t index; size_t first; size_t last; - bool start; - bool end; + _Bool start; + _Bool end; } multimap_iter, *multimap_iter_ptr; multimap *mm_new(size_t capacity, double load, int (*compare)(size_t, size_t), size_t (*hash)(size_t)); -void mm_clear(multimap *_map_); -void mm_free(multimap *_map_); -bool mm_insert(multimap *_map_, size_t key, size_t value); -bool mm_remove(multimap *_map_, size_t key, size_t *value); -size_t mm_remove_all(multimap *_map_, size_t key); -bool mm_insert_if(multimap *_map_, size_t key, size_t value, bool condition); -bool mm_remove_if(multimap *_map_, size_t key, size_t *value, bool condition); -bool mm_max(multimap *_map_, size_t *key, size_t *value); -bool mm_min(multimap *_map_, size_t *key, size_t *value); +void mm_clear(multimap *_map_, void (*deallocator)(size_t, size_t)); +void mm_free(multimap *_map_, void (*deallocator)(size_t, size_t)); +_Bool mm_insert(multimap *_map_, size_t key, size_t value); +_Bool mm_update(multimap *_map_, size_t key, size_t new_value, size_t *old_value); +size_t mm_update_all(multimap *_map_, size_t key, size_t new_value, size_t **old_values); +_Bool mm_remove(multimap *_map_, size_t key, size_t *out_value); +size_t mm_remove_all(multimap *_map_, size_t key, size_t **out_values); +_Bool mm_max(multimap *_map_, size_t *key, size_t *value); +_Bool mm_min(multimap *_map_, size_t *key, size_t *value); size_t mm_get(multimap *_map_, size_t key); size_t *mm_get_ref(multimap *_map_, size_t key); -bool mm_contains(multimap *_map_, size_t key); -bool mm_empty(multimap *_map_); +_Bool mm_contains(multimap *_map_, size_t key); +_Bool mm_empty(multimap *_map_); +_Bool mm_full(multimap *_map_); size_t mm_count(multimap *_map_); +size_t mm_key_count(multimap *_map_, size_t key); size_t mm_capacity(multimap *_map_); +double mm_load(multimap *_map_); +_Bool mm_resize(multimap *_map_, size_t capacity); +multimap *mm_copy_of(multimap *_map_, size_t (*key_copy_func)(size_t), size_t (*value_copy_func)(size_t)); +_Bool mm_equals(multimap *_map1_, multimap *_map2_, _Bool ignore_key_count); +cmc_string mm_to_string(multimap *_map_); multimap_iter *mm_iter_new(multimap *target); void mm_iter_free(multimap_iter *iter); void mm_iter_init(multimap_iter *iter, multimap *target); -bool mm_iter_start(multimap_iter *iter); -bool mm_iter_end(multimap_iter *iter); +_Bool mm_iter_start(multimap_iter *iter); +_Bool mm_iter_end(multimap_iter *iter); void mm_iter_to_start(multimap_iter *iter); void mm_iter_to_end(multimap_iter *iter); -bool mm_iter_next(multimap_iter *iter); -bool mm_iter_prev(multimap_iter *iter); +_Bool mm_iter_next(multimap_iter *iter); +_Bool mm_iter_prev(multimap_iter *iter); +_Bool mm_iter_advance(multimap_iter *iter, size_t steps); +_Bool mm_iter_rewind(multimap_iter *iter, size_t steps); +_Bool mm_iter_go_to(multimap_iter *iter, size_t index); size_t mm_iter_key(multimap_iter *iter); size_t mm_iter_value(multimap_iter *iter); size_t *mm_iter_rvalue(multimap_iter *iter); size_t mm_iter_index(multimap_iter *iter); -static inline size_t mm_impl_default_key(void) -{ - size_t _empty_key_; - memset(&_empty_key_, 0, sizeof(size_t)); - return _empty_key_; -} -static inline size_t mm_impl_default_value(void) -{ - size_t _empty_value_; - memset(&_empty_value_, 0, sizeof(size_t)); - return _empty_value_; -} -bool mm_impl_grow(multimap *_map_); multimap_entry *mm_impl_new_entry(size_t key, size_t value); multimap_entry *mm_impl_get_entry(multimap *_map_, size_t key); size_t mm_impl_calculate_size(size_t required); @@ -81,18 +78,18 @@ static multimap_iter mm_impl_it_end(multimap *_map_); multimap *mm_new(size_t capacity, double load, int (*compare)(size_t, size_t), size_t (*hash)(size_t)) { if (capacity == 0 || load <= 0) - return NULL; - if (capacity >= UINTMAX_MAX * load) - return NULL; + return ((void *)0); + if (capacity >= 0xffffffffffffffff * load) + return ((void *)0); size_t real_capacity = mm_impl_calculate_size(capacity / load); multimap *_map_ = malloc(sizeof(multimap)); if (!_map_) - return NULL; + return ((void *)0); _map_->buffer = malloc(sizeof(multimap_entry_ptr[2]) * real_capacity); if (!_map_->buffer) { free(_map_); - return NULL; + return ((void *)0); } memset(_map_->buffer, 0, sizeof(multimap_entry_ptr[2]) * real_capacity); _map_->count = 0; @@ -100,25 +97,33 @@ multimap *mm_new(size_t capacity, double load, int (*compare)(size_t, size_t), s _map_->load = load; _map_->cmp = compare; _map_->hash = hash; + _map_->it_start = mm_impl_it_start; + _map_->it_end = mm_impl_it_end; return _map_; } -void mm_clear(multimap *_map_) +void mm_clear(multimap *_map_, void (*deallocator)(size_t, size_t)) { size_t index = 0; multimap_entry *scan; while (index < _map_->capacity) { scan = _map_->buffer[index][0]; - if (scan != NULL) + if (scan != ((void *)0)) { - if (scan->next == NULL && scan->prev == NULL) + if (scan->next == ((void *)0) && scan->prev == ((void *)0)) + { + if (deallocator) + deallocator(scan->key, scan->value); free(scan); + } else { - while (scan != NULL) + while (scan != ((void *)0)) { multimap_entry *tmp = scan; scan = scan->next; + if (deallocator) + deallocator(tmp->key, tmp->value); free(tmp); } } @@ -128,23 +133,45 @@ void mm_clear(multimap *_map_) memset(_map_->buffer, 0, sizeof(multimap_entry_ptr[2]) * _map_->capacity); _map_->count = 0; } -void mm_free(multimap *_map_) +void mm_free(multimap *_map_, void (*deallocator)(size_t, size_t)) { - mm_clear(_map_); + size_t index = 0; + multimap_entry *scan; + while (index < _map_->capacity) + { + scan = _map_->buffer[index][0]; + if (scan != ((void *)0)) + { + if (scan->next == ((void *)0) && scan->prev == ((void *)0)) + free(scan); + else + { + while (scan != ((void *)0)) + { + multimap_entry *tmp = scan; + scan = scan->next; + if (deallocator) + deallocator(tmp->key, tmp->value); + free(tmp); + } + } + } + index++; + } free(_map_->buffer); free(_map_); } -bool mm_insert(multimap *_map_, size_t key, size_t value) +_Bool mm_insert(multimap *_map_, size_t key, size_t value) { - if ((double)_map_->capacity * _map_->load <= (double)_map_->count) + if (mm_full(_map_)) { - if (!mm_impl_grow(_map_)) - return false; + if (!mm_resize(_map_, mm_capacity(_map_) + 1)) + return 0; } size_t hash = _map_->hash(key); size_t pos = hash % _map_->capacity; multimap_entry *entry = mm_impl_new_entry(key, value); - if (_map_->buffer[pos][0] == NULL) + if (_map_->buffer[pos][0] == ((void *)0)) { _map_->buffer[pos][0] = entry; _map_->buffer[pos][1] = entry; @@ -156,31 +183,68 @@ bool mm_insert(multimap *_map_, size_t key, size_t value) _map_->buffer[pos][1] = entry; } _map_->count++; - return true; + return 1; } -bool mm_remove(multimap *_map_, size_t key, size_t *value) +_Bool mm_update(multimap *_map_, size_t key, size_t new_value, size_t *old_value) +{ + multimap_entry *entry = mm_impl_get_entry(_map_, key); + if (!entry) + return 0; + if (old_value) + *old_value = entry->value; + entry->value = new_value; + return 0; +} +size_t mm_update_all(multimap *_map_, size_t key, size_t new_value, size_t **old_values) +{ + size_t total = mm_key_count(_map_, key); + size_t index = 0; + if (total == 0) + return total; + if (old_values) + { + *old_values = malloc(sizeof(size_t) * total); + if (!(*old_values)) + return 0; + } + size_t hash = _map_->hash(key); + multimap_entry *entry = _map_->buffer[hash % _map_->capacity][0]; + while (entry != ((void *)0)) + { + if (_map_->cmp(entry->key, key) == 0) + { + if (old_values) + (*old_values)[index++] = entry->value; + entry->value = new_value; + } + entry = entry->next; + } + return index; +} +_Bool mm_remove(multimap *_map_, size_t key, size_t *out_value) { size_t hash = _map_->hash(key); multimap_entry **head = &(_map_->buffer[hash % _map_->capacity][0]); multimap_entry **tail = &(_map_->buffer[hash % _map_->capacity][1]); - if (*head == NULL) - return false; + if (*head == ((void *)0)) + return 0; multimap_entry *entry = *head; - if (entry->next == NULL && entry->prev == NULL) + if (entry->next == ((void *)0) && entry->prev == ((void *)0)) { if (_map_->cmp(entry->key, key) == 0) { - *head = NULL; - *tail = NULL; - *value = entry->value; + *head = ((void *)0); + *tail = ((void *)0); + if (out_value) + *out_value = entry->value; } else - return false; + return 0; } else { - bool found = false; - while (entry != NULL) + _Bool found = 0; + while (entry != ((void *)0)) { if (_map_->cmp(entry->key, key) == 0) { @@ -188,43 +252,48 @@ bool mm_remove(multimap *_map_, size_t key, size_t *value) *head = entry->next; if (*tail == entry) *tail = entry->prev; - if (entry->prev != NULL) + if (entry->prev != ((void *)0)) entry->prev->next = entry->next; - if (entry->next != NULL) + if (entry->next != ((void *)0)) entry->next->prev = entry->prev; - *value = entry->value; - found = true; + if (out_value) + *out_value = entry->value; + found = 1; break; } else entry = entry->next; } if (!found) - return false; + return 0; } free(entry); _map_->count--; - return true; + return 1; } -size_t mm_remove_all(multimap *_map_, size_t key) +size_t mm_remove_all(multimap *_map_, size_t key, size_t **out_values) { - size_t total = 0; size_t hash = _map_->hash(key); multimap_entry **head = &(_map_->buffer[hash % _map_->capacity][0]); multimap_entry **tail = &(_map_->buffer[hash % _map_->capacity][1]); - if (*head == NULL) - return total; + if (*head == ((void *)0)) + return 0; + size_t total = mm_key_count(_map_, key); + size_t index = 0; + if (out_values) + *out_values = malloc(sizeof(multimap_entry) * total); multimap_entry *entry = *head; - if (entry->next == NULL) + if (entry->next == ((void *)0)) { - *head = NULL; - *tail = NULL; + *head = ((void *)0); + *tail = ((void *)0); + if (out_values) + (*out_values)[index++] = entry->value; free(entry); - total++; } else { - while (entry != NULL) + while (entry != ((void *)0)) { if (_map_->cmp(entry->key, key) == 0) { @@ -233,37 +302,26 @@ size_t mm_remove_all(multimap *_map_, size_t key) if (*tail == entry) *tail = entry->prev; multimap_entry *temp = entry->next; - if (entry->prev != NULL) + if (entry->prev != ((void *)0)) entry->prev->next = entry->next; - if (entry->next != NULL) + if (entry->next != ((void *)0)) entry->next->prev = entry->prev; + if (out_values) + (*out_values)[index++] = entry->value; free(entry); entry = temp; - total++; } else entry = entry->next; } } - _map_->count -= total; - return total; + _map_->count -= index; + return index; } -bool mm_insert_if(multimap *_map_, size_t key, size_t value, bool condition) -{ - if (condition) - return mm_insert(_map_, key, value); - return false; -} -bool mm_remove_if(multimap *_map_, size_t key, size_t *value, bool condition) -{ - if (condition) - return mm_remove(_map_, key, value); - return false; -} -bool mm_max(multimap *_map_, size_t *key, size_t *value) +_Bool mm_max(multimap *_map_, size_t *key, size_t *value) { if (mm_empty(_map_)) - return false; + return 0; multimap_iter iter; for (mm_iter_init(&iter, _map_); !mm_iter_end(&iter); mm_iter_next(&iter)) { @@ -281,12 +339,12 @@ bool mm_max(multimap *_map_, size_t *key, size_t *value) *value = result_value; } } - return true; + return 1; } -bool mm_min(multimap *_map_, size_t *key, size_t *value) +_Bool mm_min(multimap *_map_, size_t *key, size_t *value) { if (mm_empty(_map_)) - return false; + return 0; multimap_iter iter; for (mm_iter_init(&iter, _map_); !mm_iter_end(&iter); mm_iter_next(&iter)) { @@ -304,47 +362,155 @@ bool mm_min(multimap *_map_, size_t *key, size_t *value) *value = result_value; } } - return true; + return 1; } size_t mm_get(multimap *_map_, size_t key) { multimap_entry *entry = mm_impl_get_entry(_map_, key); if (!entry) - return mm_impl_default_value(); + return (size_t){0}; return entry->value; } size_t *mm_get_ref(multimap *_map_, size_t key) { multimap_entry *entry = mm_impl_get_entry(_map_, key); if (!entry) - return NULL; + return ((void *)0); return &(entry->value); } -bool mm_contains(multimap *_map_, size_t key) { return mm_impl_get_entry(_map_, key) != NULL; } -bool mm_empty(multimap *_map_) { return _map_->count == 0; } +_Bool mm_contains(multimap *_map_, size_t key) { return mm_impl_get_entry(_map_, key) != ((void *)0); } +_Bool mm_empty(multimap *_map_) { return _map_->count == 0; } +_Bool mm_full(multimap *_map_) { return (double)mm_capacity(_map_) * mm_load(_map_) <= (double)mm_count(_map_); } size_t mm_count(multimap *_map_) { return _map_->count; } +size_t mm_key_count(multimap *_map_, size_t key) +{ + size_t hash = _map_->hash(key); + multimap_entry *entry = _map_->buffer[hash % _map_->capacity][0]; + size_t total_count = 0; + if (!entry) + return total_count; + while (entry != ((void *)0)) + { + if (_map_->cmp(entry->key, key) == 0) + total_count++; + entry = entry->next; + } + return total_count; +} size_t mm_capacity(multimap *_map_) { return _map_->capacity; } +double mm_load(multimap *_map_) { return _map_->load; } +_Bool mm_resize(multimap *_map_, size_t capacity) +{ + if (mm_capacity(_map_) == capacity) + return 1; + if (mm_capacity(_map_) > capacity / mm_load(_map_)) + return 1; + if (capacity >= 0xffffffffffffffff * mm_load(_map_)) + return 0; + size_t theoretical_size = mm_impl_calculate_size(capacity); + if (theoretical_size < mm_count(_map_) / mm_load(_map_)) + return 0; + multimap *_new_map_ = mm_new(capacity, mm_load(_map_), _map_->cmp, _map_->hash); + if (!_new_map_) + return 0; + multimap_iter iter; + for (mm_iter_init(&iter, _map_); !mm_iter_end(&iter); mm_iter_next(&iter)) + { + size_t key = mm_iter_key(&iter); + size_t value = mm_iter_value(&iter); + mm_insert(_new_map_, key, value); + } + if (mm_count(_map_) != mm_count(_new_map_)) + { + mm_free(_new_map_, ((void *)0)); + return 0; + } + multimap_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; + mm_free(_new_map_, ((void *)0)); + return 1; +} +multimap *mm_copy_of(multimap *_map_, size_t (*key_copy_func)(size_t), size_t (*value_copy_func)(size_t)) +{ + multimap *result = mm_new(_map_->capacity, _map_->load, _map_->cmp, _map_->hash); + if (!result) + return ((void *)0); + multimap_iter iter; + mm_iter_init(&iter, _map_); + if (!mm_empty(_map_)) + { + for (mm_iter_to_start(&iter); !mm_iter_end(&iter); mm_iter_next(&iter)) + { + size_t key = mm_iter_key(&iter); + size_t value = mm_iter_value(&iter); + if (key_copy_func) + key = key_copy_func(key); + if (value_copy_func) + value = value_copy_func(value); + mm_insert(result, key, value); + } + } + return result; +} +_Bool mm_equals(multimap *_map1_, multimap *_map2_, _Bool ignore_key_count) +{ + if (ignore_key_count) + { + multimap_iter iter; + mm_iter_init(&iter, _map1_); + for (mm_iter_to_start(&iter); !mm_iter_end(&iter); mm_iter_next(&iter)) + { + if (mm_impl_get_entry(_map2_, mm_iter_key(&iter)) == ((void *)0)) + return 0; + } + } + else + { + if (mm_count(_map1_) != mm_count(_map2_)) + return 0; + multimap_iter iter; + mm_iter_init(&iter, _map1_); + for (mm_iter_to_start(&iter); !mm_iter_end(&iter); mm_iter_next(&iter)) + { + size_t key = mm_iter_key(&iter); + if (mm_key_count(_map1_, key) != mm_key_count(_map2_, key)) + return 0; + } + } + return 1; +} +cmc_string mm_to_string(multimap *_map_) +{ + cmc_string str; + multimap *m_ = _map_; + const char *name = "multimap"; + snprintf(str.s, cmc_string_len, cmc_string_fmt_multimap, name, m_, m_->buffer, m_->capacity, m_->count, m_->load, m_->cmp, m_->hash); + return str; +} multimap_iter *mm_iter_new(multimap *target) { multimap_iter *iter = malloc(sizeof(multimap_iter)); if (!iter) - return NULL; + return ((void *)0); mm_iter_init(iter, target); return iter; } void mm_iter_free(multimap_iter *iter) { free(iter); } void mm_iter_init(multimap_iter *iter, multimap *target) { + memset(iter, 0, sizeof(multimap_iter)); iter->target = target; - iter->cursor = 0; - iter->index = 0; - iter->start = true; + iter->start = 1; iter->end = mm_empty(target); if (!mm_empty(target)) { for (size_t i = 0; i < target->capacity; i++) { - if (target->buffer[i][0] != NULL) + if (target->buffer[i][0] != ((void *)0)) { iter->curr_entry = target->buffer[i][0]; iter->first = i; @@ -354,7 +520,7 @@ void mm_iter_init(multimap_iter *iter, multimap *target) iter->cursor = iter->first; for (size_t i = target->capacity; i > 0; i--) { - if (target->buffer[i - 1][0] != NULL) + if (target->buffer[i - 1][0] != ((void *)0)) { iter->last = i - 1; break; @@ -362,29 +528,35 @@ void mm_iter_init(multimap_iter *iter, multimap *target) } } } -bool mm_iter_start(multimap_iter *iter) { return mm_empty(iter->target) || iter->start; } -bool mm_iter_end(multimap_iter *iter) { return mm_empty(iter->target) || iter->end; } +_Bool mm_iter_start(multimap_iter *iter) { return mm_empty(iter->target) || iter->start; } +_Bool mm_iter_end(multimap_iter *iter) { return mm_empty(iter->target) || iter->end; } void mm_iter_to_start(multimap_iter *iter) { - iter->cursor = iter->first; - iter->index = 0; - iter->start = true; - iter->end = mm_empty(iter->target); - iter->curr_entry = iter->target->buffer[iter->first][0]; + if (!mm_empty(iter->target)) + { + iter->cursor = iter->first; + iter->index = 0; + iter->start = 1; + iter->end = mm_empty(iter->target); + iter->curr_entry = iter->target->buffer[iter->first][0]; + } } void mm_iter_to_end(multimap_iter *iter) { - iter->cursor = iter->last; - iter->index = iter->target->count - 1; - iter->start = mm_empty(iter->target); - iter->end = true; - iter->curr_entry = iter->target->buffer[iter->last][1]; + if (!mm_empty(iter->target)) + { + iter->cursor = iter->last; + iter->index = iter->target->count - 1; + iter->start = mm_empty(iter->target); + iter->end = 1; + iter->curr_entry = iter->target->buffer[iter->last][1]; + } } -bool mm_iter_next(multimap_iter *iter) +_Bool mm_iter_next(multimap_iter *iter) { if (iter->end) - return false; - if (iter->curr_entry->next != NULL) + return 0; + if (iter->curr_entry->next != ((void *)0)) { iter->curr_entry = iter->curr_entry->next; iter->index++; @@ -393,26 +565,23 @@ bool mm_iter_next(multimap_iter *iter) { if (iter->cursor == iter->last) { - iter->end = true; - return false; + iter->end = 1; + return 0; } - else - { + iter->cursor++; + while (iter->target->buffer[iter->cursor][0] == ((void *)0)) iter->cursor++; - while (iter->target->buffer[iter->cursor][0] == NULL) - iter->cursor++; - iter->curr_entry = iter->target->buffer[iter->cursor][0]; - iter->index++; - } + iter->curr_entry = iter->target->buffer[iter->cursor][0]; + iter->index++; } iter->start = mm_empty(iter->target); - return true; + return 1; } -bool mm_iter_prev(multimap_iter *iter) +_Bool mm_iter_prev(multimap_iter *iter) { if (iter->start) - return false; - if (iter->curr_entry->prev != NULL) + return 0; + if (iter->curr_entry->prev != ((void *)0)) { iter->curr_entry = iter->curr_entry->prev; iter->index--; @@ -421,98 +590,99 @@ bool mm_iter_prev(multimap_iter *iter) { if (iter->cursor == iter->first) { - iter->start = true; - return false; + iter->start = 1; + return 0; } - else - { + iter->cursor--; + while (iter->target->buffer[iter->cursor][1] == ((void *)0)) iter->cursor--; - while (iter->target->buffer[iter->cursor][1] == NULL) - iter->cursor--; - iter->curr_entry = iter->target->buffer[iter->cursor][1]; - iter->index--; - } + iter->curr_entry = iter->target->buffer[iter->cursor][1]; + iter->index--; } iter->end = mm_empty(iter->target); - return true; + return 1; +} +_Bool mm_iter_advance(multimap_iter *iter, size_t steps) +{ + if (iter->end) + return 0; + if (iter->index + 1 == mm_count(iter->target)) + { + iter->end = 1; + return 0; + } + if (steps == 0 || iter->index + steps >= mm_count(iter->target)) + return 0; + for (size_t i = 0; i < steps; i++) + mm_iter_next(iter); + return 1; +} +_Bool mm_iter_rewind(multimap_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++) + mm_iter_prev(iter); + return 1; +} +_Bool mm_iter_go_to(multimap_iter *iter, size_t index) +{ + if (index >= mm_count(iter->target)) + return 0; + if (iter->index > index) + return mm_iter_rewind(iter, iter->index - index); + else if (iter->index < index) + return mm_iter_advance(iter, index - iter->index); + return 1; } size_t mm_iter_key(multimap_iter *iter) { if (mm_empty(iter->target)) - return mm_impl_default_key(); + return (size_t){0}; return iter->curr_entry->key; } size_t mm_iter_value(multimap_iter *iter) { if (mm_empty(iter->target)) - return mm_impl_default_value(); + return (size_t){0}; return iter->curr_entry->value; } size_t *mm_iter_rvalue(multimap_iter *iter) { if (mm_empty(iter->target)) - return NULL; + return ((void *)0); return &(iter->curr_entry->value); } size_t mm_iter_index(multimap_iter *iter) { return iter->index; } -bool mm_impl_grow(multimap *_map_) -{ - size_t new_capacity = mm_impl_calculate_size(_map_->capacity * 1.5); - multimap *_new_map_ = mm_new(new_capacity, _map_->load, _map_->cmp, _map_->hash); - if (!_new_map_) - return false; - multimap_iter iter; - for (mm_iter_init(&iter, _map_); !mm_iter_end(&iter); mm_iter_next(&iter)) - { - size_t key = mm_iter_key(&iter); - size_t value = mm_iter_value(&iter); - mm_insert(_new_map_, key, value); - } - if (_map_->count != _new_map_->count) - { - mm_free(_new_map_); - return false; - } - multimap_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; - mm_free(_new_map_); - return true; -} multimap_entry *mm_impl_new_entry(size_t key, size_t value) { multimap_entry *entry = malloc(sizeof(multimap_entry)); if (!entry) - return NULL; + return ((void *)0); entry->key = key; entry->value = value; - entry->next = NULL; - entry->prev = NULL; + entry->next = ((void *)0); + entry->prev = ((void *)0); return entry; } multimap_entry *mm_impl_get_entry(multimap *_map_, size_t key) { size_t hash = _map_->hash(key); multimap_entry *entry = _map_->buffer[hash % _map_->capacity][0]; - if (entry == NULL) - return NULL; - if (entry->next == NULL && entry->prev == NULL) - { - if (_map_->cmp(entry->key, key) == 0) - return entry; - else - return NULL; - } - while (entry != NULL) + while (entry != ((void *)0)) { if (_map_->cmp(entry->key, key) == 0) return entry; entry = entry->next; } - return NULL; + return ((void *)0); } size_t mm_impl_calculate_size(size_t required) { diff --git a/tests/codecov/src/multiset.c b/tests/codecov/src/multiset.c index 708b915..6961997 100644 --- a/tests/codecov/src/multiset.c +++ b/tests/codecov/src/multiset.c @@ -1,6 +1,6 @@ -#include "ext/multiset.h" +#include -//MULTISET_GENERATE(ms, multiset, , size_t) +//CMC_GENERATE_MULTISET(ms, multiset, size_t) typedef struct multiset_s { @@ -28,58 +28,57 @@ typedef struct multiset_iter_s size_t index; size_t first; size_t last; - bool start; - bool end; + _Bool start; + _Bool end; } multiset_iter, *multiset_iter_ptr; multiset *ms_new(size_t capacity, double load, int (*compare)(size_t, size_t), size_t (*hash)(size_t)); -void ms_clear(multiset *_set_); -void ms_free(multiset *_set_); -bool ms_insert(multiset *_set_, size_t element); -bool ms_insert_many(multiset *_set_, size_t element, size_t count); -bool ms_update(multiset *_set_, size_t element, size_t multiplicity); -bool ms_remove(multiset *_set_, size_t element); +void ms_clear(multiset *_set_, void (*deallocator)(size_t)); +void ms_free(multiset *_set_, void (*deallocator)(size_t)); +_Bool ms_insert(multiset *_set_, size_t element); +_Bool ms_insert_many(multiset *_set_, size_t element, size_t count); +_Bool ms_update(multiset *_set_, size_t element, size_t multiplicity); +_Bool ms_remove(multiset *_set_, size_t element); size_t ms_remove_all(multiset *_set_, size_t element); -bool ms_insert_if(multiset *_set_, size_t element, bool condition); -bool ms_remove_if(multiset *_set_, size_t element, bool condition); -bool ms_max(multiset *_set_, size_t *value); -bool ms_min(multiset *_set_, size_t *value); +_Bool ms_max(multiset *_set_, size_t *value); +_Bool ms_min(multiset *_set_, size_t *value); size_t ms_multiplicity_of(multiset *_set_, size_t element); -bool ms_contains(multiset *_set_, size_t element); -bool ms_empty(multiset *_set_); +_Bool ms_contains(multiset *_set_, size_t element); +_Bool ms_empty(multiset *_set_); +_Bool ms_full(multiset *_set_); size_t ms_count(multiset *_set_); size_t ms_cardinality(multiset *_set_); size_t ms_capacity(multiset *_set_); +double ms_load(multiset *_set_); +_Bool ms_resize(multiset *_set_, size_t capacity); +multiset *ms_copy_of(multiset *_set_, size_t (*copy_func)(size_t)); +_Bool ms_equals(multiset *_set1_, multiset *_set2_, _Bool ignore_multiplicity); cmc_string ms_to_string(multiset *_set_); multiset *ms_union(multiset *_set1_, multiset *_set2_); multiset *ms_intersection(multiset *_set1_, multiset *_set2_); multiset *ms_difference(multiset *_set1_, multiset *_set2_); multiset *ms_summation(multiset *_set1_, multiset *_set2_); multiset *ms_symmetric_difference(multiset *_set1_, multiset *_set2_); -bool ms_is_subset(multiset *_set1_, multiset *_set2_); -bool ms_is_superset(multiset *_set1_, multiset *_set2_); -bool ms_is_proper_subset(multiset *_set1_, multiset *_set2_); -bool ms_is_proper_superset(multiset *_set1_, multiset *_set2_); -bool ms_is_disjointset(multiset *_set1_, multiset *_set2_); +_Bool ms_is_subset(multiset *_set1_, multiset *_set2_); +_Bool ms_is_superset(multiset *_set1_, multiset *_set2_); +_Bool ms_is_proper_subset(multiset *_set1_, multiset *_set2_); +_Bool ms_is_proper_superset(multiset *_set1_, multiset *_set2_); +_Bool ms_is_disjointset(multiset *_set1_, multiset *_set2_); multiset_iter *ms_iter_new(multiset *target); void ms_iter_free(multiset_iter *iter); void ms_iter_init(multiset_iter *iter, multiset *target); -bool ms_iter_start(multiset_iter *iter); -bool ms_iter_end(multiset_iter *iter); +_Bool ms_iter_start(multiset_iter *iter); +_Bool ms_iter_end(multiset_iter *iter); void ms_iter_to_start(multiset_iter *iter); void ms_iter_to_end(multiset_iter *iter); -bool ms_iter_next(multiset_iter *iter); -bool ms_iter_prev(multiset_iter *iter); +_Bool ms_iter_next(multiset_iter *iter); +_Bool ms_iter_prev(multiset_iter *iter); +_Bool ms_iter_advance(multiset_iter *iter, size_t steps); +_Bool ms_iter_rewind(multiset_iter *iter, size_t steps); +_Bool ms_iter_go_to(multiset_iter *iter, size_t index); size_t ms_iter_value(multiset_iter *iter); size_t ms_iter_multiplicity(multiset_iter *iter); size_t ms_iter_index(multiset_iter *iter); -static inline size_t ms_impl_default_value(void) -{ - size_t _empty_value_; - memset(&_empty_value_, 0, sizeof(size_t)); - return _empty_value_; -} -static multiset_entry *ms_impl_insert_and_return(multiset *_set_, size_t element, bool *new_node); -static bool ms_impl_grow(multiset *_set_); +static multiset_entry *ms_impl_insert_and_return(multiset *_set_, size_t element, _Bool *new_node); static multiset_entry *ms_impl_get_entry(multiset *_set_, size_t element); static size_t ms_impl_calculate_size(size_t required); static multiset_iter ms_impl_it_start(multiset *_set_); @@ -87,18 +86,18 @@ static multiset_iter ms_impl_it_end(multiset *_set_); multiset *ms_new(size_t capacity, double load, int (*compare)(size_t, size_t), size_t (*hash)(size_t)) { if (capacity == 0 || load <= 0 || load >= 1) - return NULL; - if (capacity >= UINTMAX_MAX * load) - return NULL; + return ((void *)0); + if (capacity >= 0xffffffffffffffff * load) + return ((void *)0); size_t real_capacity = ms_impl_calculate_size(capacity / load); multiset *_set_ = malloc(sizeof(multiset)); if (!_set_) - return NULL; + return ((void *)0); _set_->buffer = malloc(sizeof(multiset_entry) * real_capacity); if (!_set_->buffer) { free(_set_); - return NULL; + return ((void *)0); } memset(_set_->buffer, 0, sizeof(multiset_entry) * real_capacity); _set_->count = 0; @@ -111,81 +110,103 @@ multiset *ms_new(size_t capacity, double load, int (*compare)(size_t, size_t), s _set_->it_end = ms_impl_it_end; return _set_; } -void ms_clear(multiset *_set_) +void ms_clear(multiset *_set_, void (*deallocator)(size_t)) { + if (deallocator) + { + for (size_t i = 0; i < _set_->capacity; i++) + { + multiset_entry *entry = &(_set_->buffer[i]); + if (entry->state == CMC_ES_FILLED) + { + deallocator(entry->value); + } + } + } memset(_set_->buffer, 0, sizeof(multiset_entry) * _set_->capacity); _set_->count = 0; } -void ms_free(multiset *_set_) +void ms_free(multiset *_set_, void (*deallocator)(size_t)) { + if (deallocator) + { + for (size_t i = 0; i < _set_->capacity; i++) + { + multiset_entry *entry = &(_set_->buffer[i]); + if (entry->state == CMC_ES_FILLED) + { + deallocator(entry->value); + } + } + } free(_set_->buffer); free(_set_); } -bool ms_insert(multiset *_set_, size_t element) +_Bool ms_insert(multiset *_set_, size_t element) { - bool new_node; + _Bool new_node; multiset_entry *entry = ms_impl_insert_and_return(_set_, element, &new_node); if (!entry) - return false; + return 0; if (!new_node) entry->multiplicity++; _set_->cardinality++; - return true; + return 1; } -bool ms_insert_many(multiset *_set_, size_t element, size_t count) +_Bool ms_insert_many(multiset *_set_, size_t element, size_t count) { if (count == 0) - return true; - bool new_node; + return 1; + _Bool new_node; multiset_entry *entry = ms_impl_insert_and_return(_set_, element, &new_node); if (!entry) - return false; + return 0; if (new_node) entry->multiplicity = count; else entry->multiplicity += count; _set_->cardinality += count; - return true; + return 1; } -bool ms_update(multiset *_set_, size_t element, size_t multiplicity) +_Bool ms_update(multiset *_set_, size_t element, size_t multiplicity) { if (multiplicity == 0) return ms_remove_all(_set_, element); - bool new_node; + _Bool new_node; multiset_entry *entry = ms_impl_insert_and_return(_set_, element, &new_node); if (!entry) - return false; + return 0; if (new_node) _set_->cardinality++; _set_->cardinality = (_set_->cardinality - entry->multiplicity) + multiplicity; entry->multiplicity = multiplicity; - return true; + return 1; } -bool ms_remove(multiset *_set_, size_t element) +_Bool ms_remove(multiset *_set_, size_t element) { multiset_entry *result = ms_impl_get_entry(_set_, element); - if (result == NULL) - return false; + if (result == ((void *)0)) + return 0; if (result->multiplicity > 1) result->multiplicity--; else { - result->value = ms_impl_default_value(); + result->value = (size_t){0}; result->multiplicity = 0; result->dist = 0; result->state = CMC_ES_DELETED; _set_->count--; } _set_->cardinality--; - return true; + return 1; } size_t ms_remove_all(multiset *_set_, size_t element) { multiset_entry *result = ms_impl_get_entry(_set_, element); - if (result == NULL) + if (result == ((void *)0)) return 0; size_t removed = result->multiplicity; - result->value = ms_impl_default_value(); + result->value = (size_t){0}; result->multiplicity = 0; result->dist = 0; result->state = CMC_ES_DELETED; @@ -193,22 +214,10 @@ size_t ms_remove_all(multiset *_set_, size_t element) _set_->cardinality -= removed; return removed; } -bool ms_insert_if(multiset *_set_, size_t element, bool condition) -{ - if (condition) - return ms_insert(_set_, element); - return false; -} -bool ms_remove_if(multiset *_set_, size_t element, bool condition) -{ - if (condition) - return ms_remove(_set_, element); - return false; -} -bool ms_max(multiset *_set_, size_t *value) +_Bool ms_max(multiset *_set_, size_t *value) { if (ms_empty(_set_)) - return false; + return 0; multiset_iter iter; for (ms_iter_init(&iter, _set_); !ms_iter_end(&iter); ms_iter_next(&iter)) { @@ -219,12 +228,12 @@ bool ms_max(multiset *_set_, size_t *value) else if (_set_->cmp(result, *value) > 0) *value = result; } - return true; + return 1; } -bool ms_min(multiset *_set_, size_t *value) +_Bool ms_min(multiset *_set_, size_t *value) { if (ms_empty(_set_)) - return false; + return 0; multiset_iter iter; for (ms_iter_init(&iter, _set_); !ms_iter_end(&iter); ms_iter_next(&iter)) { @@ -235,7 +244,7 @@ bool ms_min(multiset *_set_, size_t *value) else if (_set_->cmp(result, *value) < 0) *value = result; } - return true; + return 1; } size_t ms_multiplicity_of(multiset *_set_, size_t element) { @@ -244,11 +253,97 @@ size_t ms_multiplicity_of(multiset *_set_, size_t element) return 0; return entry->multiplicity; } -bool ms_contains(multiset *_set_, size_t element) { return ms_impl_get_entry(_set_, element) != NULL; } -bool ms_empty(multiset *_set_) { return _set_->count == 0; } +_Bool ms_contains(multiset *_set_, size_t element) { return ms_impl_get_entry(_set_, element) != ((void *)0); } +_Bool ms_empty(multiset *_set_) { return _set_->count == 0; } +_Bool ms_full(multiset *_set_) { return (double)ms_capacity(_set_) * ms_load(_set_) <= (double)ms_count(_set_); } size_t ms_count(multiset *_set_) { return _set_->count; } size_t ms_cardinality(multiset *_set_) { return _set_->cardinality; } size_t ms_capacity(multiset *_set_) { return _set_->capacity; } +double ms_load(multiset *_set_) { return _set_->load; } +_Bool ms_resize(multiset *_set_, size_t capacity) +{ + if (ms_capacity(_set_) == capacity) + return 1; + if (ms_capacity(_set_) > capacity / ms_load(_set_)) + return 1; + if (capacity >= 0xffffffffffffffff * ms_load(_set_)) + return 0; + size_t theoretical_size = ms_impl_calculate_size(capacity); + if (theoretical_size < ms_count(_set_) / ms_load(_set_)) + return 0; + multiset *_new_set_ = ms_new(capacity, ms_load(_set_), _set_->cmp, _set_->hash); + if (!_new_set_) + return 0; + multiset_iter iter; + for (ms_iter_init(&iter, _set_); !ms_iter_end(&iter); ms_iter_next(&iter)) + { + ms_insert_many(_new_set_, ms_iter_value(&iter), ms_iter_multiplicity(&iter)); + } + if (ms_count(_set_) != ms_count(_new_set_)) + { + ms_free(_new_set_, ((void *)0)); + return 0; + } + multiset_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; + ms_free(_new_set_, ((void *)0)); + return 1; +} +multiset *ms_copy_of(multiset *_set_, size_t (*copy_func)(size_t)) +{ + multiset *result = ms_new(_set_->capacity, _set_->load, _set_->cmp, _set_->hash); + if (!result) + return ((void *)0); + if (copy_func) + { + for (size_t i = 0; i < _set_->capacity; i++) + { + multiset_entry *scan = &(_set_->buffer[i]); + if (scan->state != CMC_ES_EMPTY) + { + multiset_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 = copy_func(scan->value); + } + } + } + } + else + memcpy(result->buffer, _set_->buffer, sizeof(multiset_entry) * _set_->capacity); + result->count = _set_->count; + result->cardinality = _set_->cardinality; + return result; +} +_Bool ms_equals(multiset *_set1_, multiset *_set2_, _Bool ignore_multiplicity) +{ + if (ms_count(_set1_) != ms_count(_set2_)) + return 0; + if (!ignore_multiplicity && ms_cardinality(_set1_) != ms_cardinality(_set2_)) + return 0; + if (ms_count(_set1_) == 0) + return 1; + multiset_iter iter; + ms_iter_init(&iter, _set1_); + for (ms_iter_to_start(&iter); !ms_iter_end(&iter); ms_iter_next(&iter)) + { + multiset_entry *entry = ms_impl_get_entry(_set2_, ms_iter_value(&iter)); + if (entry == ((void *)0)) + return 0; + if (!ignore_multiplicity && entry->multiplicity != ms_iter_multiplicity(&iter)) + return 0; + } + return 1; +} cmc_string ms_to_string(multiset *_set_) { cmc_string str; @@ -261,7 +356,7 @@ multiset *ms_union(multiset *_set1_, multiset *_set2_) { multiset *_set_r_ = ms_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); if (!_set_r_) - return NULL; + return ((void *)0); multiset_iter iter1, iter2; ms_iter_init(&iter1, _set1_); ms_iter_init(&iter2, _set2_); @@ -287,7 +382,7 @@ multiset *ms_intersection(multiset *_set1_, multiset *_set2_) { multiset *_set_r_ = ms_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); if (!_set_r_) - return NULL; + return ((void *)0); multiset *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; multiset *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; multiset_iter iter; @@ -306,7 +401,7 @@ multiset *ms_difference(multiset *_set1_, multiset *_set2_) { multiset *_set_r_ = ms_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); if (!_set_r_) - return NULL; + return ((void *)0); multiset_iter iter; ms_iter_init(&iter, _set1_); for (ms_iter_to_start(&iter); !ms_iter_end(&iter); ms_iter_next(&iter)) @@ -323,7 +418,7 @@ multiset *ms_summation(multiset *_set1_, multiset *_set2_) { multiset *_set_r_ = ms_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); if (!_set_r_) - return NULL; + return ((void *)0); multiset_iter iter1, iter2; ms_iter_init(&iter1, _set1_); ms_iter_init(&iter2, _set2_); @@ -342,7 +437,7 @@ multiset *ms_symmetric_difference(multiset *_set1_, multiset *_set2_) multiset_iter iter1, iter2; multiset *_set_r_ = ms_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); if (!_set_r_) - return NULL; + return ((void *)0); ms_iter_init(&iter1, _set1_); ms_iter_init(&iter2, _set2_); for (ms_iter_to_start(&iter1); !ms_iter_end(&iter1); ms_iter_next(&iter1)) @@ -373,12 +468,12 @@ multiset *ms_symmetric_difference(multiset *_set1_, multiset *_set2_) } return _set_r_; } -bool ms_is_subset(multiset *_set1_, multiset *_set2_) +_Bool ms_is_subset(multiset *_set1_, multiset *_set2_) { if (ms_count(_set1_) > ms_count(_set2_)) - return false; + return 0; if (ms_empty(_set1_)) - return true; + return 1; multiset_iter iter; ms_iter_init(&iter, _set1_); for (ms_iter_to_start(&iter); !ms_iter_end(&iter); ms_iter_next(&iter)) @@ -387,21 +482,21 @@ bool ms_is_subset(multiset *_set1_, multiset *_set2_) size_t m1 = ms_iter_multiplicity(&iter); size_t m2 = ms_multiplicity_of(_set2_, value); if (m1 > m2) - return false; + return 0; } - return true; + return 1; } -bool ms_is_superset(multiset *_set1_, multiset *_set2_) { return ms_is_subset(_set2_, _set1_); } -bool ms_is_proper_subset(multiset *_set1_, multiset *_set2_) +_Bool ms_is_superset(multiset *_set1_, multiset *_set2_) { return ms_is_subset(_set2_, _set1_); } +_Bool ms_is_proper_subset(multiset *_set1_, multiset *_set2_) { if (ms_count(_set1_) >= ms_count(_set2_)) - return false; + return 0; if (ms_empty(_set1_)) { if (!ms_empty(_set2_)) - return true; + return 1; else - return false; + return 0; } multiset_iter iter; ms_iter_init(&iter, _set1_); @@ -411,40 +506,39 @@ bool ms_is_proper_subset(multiset *_set1_, multiset *_set2_) size_t m1 = ms_iter_multiplicity(&iter); size_t m2 = ms_multiplicity_of(_set2_, value); if (m1 >= m2) - return false; + return 0; } - return true; + return 1; } -bool ms_is_proper_superset(multiset *_set1_, multiset *_set2_) { return ms_is_proper_subset(_set2_, _set1_); } -bool ms_is_disjointset(multiset *_set1_, multiset *_set2_) +_Bool ms_is_proper_superset(multiset *_set1_, multiset *_set2_) { return ms_is_proper_subset(_set2_, _set1_); } +_Bool ms_is_disjointset(multiset *_set1_, multiset *_set2_) { if (ms_empty(_set1_)) - return true; + return 1; multiset_iter iter; ms_iter_init(&iter, _set1_); for (ms_iter_to_start(&iter); !ms_iter_end(&iter); ms_iter_next(&iter)) { size_t value = ms_iter_value(&iter); if (ms_contains(_set2_, value)) - return false; + return 0; } - return true; + return 1; } multiset_iter *ms_iter_new(multiset *target) { multiset_iter *iter = malloc(sizeof(multiset_iter)); if (!iter) - return NULL; + return ((void *)0); ms_iter_init(iter, target); return iter; } void ms_iter_free(multiset_iter *iter) { free(iter); } void ms_iter_init(multiset_iter *iter, multiset *target) { + memset(iter, 0, sizeof(multiset_iter)); iter->target = target; - iter->cursor = 0; - iter->index = 0; - iter->start = true; + iter->start = 1; iter->end = ms_empty(target); if (!ms_empty(target)) { @@ -467,68 +561,114 @@ void ms_iter_init(multiset_iter *iter, multiset *target) } } } -bool ms_iter_start(multiset_iter *iter) { return ms_empty(iter->target) || iter->start; } -bool ms_iter_end(multiset_iter *iter) { return ms_empty(iter->target) || iter->end; } +_Bool ms_iter_start(multiset_iter *iter) { return ms_empty(iter->target) || iter->start; } +_Bool ms_iter_end(multiset_iter *iter) { return ms_empty(iter->target) || iter->end; } void ms_iter_to_start(multiset_iter *iter) { - iter->cursor = iter->first; - iter->index = 0; - iter->start = true; - iter->end = ms_empty(iter->target); + if (!ms_empty(iter->target)) + { + iter->cursor = iter->first; + iter->index = 0; + iter->start = 1; + iter->end = ms_empty(iter->target); + } } void ms_iter_to_end(multiset_iter *iter) { - iter->cursor = iter->last; - iter->index = iter->target->count - 1; - iter->start = ms_empty(iter->target); - iter->end = true; + if (!ms_empty(iter->target)) + { + iter->cursor = iter->last; + iter->index = iter->target->count - 1; + iter->start = ms_empty(iter->target); + iter->end = 1; + } } -bool ms_iter_next(multiset_iter *iter) +_Bool ms_iter_next(multiset_iter *iter) { if (iter->end) - return false; - multiset_entry *scan = &(iter->target->buffer[iter->cursor]); - if (iter->cursor == iter->last) - iter->end = true; - else + return 0; + if (iter->index + 1 == ms_count(iter->target)) { - iter->index++; - while (1) - { - iter->cursor++; - scan = &(iter->target->buffer[iter->cursor]); - if (scan->state == CMC_ES_FILLED) - break; - } + iter->end = 1; + return 0; } iter->start = ms_empty(iter->target); - return true; + multiset_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 ms_iter_prev(multiset_iter *iter) +_Bool ms_iter_prev(multiset_iter *iter) { if (iter->start) - return false; - multiset_entry *scan = &(iter->target->buffer[iter->cursor]); - if (iter->cursor == iter->first) - iter->start = true; - else + return 0; + if (iter->index == 0) { - iter->index--; - while (1) - { - iter->cursor--; - scan = &(iter->target->buffer[iter->cursor]); - if (scan->state == CMC_ES_FILLED) - break; - } + iter->start = 1; + return 0; } iter->end = ms_empty(iter->target); - return true; + multiset_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 ms_iter_advance(multiset_iter *iter, size_t steps) +{ + if (iter->end) + return 0; + if (iter->index + 1 == ms_count(iter->target)) + { + iter->end = 1; + return 0; + } + if (steps == 0 || iter->index + steps >= ms_count(iter->target)) + return 0; + for (size_t i = 0; i < steps; i++) + ms_iter_next(iter); + return 1; +} +_Bool ms_iter_rewind(multiset_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++) + ms_iter_prev(iter); + return 1; +} +_Bool ms_iter_go_to(multiset_iter *iter, size_t index) +{ + if (index >= ms_count(iter->target)) + return 0; + if (iter->index > index) + return ms_iter_rewind(iter, iter->index - index); + else if (iter->index < index) + return ms_iter_advance(iter, index - iter->index); + return 1; } size_t ms_iter_value(multiset_iter *iter) { if (ms_empty(iter->target)) - return ms_impl_default_value(); + return (size_t){0}; return iter->target->buffer[iter->cursor].value; } size_t ms_iter_multiplicity(multiset_iter *iter) @@ -538,17 +678,17 @@ size_t ms_iter_multiplicity(multiset_iter *iter) return iter->target->buffer[iter->cursor].multiplicity; } size_t ms_iter_index(multiset_iter *iter) { return iter->index; } -static multiset_entry *ms_impl_insert_and_return(multiset *_set_, size_t element, bool *new_node) +static multiset_entry *ms_impl_insert_and_return(multiset *_set_, size_t element, _Bool *new_node) { - *new_node = false; + *new_node = 0; multiset_entry *entry = ms_impl_get_entry(_set_, element); - if (entry != NULL) + if (entry != ((void *)0)) return entry; - *new_node = true; - if ((double)_set_->capacity * _set_->load <= (double)_set_->count) + *new_node = 1; + if (ms_full(_set_)) { - if (!ms_impl_grow(_set_)) - return NULL; + if (!ms_resize(_set_, ms_capacity(_set_) + 1)) + return ((void *)0); } size_t hash = _set_->hash(element); size_t original_pos = hash % _set_->capacity; @@ -564,7 +704,7 @@ static multiset_entry *ms_impl_insert_and_return(multiset *_set_, size_t element } else { - while (true) + while (1) { pos++; target = &(_set_->buffer[pos % _set_->capacity]); @@ -593,29 +733,6 @@ static multiset_entry *ms_impl_insert_and_return(multiset *_set_, size_t element _set_->count++; return target; } -static bool ms_impl_grow(multiset *_set_) -{ - size_t new_size = ms_impl_calculate_size(_set_->capacity + _set_->capacity / 2); - multiset *_new_set_ = ms_new(new_size, _set_->load, _set_->cmp, _set_->hash); - if (!_new_set_) - return false; - multiset_iter iter; - for (ms_iter_init(&iter, _set_); !ms_iter_end(&iter); ms_iter_next(&iter)) - { - ms_insert_many(_new_set_, ms_iter_value(&iter), ms_iter_multiplicity(&iter)); - } - if (_set_->count != _new_set_->count) - { - ms_free(_new_set_); - return false; - } - multiset_entry *tmp = _set_->buffer; - _set_->buffer = _new_set_->buffer; - _new_set_->buffer = tmp; - _set_->capacity = _new_set_->capacity; - ms_free(_new_set_); - return true; -} static multiset_entry *ms_impl_get_entry(multiset *_set_, size_t element) { size_t hash = _set_->hash(element); @@ -628,7 +745,7 @@ static multiset_entry *ms_impl_get_entry(multiset *_set_, size_t element) pos++; target = &(_set_->buffer[pos % _set_->capacity]); } - return NULL; + return ((void *)0); } static size_t ms_impl_calculate_size(size_t required) { diff --git a/tests/codecov/src/queue.c b/tests/codecov/src/queue.c index 15f183d..ca68d2d 100644 --- a/tests/codecov/src/queue.c +++ b/tests/codecov/src/queue.c @@ -1,6 +1,6 @@ -#include "cmc/queue.h" +#include -//QUEUE_GENERATE(q, queue, , size_t) +//CMC_GENERATE_QUEUE(q, queue, size_t) typedef struct queue_s { @@ -8,7 +8,7 @@ typedef struct queue_s size_t capacity; size_t count; size_t front; - size_t rear; + size_t back; struct queue_iter_s (*it_start)(struct queue_s *); struct queue_iter_s (*it_end)(struct queue_s *); } queue, *queue_ptr; @@ -17,134 +17,204 @@ typedef struct queue_iter_s struct queue_s *target; size_t cursor; size_t index; - bool start; - bool end; + _Bool start; + _Bool end; } queue_iter, *queue_iter_ptr; queue *q_new(size_t capacity); -void q_clear(queue *_queue_); -void q_free(queue *_queue_); -bool q_enqueue(queue *_queue_, size_t element); -bool q_dequeue(queue *_queue_); -bool q_enqueue_if(queue *_queue_, size_t element, bool condition); -bool q_dequeue_if(queue *_queue_, bool condition); +void q_clear(queue *_queue_, void (*deallocator)(size_t)); +void q_free(queue *_queue_, void (*deallocator)(size_t)); +_Bool q_enqueue(queue *_queue_, size_t element); +_Bool q_dequeue(queue *_queue_); size_t q_peek(queue *_queue_); -bool q_contains(queue *_queue_, size_t element, int (*comparator)(size_t, size_t)); -bool q_empty(queue *_queue_); -bool q_full(queue *_queue_); +_Bool q_contains(queue *_queue_, size_t element, int (*comparator)(size_t, size_t)); +_Bool q_empty(queue *_queue_); +_Bool q_full(queue *_queue_); size_t q_count(queue *_queue_); size_t q_capacity(queue *_queue_); +_Bool q_resize(queue *_queue_, size_t capacity); +queue *q_copy_of(queue *_queue_, size_t (*copy_func)(size_t)); +_Bool q_equals(queue *_queue1_, queue *_queue2_, int (*comparator)(size_t, size_t)); +cmc_string q_to_string(queue *_queue_); queue_iter *q_iter_new(queue *target); void q_iter_free(queue_iter *iter); void q_iter_init(queue_iter *iter, queue *target); -bool q_iter_start(queue_iter *iter); -bool q_iter_end(queue_iter *iter); +_Bool q_iter_start(queue_iter *iter); +_Bool q_iter_end(queue_iter *iter); void q_iter_to_start(queue_iter *iter); void q_iter_to_end(queue_iter *iter); -bool q_iter_next(queue_iter *iter); -bool q_iter_prev(queue_iter *iter); +_Bool q_iter_next(queue_iter *iter); +_Bool q_iter_prev(queue_iter *iter); +_Bool q_iter_advance(queue_iter *iter, size_t steps); +_Bool q_iter_rewind(queue_iter *iter, size_t steps); +_Bool q_iter_go_to(queue_iter *iter, size_t index); size_t q_iter_value(queue_iter *iter); size_t *q_iter_rvalue(queue_iter *iter); size_t q_iter_index(queue_iter *iter); -static inline size_t q_impl_default_value(void) -{ - size_t _empty_value_; - memset(&_empty_value_, 0, sizeof(size_t)); - return _empty_value_; -} -static bool q_impl_grow(queue *_queue_); static queue_iter q_impl_it_start(queue *_queue_); static queue_iter q_impl_it_end(queue *_queue_); queue *q_new(size_t capacity) { if (capacity < 1) - return NULL; + return ((void *)0); queue *_queue_ = malloc(sizeof(queue)); if (!_queue_) - return NULL; + return ((void *)0); _queue_->buffer = malloc(sizeof(size_t) * capacity); if (!_queue_->buffer) { free(_queue_); - return NULL; + return ((void *)0); } memset(_queue_->buffer, 0, sizeof(size_t) * capacity); _queue_->capacity = capacity; _queue_->count = 0; _queue_->front = 0; - _queue_->rear = 0; + _queue_->back = 0; _queue_->it_start = q_impl_it_start; _queue_->it_end = q_impl_it_end; return _queue_; } -void q_clear(queue *_queue_) +void q_clear(queue *_queue_, void (*deallocator)(size_t)) { + if (deallocator) + { + for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) + { + deallocator(_queue_->buffer[i]); + i = (i + 1) % _queue_->capacity; + } + } memset(_queue_->buffer, 0, sizeof(size_t) * _queue_->capacity); _queue_->count = 0; _queue_->front = 0; - _queue_->rear = 0; + _queue_->back = 0; } -void q_free(queue *_queue_) +void q_free(queue *_queue_, void (*deallocator)(size_t)) { + if (deallocator) + { + for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) + { + deallocator(_queue_->buffer[i]); + i = (i + 1) % _queue_->capacity; + } + } free(_queue_->buffer); free(_queue_); } -bool q_enqueue(queue *_queue_, size_t element) +_Bool q_enqueue(queue *_queue_, size_t element) { if (q_full(_queue_)) { - if (!q_impl_grow(_queue_)) - return false; + if (!q_resize(_queue_, q_capacity(_queue_) * 2)) + return 0; } - _queue_->buffer[_queue_->rear] = element; - _queue_->rear = (_queue_->rear == _queue_->capacity - 1) ? 0 : _queue_->rear + 1; + _queue_->buffer[_queue_->back] = element; + _queue_->back = (_queue_->back == _queue_->capacity - 1) ? 0 : _queue_->back + 1; _queue_->count++; - return true; + return 1; } -bool q_dequeue(queue *_queue_) +_Bool q_dequeue(queue *_queue_) { if (q_empty(_queue_)) - return false; - _queue_->buffer[_queue_->front] = q_impl_default_value(); + return 0; + _queue_->buffer[_queue_->front] = (size_t){0}; _queue_->front = (_queue_->front == _queue_->capacity - 1) ? 0 : _queue_->front + 1; _queue_->count--; - return true; -} -bool q_enqueue_if(queue *_queue_, size_t element, bool condition) -{ - if (condition) - return q_enqueue(_queue_, element); - return false; -} -bool q_dequeue_if(queue *_queue_, bool condition) -{ - if (condition) - return q_dequeue(_queue_); - return false; + return 1; } size_t q_peek(queue *_queue_) { if (q_empty(_queue_)) - return q_impl_default_value(); + return (size_t){0}; return _queue_->buffer[_queue_->front]; } -bool q_contains(queue *_queue_, size_t element, int (*comparator)(size_t, size_t)) +_Bool q_contains(queue *_queue_, size_t element, int (*comparator)(size_t, size_t)) { - for (size_t i = _queue_->front, j = 0; j < _queue_->count; i = (i + 1) % _queue_->count, j++) + for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) { if (comparator(_queue_->buffer[i], element) == 0) - return true; + return 1; + i = (i + 1) % _queue_->capacity; } - return false; + return 0; } -bool q_empty(queue *_queue_) { return _queue_->count == 0; } -bool q_full(queue *_queue_) { return _queue_->count >= _queue_->capacity; } +_Bool q_empty(queue *_queue_) { return _queue_->count == 0; } +_Bool q_full(queue *_queue_) { return _queue_->count >= _queue_->capacity; } size_t q_count(queue *_queue_) { return _queue_->count; } size_t q_capacity(queue *_queue_) { return _queue_->capacity; } +_Bool q_resize(queue *_queue_, size_t capacity) +{ + if (q_capacity(_queue_) == capacity) + return 1; + if (capacity < q_count(_queue_)) + return 0; + size_t *new_buffer = malloc(sizeof(size_t) * capacity); + if (!new_buffer) + return 0; + for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) + { + new_buffer[j] = _queue_->buffer[i]; + i = (i + 1) % q_capacity(_queue_); + } + free(_queue_->buffer); + _queue_->buffer = new_buffer; + _queue_->capacity = capacity; + _queue_->front = 0; + _queue_->back = _queue_->count; + return 1; +} +queue *q_copy_of(queue *_queue_, size_t (*copy_func)(size_t)) +{ + queue *result = q_new(_queue_->capacity); + if (!result) + return ((void *)0); + if (copy_func) + { + for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) + { + result->buffer[j] = copy_func(_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; + return result; +} +_Bool q_equals(queue *_queue1_, queue *_queue2_, int (*comparator)(size_t, size_t)) +{ + if (q_count(_queue1_) != q_count(_queue2_)) + return 0; + size_t i, j, k; + for (i = _queue1_->front, j = _queue2_->front, k = 0; k < q_count(_queue1_); k++) + { + if (comparator(_queue1_->buffer[i], _queue2_->buffer[j]) != 0) + return 0; + i = (i + 1) % _queue1_->capacity; + j = (j + 1) % _queue2_->capacity; + } + return 1; +} +cmc_string q_to_string(queue *_queue_) +{ + cmc_string str; + queue *q_ = _queue_; + const char *name = "queue"; + snprintf(str.s, cmc_string_len, cmc_string_fmt_queue, name, q_, q_->buffer, q_->capacity, q_->count, q_->front, q_->back); + return str; +} queue_iter *q_iter_new(queue *target) { queue_iter *iter = malloc(sizeof(queue_iter)); if (!iter) - return NULL; + return ((void *)0); q_iter_init(iter, target); return iter; } @@ -154,16 +224,16 @@ void q_iter_init(queue_iter *iter, queue *target) iter->target = target; iter->cursor = target->front; iter->index = 0; - iter->start = true; + iter->start = 1; iter->end = q_empty(target); } -bool q_iter_start(queue_iter *iter) { return q_empty(iter->target) || iter->start; } -bool q_iter_end(queue_iter *iter) { return q_empty(iter->target) || iter->end; } +_Bool q_iter_start(queue_iter *iter) { return q_empty(iter->target) || iter->start; } +_Bool q_iter_end(queue_iter *iter) { return q_empty(iter->target) || iter->end; } void q_iter_to_start(queue_iter *iter) { iter->cursor = iter->target->front; iter->index = 0; - iter->start = true; + iter->start = 1; iter->end = q_empty(iter->target); } void q_iter_to_end(queue_iter *iter) @@ -171,69 +241,101 @@ void q_iter_to_end(queue_iter *iter) if (q_empty(iter->target)) iter->cursor = 0; else - iter->cursor = (iter->target->rear == 0) ? iter->target->capacity - 1 : iter->target->rear - 1; + { + 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 = q_empty(iter->target); - iter->end = true; + iter->end = 1; } -bool q_iter_next(queue_iter *iter) +_Bool q_iter_next(queue_iter *iter) { if (iter->end) - return false; - iter->start = q_empty(iter->target); - if (iter->index == iter->target->count - 1) - iter->end = true; - else + return 0; + if (iter->index + 1 == q_count(iter->target)) { - iter->cursor = (iter->cursor + 1) % (iter->target->capacity); - iter->index++; + iter->end = 1; + return 0; } - return true; + iter->start = q_empty(iter->target); + iter->cursor = (iter->cursor + 1) % (iter->target->capacity); + iter->index++; + return 1; } -bool q_iter_prev(queue_iter *iter) +_Bool q_iter_prev(queue_iter *iter) { if (iter->start) - return false; - iter->end = q_empty(iter->target); + return 0; if (iter->index == 0) - iter->start = true; - else { - iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; - iter->index--; + iter->start = 1; + return 0; } - return true; + 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(queue_iter *iter, size_t steps) +{ + if (iter->end) + return 0; + if (iter->index + 1 == q_count(iter->target)) + { + iter->end = 1; + return 0; + } + if (steps == 0 || iter->index + steps >= q_count(iter->target)) + 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(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 += q_capacity(iter->target); + iter->cursor -= steps; + return 1; +} +_Bool q_iter_go_to(queue_iter *iter, size_t index) +{ + if (index >= q_count(iter->target)) + 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(queue_iter *iter) { if (q_empty(iter->target)) - return q_impl_default_value(); + return (size_t){0}; return iter->target->buffer[iter->cursor]; } size_t *q_iter_rvalue(queue_iter *iter) { if (q_empty(iter->target)) - return NULL; + return ((void *)0); return &(iter->target->buffer[iter->cursor]); } size_t q_iter_index(queue_iter *iter) { return iter->index; } -static bool q_impl_grow(queue *_queue_) -{ - size_t new_capacity = _queue_->capacity * 2; - size_t *new_buffer = malloc(sizeof(size_t) * new_capacity); - if (!new_buffer) - return false; - for (size_t i = _queue_->front, j = 0; j < _queue_->count; i = (i + 1) % _queue_->capacity, j++) - { - new_buffer[j] = _queue_->buffer[i]; - } - free(_queue_->buffer); - _queue_->buffer = new_buffer; - _queue_->capacity = new_capacity; - _queue_->front = 0; - _queue_->rear = _queue_->count; - return true; -} static queue_iter q_impl_it_start(queue *_queue_) { queue_iter iter; diff --git a/tests/codecov/src/sortedlist.c b/tests/codecov/src/sortedlist.c new file mode 100644 index 0000000..f0bb940 --- /dev/null +++ b/tests/codecov/src/sortedlist.c @@ -0,0 +1,431 @@ +#include + +//CMC_GENERATE_SORTEDLIST(sl, sortedlist, size_t) + +typedef struct sortedlist_s +{ + size_t *buffer; + size_t capacity; + size_t count; + _Bool is_sorted; + int (*cmp)(size_t, size_t); + struct sortedlist_iter_s (*it_start)(struct sortedlist_s *); + struct sortedlist_iter_s (*it_end)(struct sortedlist_s *); +} sortedlist, *sortedlist_ptr; +typedef struct sortedlist_iter_s +{ + struct sortedlist_s *target; + size_t cursor; + _Bool start; + _Bool end; +} sortedlist_iter, *sortedlist_iter_ptr; +sortedlist *sl_new(size_t capacity, int (*compare)(size_t, size_t)); +void sl_clear(sortedlist *_list_, void (*deallocator)(size_t)); +void sl_free(sortedlist *_list_, void (*deallocator)(size_t)); +_Bool sl_insert(sortedlist *_list_, size_t element); +_Bool sl_remove(sortedlist *_list_, size_t index); +_Bool sl_max(sortedlist *_list_, size_t *result); +_Bool sl_min(sortedlist *_list_, size_t *result); +size_t sl_get(sortedlist *_list_, size_t index); +size_t sl_indexof(sortedlist *_list_, size_t element, _Bool from_start); +_Bool sl_contains(sortedlist *_list_, size_t element); +_Bool sl_empty(sortedlist *_list_); +_Bool sl_full(sortedlist *_list_); +size_t sl_count(sortedlist *_list_); +size_t sl_capacity(sortedlist *_list_); +_Bool sl_resize(sortedlist *_list_, size_t capacity); +void sl_sort(sortedlist *_list_); +sortedlist *sl_copy_of(sortedlist *_list_, size_t (*copy_func)(size_t)); +_Bool sl_equals(sortedlist *_list1_, sortedlist *_list2_); +cmc_string sl_to_string(sortedlist *_list_); +sortedlist_iter *sl_iter_new(sortedlist *target); +void sl_iter_free(sortedlist_iter *iter); +void sl_iter_init(sortedlist_iter *iter, sortedlist *target); +_Bool sl_iter_start(sortedlist_iter *iter); +_Bool sl_iter_end(sortedlist_iter *iter); +void sl_iter_to_start(sortedlist_iter *iter); +void sl_iter_to_end(sortedlist_iter *iter); +_Bool sl_iter_next(sortedlist_iter *iter); +_Bool sl_iter_prev(sortedlist_iter *iter); +_Bool sl_iter_advance(sortedlist_iter *iter, size_t steps); +_Bool sl_iter_rewind(sortedlist_iter *iter, size_t steps); +_Bool sl_iter_go_to(sortedlist_iter *iter, size_t index); +size_t sl_iter_value(sortedlist_iter *iter); +size_t sl_iter_index(sortedlist_iter *iter); +static size_t sl_impl_binary_search_first(sortedlist *_list_, size_t value); +static size_t sl_impl_binary_search_last(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); +static sortedlist_iter sl_impl_it_start(sortedlist *_list_); +static sortedlist_iter sl_impl_it_end(sortedlist *_list_); +sortedlist *sl_new(size_t capacity, int (*compare)(size_t, size_t)) +{ + if (capacity < 1) + return ((void *)0); + sortedlist *_list_ = malloc(sizeof(sortedlist)); + if (!_list_) + return ((void *)0); + _list_->buffer = calloc(capacity, sizeof(size_t)); + if (!_list_->buffer) + { + free(_list_); + return ((void *)0); + } + _list_->capacity = capacity; + _list_->count = 0; + _list_->cmp = compare; + _list_->is_sorted = 0; + _list_->it_start = sl_impl_it_start; + _list_->it_end = sl_impl_it_end; + return _list_; +} +void sl_clear(sortedlist *_list_, void (*deallocator)(size_t)) +{ + if (deallocator) + { + for (size_t i = 0; i < _list_->count; i++) + deallocator(_list_->buffer[i]); + } + memset(_list_->buffer, 0, sizeof(size_t) * _list_->capacity); + _list_->count = 0; +} +void sl_free(sortedlist *_list_, void (*deallocator)(size_t)) +{ + if (deallocator) + { + for (size_t i = 0; i < _list_->count; i++) + deallocator(_list_->buffer[i]); + } + free(_list_->buffer); + free(_list_); +} +_Bool sl_insert(sortedlist *_list_, size_t element) +{ + if (sl_full(_list_)) + { + if (!sl_resize(_list_, sl_capacity(_list_) * 2)) + return 0; + } + _list_->buffer[_list_->count++] = element; + _list_->is_sorted = 0; + return 1; +} +_Bool sl_remove(sortedlist *_list_, size_t index) +{ + if (index >= _list_->count) + return 0; + memmove(_list_->buffer + index, _list_->buffer + index + 1, (_list_->count - index) * sizeof(size_t)); + _list_->buffer[--_list_->count] = (size_t){0}; + return 1; +} +_Bool sl_min(sortedlist *_list_, size_t *result) +{ + if (sl_empty(_list_)) + return 0; + sl_sort(_list_); + *result = _list_->buffer[0]; + return 1; +} +_Bool sl_max(sortedlist *_list_, size_t *result) +{ + if (sl_empty(_list_)) + return 0; + sl_sort(_list_); + *result = _list_->buffer[_list_->count - 1]; + return 1; +} +size_t sl_get(sortedlist *_list_, size_t index) +{ + if (index >= _list_->count) + return (size_t){0}; + sl_sort(_list_); + return _list_->buffer[index]; +} +size_t sl_indexof(sortedlist *_list_, size_t element, _Bool from_start) +{ + sl_sort(_list_); + if (from_start) + { + return sl_impl_binary_search_first(_list_, element); + } + return sl_impl_binary_search_last(_list_, element); +} +_Bool sl_contains(sortedlist *_list_, size_t element) +{ + if (sl_empty(_list_)) + return 0; + sl_sort(_list_); + return sl_impl_binary_search_first(_list_, element) < sl_count(_list_); +} +_Bool sl_empty(sortedlist *_list_) { return _list_->count == 0; } +_Bool sl_full(sortedlist *_list_) { return _list_->count >= _list_->capacity; } +size_t sl_count(sortedlist *_list_) { return _list_->count; } +size_t sl_capacity(sortedlist *_list_) { return _list_->capacity; } +_Bool sl_resize(sortedlist *_list_, size_t capacity) +{ + if (sl_capacity(_list_) == capacity) + return 1; + if (capacity < sl_count(_list_)) + return 0; + size_t *new_buffer = realloc(_list_->buffer, sizeof(size_t) * capacity); + if (!new_buffer) + return 0; + _list_->buffer = new_buffer; + _list_->capacity = capacity; + return 1; +} +void sl_sort(sortedlist *_list_) +{ + if (!_list_->is_sorted && _list_->count > 1) + { + sl_impl_sort_quicksort(_list_->buffer, _list_->cmp, 0, _list_->count - 1); + _list_->is_sorted = 1; + } +} +sortedlist *sl_copy_of(sortedlist *_list_, size_t (*copy_func)(size_t)) +{ + sortedlist *result = sl_new(_list_->capacity, _list_->cmp); + if (!result) + return ((void *)0); + if (copy_func) + { + for (size_t i = 0; i < _list_->count; i++) + result->buffer[i] = copy_func(_list_->buffer[i]); + } + else + memcpy(result->buffer, _list_->buffer, sizeof(size_t) * _list_->count); + result->count = _list_->count; + return result; +} +_Bool sl_equals(sortedlist *_list1_, sortedlist *_list2_) +{ + if (sl_count(_list1_) != sl_count(_list2_)) + return 0; + for (size_t i = 0; i < sl_count(_list1_); i++) + { + if (_list1_->cmp(_list1_->buffer[i], _list2_->buffer[i]) != 0) + return 0; + } + return 0; +} +cmc_string sl_to_string(sortedlist *_list_) +{ + cmc_string str; + sortedlist *l_ = _list_; + const char *name = "sortedlist"; + snprintf(str.s, cmc_string_len, cmc_string_fmt_sortedlist, name, l_, l_->buffer, l_->capacity, l_->count, l_->is_sorted ? "true" : "false", l_->cmp); + return str; +} +sortedlist_iter *sl_iter_new(sortedlist *target) +{ + sortedlist_iter *iter = malloc(sizeof(sortedlist_iter)); + if (!iter) + return ((void *)0); + sl_iter_init(iter, target); + return iter; +} +void sl_iter_free(sortedlist_iter *iter) { free(iter); } +void sl_iter_init(sortedlist_iter *iter, sortedlist *target) +{ + sl_sort(target); + iter->target = target; + iter->cursor = 0; + iter->start = 1; + iter->end = sl_empty(target); +} +_Bool sl_iter_start(sortedlist_iter *iter) { return sl_empty(iter->target) || iter->start; } +_Bool sl_iter_end(sortedlist_iter *iter) { return sl_empty(iter->target) || iter->end; } +void sl_iter_to_start(sortedlist_iter *iter) +{ + if (!sl_empty(iter->target)) + { + iter->cursor = 0; + iter->start = 1; + iter->end = sl_empty(iter->target); + } +} +void sl_iter_to_end(sortedlist_iter *iter) +{ + if (!sl_empty(iter->target)) + { + iter->start = sl_empty(iter->target); + iter->cursor = sl_empty(iter->target) ? 0 : iter->target->count - 1; + iter->end = 1; + } +} +_Bool sl_iter_next(sortedlist_iter *iter) +{ + if (iter->end) + return 0; + if (iter->cursor + 1 == sl_count(iter->target)) + { + iter->end = 1; + return 0; + } + iter->start = sl_empty(iter->target); + iter->cursor++; + return 1; +} +_Bool sl_iter_prev(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(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 >= sl_count(iter->target)) + return 0; + iter->start = sl_empty(iter->target); + iter->cursor += steps; + return 1; +} +_Bool sl_iter_rewind(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(sortedlist_iter *iter, size_t index) +{ + if (index >= sl_count(iter->target)) + 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(sortedlist_iter *iter) +{ + if (sl_empty(iter->target)) + return (size_t){0}; + return iter->target->buffer[iter->cursor]; +} +size_t sl_iter_index(sortedlist_iter *iter) { return iter->cursor; } +static size_t sl_impl_binary_search_first(sortedlist *_list_, size_t value) +{ + if (sl_empty(_list_)) + return 1; + size_t L = 0; + size_t R = sl_count(_list_); + while (L < R) + { + size_t M = L + (R - L) / 2; + if (_list_->cmp(_list_->buffer[M], value) < 0) + L = M + 1; + else + R = M; + } + if (_list_->cmp(_list_->buffer[L], value) == 0) + return L; + return sl_count(_list_); +} +static size_t sl_impl_binary_search_last(sortedlist *_list_, size_t value) +{ + if (sl_empty(_list_)) + return 1; + size_t L = 0; + size_t R = sl_count(_list_); + while (L < R) + { + size_t M = L + (R - L) / 2; + if (_list_->cmp(_list_->buffer[M], value) > 0) + R = M; + else + L = M + 1; + } + if (_list_->cmp(_list_->buffer[L - 1], value) == 0) + return L - 1; + return sl_count(_list_); +} +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_; + } +} +static sortedlist_iter sl_impl_it_start(sortedlist *_list_) +{ + sortedlist_iter iter; + sl_iter_init(&iter, _list_); + sl_iter_to_start(&iter); + return iter; +} +static sortedlist_iter sl_impl_it_end(sortedlist *_list_) +{ + sortedlist_iter iter; + sl_iter_init(&iter, _list_); + sl_iter_to_end(&iter); + return iter; +} diff --git a/tests/codecov/src/stack.c b/tests/codecov/src/stack.c index 72713e0..3ffc109 100644 --- a/tests/codecov/src/stack.c +++ b/tests/codecov/src/stack.c @@ -1,6 +1,6 @@ -#include "cmc/stack.h" +#include -//STACK_GENERATE(s, stack, , size_t) +//CMC_GENERATE_STACK(s, stack, size_t) typedef struct stack_s { @@ -14,55 +14,53 @@ typedef struct stack_iter_s { struct stack_s *target; size_t cursor; - bool start; - bool end; + _Bool start; + _Bool end; } stack_iter, *stack_iter_ptr; stack *s_new(size_t capacity); -void s_clear(stack *_stack_); -void s_free(stack *_stack_); -bool s_push(stack *_stack_, size_t element); -bool s_pop(stack *_stack_); -bool s_push_if(stack *_stack_, size_t element, bool condition); -bool s_pop_if(stack *_stack_, bool condition); +void s_clear(stack *_stack_, void (*deallocator)(size_t)); +void s_free(stack *_stack_, void (*deallocator)(size_t)); +_Bool s_push(stack *_stack_, size_t element); +_Bool s_pop(stack *_stack_); size_t s_top(stack *_stack_); -bool s_contains(stack *_stack_, size_t element, int (*comparator)(size_t, size_t)); -bool s_empty(stack *_stack_); -bool s_full(stack *_stack_); +_Bool s_contains(stack *_stack_, size_t element, int (*comparator)(size_t, size_t)); +_Bool s_empty(stack *_stack_); +_Bool s_full(stack *_stack_); size_t s_count(stack *_stack_); size_t s_capacity(stack *_stack_); +_Bool s_resize(stack *_stack_, size_t capacity); +stack *s_copy_of(stack *_stack_, size_t (*copy_func)(size_t)); +_Bool s_equals(stack *_stack1_, stack *_stack2_, int (*comparator)(size_t, size_t)); +cmc_string s_to_string(stack *_stack_); stack_iter *s_iter_new(stack *target); void s_iter_free(stack_iter *iter); void s_iter_init(stack_iter *iter, stack *target); -bool s_iter_start(stack_iter *iter); -bool s_iter_end(stack_iter *iter); +_Bool s_iter_start(stack_iter *iter); +_Bool s_iter_end(stack_iter *iter); void s_iter_to_start(stack_iter *iter); void s_iter_to_end(stack_iter *iter); -bool s_iter_next(stack_iter *iter); -bool s_iter_prev(stack_iter *iter); +_Bool s_iter_next(stack_iter *iter); +_Bool s_iter_prev(stack_iter *iter); +_Bool s_iter_advance(stack_iter *iter, size_t steps); +_Bool s_iter_rewind(stack_iter *iter, size_t steps); +_Bool s_iter_go_to(stack_iter *iter, size_t index); size_t s_iter_value(stack_iter *iter); size_t *s_iter_rvalue(stack_iter *iter); size_t s_iter_index(stack_iter *iter); -static inline size_t s_impl_default_value(void) -{ - size_t _empty_value_; - memset(&_empty_value_, 0, sizeof(size_t)); - return _empty_value_; -} -static bool s_impl_grow(stack *_stack_); static stack_iter s_impl_it_start(stack *_stack_); static stack_iter s_impl_it_end(stack *_stack_); stack *s_new(size_t capacity) { if (capacity < 1) - return NULL; + return ((void *)0); stack *_stack_ = malloc(sizeof(stack)); if (!_stack_) - return NULL; + return ((void *)0); _stack_->buffer = malloc(sizeof(size_t) * capacity); if (!_stack_->buffer) { free(_stack_); - return NULL; + return ((void *)0); } memset(_stack_->buffer, 0, sizeof(size_t) * capacity); _stack_->capacity = capacity; @@ -71,69 +69,114 @@ stack *s_new(size_t capacity) _stack_->it_end = s_impl_it_end; return _stack_; } -void s_clear(stack *_stack_) +void s_clear(stack *_stack_, void (*deallocator)(size_t)) { + if (deallocator) + { + for (size_t i = 0; i < _stack_->count; i++) + deallocator(_stack_->buffer[i]); + } memset(_stack_->buffer, 0, sizeof(size_t) * _stack_->capacity); _stack_->count = 0; } -void s_free(stack *_stack_) +void s_free(stack *_stack_, void (*deallocator)(size_t)) { free(_stack_->buffer); + if (deallocator) + { + for (size_t i = 0; i < _stack_->count; i++) + deallocator(_stack_->buffer[i]); + } free(_stack_); } -bool s_push(stack *_stack_, size_t element) +_Bool s_push(stack *_stack_, size_t element) { if (s_full(_stack_)) { - if (!s_impl_grow(_stack_)) - return false; + if (!s_resize(_stack_, s_capacity(_stack_) * 2)) + return 0; } _stack_->buffer[_stack_->count++] = element; - return true; + return 1; } -bool s_pop(stack *_stack_) +_Bool s_pop(stack *_stack_) { if (s_empty(_stack_)) - return false; - _stack_->buffer[--_stack_->count] = s_impl_default_value(); - return true; -} -bool s_push_if(stack *_stack_, size_t element, bool condition) -{ - if (condition) - return s_push(_stack_, element); - return false; -} -bool s_pop_if(stack *_stack_, bool condition) -{ - if (condition) - return s_pop(_stack_); - return false; + return 0; + _stack_->buffer[--_stack_->count] = (size_t){0}; + return 1; } size_t s_top(stack *_stack_) { if (s_empty(_stack_)) - return s_impl_default_value(); + return (size_t){0}; return _stack_->buffer[_stack_->count - 1]; } -bool s_contains(stack *_stack_, size_t element, int (*comparator)(size_t, size_t)) +_Bool s_contains(stack *_stack_, size_t element, int (*comparator)(size_t, size_t)) { for (size_t i = 0; i < _stack_->count; i++) { if (comparator(_stack_->buffer[i], element) == 0) - return true; + return 1; } - return false; + return 0; } -bool s_empty(stack *_stack_) { return _stack_->count == 0; } -bool s_full(stack *_stack_) { return _stack_->count >= _stack_->capacity; } +_Bool s_empty(stack *_stack_) { return _stack_->count == 0; } +_Bool s_full(stack *_stack_) { return _stack_->count >= _stack_->capacity; } size_t s_count(stack *_stack_) { return _stack_->count; } size_t s_capacity(stack *_stack_) { return _stack_->capacity; } +_Bool s_resize(stack *_stack_, size_t capacity) +{ + if (s_capacity(_stack_) == capacity) + return 1; + if (capacity < s_count(_stack_)) + return 0; + size_t *new_buffer = realloc(_stack_->buffer, sizeof(size_t) * capacity); + if (!new_buffer) + return 0; + _stack_->buffer = new_buffer; + _stack_->capacity = capacity; + return 1; +} +stack *s_copy_of(stack *_stack_, size_t (*copy_func)(size_t)) +{ + stack *result = s_new(_stack_->capacity); + if (!result) + return ((void *)0); + if (copy_func) + { + for (size_t i = 0; i < _stack_->count; i++) + result->buffer[i] = copy_func(_stack_->buffer[i]); + } + else + memcpy(result->buffer, _stack_->buffer, sizeof(size_t) * _stack_->count); + result->count = _stack_->count; + return result; +} +_Bool s_equals(stack *_stack1_, stack *_stack2_, int (*comparator)(size_t, size_t)) +{ + if (s_count(_stack1_) != s_count(_stack2_)) + return 0; + for (size_t i = 0; i < s_count(_stack1_); i++) + { + if (comparator(_stack1_->buffer[i], _stack2_->buffer[i]) != 0) + return 0; + } + return 1; +} +cmc_string s_to_string(stack *_stack_) +{ + cmc_string str; + stack *s_ = _stack_; + const char *name = "stack"; + snprintf(str.s, cmc_string_len, cmc_string_fmt_stack, name, s_, s_->buffer, s_->capacity, s_->count); + return str; +} stack_iter *s_iter_new(stack *target) { stack_iter *iter = malloc(sizeof(stack_iter)); if (!iter) - return NULL; + return ((void *)0); s_iter_init(iter, target); return iter; } @@ -141,65 +184,106 @@ void s_iter_free(stack_iter *iter) { free(iter); } void s_iter_init(stack_iter *iter, stack *target) { iter->target = target; - if (s_empty(target)) - iter->cursor = 0; - else - iter->cursor = iter->target->count - 1; - iter->start = true; + iter->cursor = s_empty(target) ? 0 : iter->target->count - 1; + iter->start = 1; iter->end = s_empty(target); } -bool s_iter_start(stack_iter *iter) { return s_empty(iter->target) || iter->start; } -bool s_iter_end(stack_iter *iter) { return s_empty(iter->target) || iter->end; } +_Bool s_iter_start(stack_iter *iter) { return s_empty(iter->target) || iter->start; } +_Bool s_iter_end(stack_iter *iter) { return s_empty(iter->target) || iter->end; } void s_iter_to_start(stack_iter *iter) { - iter->cursor = iter->target->count - 1; - iter->start = true; - iter->end = s_empty(iter->target); + if (!s_empty(iter->target)) + { + iter->cursor = iter->target->count - 1; + iter->start = 1; + iter->end = s_empty(iter->target); + } } void s_iter_to_end(stack_iter *iter) { - iter->cursor = 0; - iter->start = s_empty(iter->target); - iter->end = true; + if (!s_empty(iter->target)) + { + iter->cursor = 0; + iter->start = s_empty(iter->target); + iter->end = 1; + } } -bool s_iter_next(stack_iter *iter) +_Bool s_iter_next(stack_iter *iter) { if (iter->end) - return false; - iter->start = s_empty(iter->target); + return 0; if (iter->cursor == 0) { - iter->end = true; - return false; + iter->end = 1; + return 0; } - else - iter->cursor--; - return true; + iter->start = s_empty(iter->target); + iter->cursor--; + return 1; } -bool s_iter_prev(stack_iter *iter) +_Bool s_iter_prev(stack_iter *iter) { if (iter->start) - return false; - iter->end = s_empty(iter->target); - if (iter->cursor == iter->target->count - 1) + return 0; + if (iter->cursor + 1 == s_count(iter->target)) { - iter->start = true; - return false; + iter->start = 1; + return 0; } - else - iter->cursor++; - return true; + iter->end = s_empty(iter->target); + iter->cursor++; + return 1; +} +_Bool s_iter_advance(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(stack_iter *iter, size_t steps) +{ + if (iter->start) + return 0; + if (iter->cursor + 1 == s_count(iter->target)) + { + iter->start = 1; + return 0; + } + if (steps == 0 || iter->cursor + steps >= s_count(iter->target)) + return 0; + iter->end = s_empty(iter->target); + iter->cursor += steps; + return 1; +} +_Bool s_iter_go_to(stack_iter *iter, size_t index) +{ + if (index >= s_count(iter->target)) + return 0; + if (iter->cursor > index) + return s_iter_rewind(iter, iter->cursor - index); + else if (iter->cursor < index) + return s_iter_advance(iter, index - iter->cursor); + return 1; } size_t s_iter_value(stack_iter *iter) { if (s_empty(iter->target)) - return s_impl_default_value(); + return (size_t){0}; return iter->target->buffer[iter->cursor]; } size_t *s_iter_rvalue(stack_iter *iter) { if (s_empty(iter->target)) - return NULL; + return ((void *)0); return &(iter->target->buffer[iter->cursor]); } size_t s_iter_index(stack_iter *iter) @@ -208,16 +292,6 @@ size_t s_iter_index(stack_iter *iter) return 0; return iter->target->count - 1 - iter->cursor; } -static bool s_impl_grow(stack *_stack_) -{ - size_t new_capacity = _stack_->capacity * 2; - size_t *new_buffer = realloc(_stack_->buffer, sizeof(size_t) * new_capacity); - if (!new_buffer) - return false; - _stack_->buffer = new_buffer; - _stack_->capacity = new_capacity; - return true; -} static stack_iter s_impl_it_start(stack *_stack_) { stack_iter iter; diff --git a/tests/codecov/src/treemap.c b/tests/codecov/src/treemap.c index dd2dea5..3e44c68 100644 --- a/tests/codecov/src/treemap.c +++ b/tests/codecov/src/treemap.c @@ -1,6 +1,6 @@ -#include "cmc/treemap.h" +#include -//TREEMAP_GENERATE(tm, treemap, , size_t, size_t) +//CMC_GENERATE_TREEMAP(tm, treemap, size_t, size_t) typedef struct treemap_s { @@ -26,48 +26,41 @@ typedef struct treemap_iter_s struct treemap_node_s *first; struct treemap_node_s *last; size_t index; - bool start; - bool end; + _Bool start; + _Bool end; } treemap_iter, *treemap_iter_ptr; treemap *tm_new(int (*compare)(size_t, size_t)); -void tm_clear(treemap *_map_); -void tm_free(treemap *_map_); -bool tm_insert(treemap *_map_, size_t key, size_t value); -bool tm_remove(treemap *_map_, size_t key, size_t *value); -bool tm_insert_if(treemap *_map_, size_t key, size_t value, bool condition); -bool tm_remove_if(treemap *_map_, size_t key, size_t *value, bool condition); -bool tm_max(treemap *_map_, size_t *key, size_t *value); -bool tm_min(treemap *_map_, size_t *key, size_t *value); +void tm_clear(treemap *_map_, void (*deallocator)(size_t, size_t)); +void tm_free(treemap *_map_, void (*deallocator)(size_t, size_t)); +_Bool tm_insert(treemap *_map_, size_t key, size_t value); +_Bool tm_update(treemap *_map_, size_t key, size_t new_value, size_t *old_value); +_Bool tm_remove(treemap *_map_, size_t key, size_t *out_value); +_Bool tm_max(treemap *_map_, size_t *key, size_t *value); +_Bool tm_min(treemap *_map_, size_t *key, size_t *value); size_t tm_get(treemap *_map_, size_t key); size_t *tm_get_ref(treemap *_map_, size_t key); -bool tm_contains(treemap *_map_, size_t key); -bool tm_empty(treemap *_map_); +_Bool tm_contains(treemap *_map_, size_t key); +_Bool tm_empty(treemap *_map_); size_t tm_count(treemap *_map_); +treemap *tm_copy_of(treemap *_map_, size_t (*key_copy_func)(size_t), size_t (*value_copy_func)(size_t)); +_Bool tm_equals(treemap *_map1_, treemap *_map2_, int (*value_comparator)(size_t, size_t)); +cmc_string tm_to_string(treemap *_map_); treemap_iter *tm_iter_new(treemap *target); void tm_iter_free(treemap_iter *iter); void tm_iter_init(treemap_iter *iter, treemap *target); -bool tm_iter_start(treemap_iter *iter); -bool tm_iter_end(treemap_iter *iter); +_Bool tm_iter_start(treemap_iter *iter); +_Bool tm_iter_end(treemap_iter *iter); void tm_iter_to_start(treemap_iter *iter); void tm_iter_to_end(treemap_iter *iter); -bool tm_iter_next(treemap_iter *iter); -bool tm_iter_prev(treemap_iter *iter); +_Bool tm_iter_next(treemap_iter *iter); +_Bool tm_iter_prev(treemap_iter *iter); +_Bool tm_iter_advance(treemap_iter *iter, size_t steps); +_Bool tm_iter_rewind(treemap_iter *iter, size_t steps); +_Bool tm_iter_go_to(treemap_iter *iter, size_t index); size_t tm_iter_key(treemap_iter *iter); size_t tm_iter_value(treemap_iter *iter); size_t *tm_iter_rvalue(treemap_iter *iter); size_t tm_iter_index(treemap_iter *iter); -static inline size_t tm_impl_default_key(void) -{ - size_t _empty_key_; - memset(&_empty_key_, 0, sizeof(size_t)); - return _empty_key_; -} -static inline size_t tm_impl_default_value(void) -{ - size_t _empty_value_; - memset(&_empty_value_, 0, sizeof(size_t)); - return _empty_value_; -} static treemap_node *tm_impl_new_node(size_t key, size_t value); static treemap_node *tm_impl_get_node(treemap *_map_, size_t key); static unsigned char tm_impl_h(treemap_node *node); @@ -81,49 +74,53 @@ treemap *tm_new(int (*compare)(size_t, size_t)) { treemap *_map_ = malloc(sizeof(treemap)); if (!_map_) - return NULL; + return ((void *)0); _map_->count = 0; - _map_->root = NULL; + _map_->root = ((void *)0); _map_->cmp = compare; _map_->it_start = tm_impl_it_start; _map_->it_end = tm_impl_it_end; return _map_; } -void tm_clear(treemap *_map_) +void tm_clear(treemap *_map_, void (*deallocator)(size_t, size_t)) { treemap_node *scan = _map_->root; - treemap_node *up = NULL; - while (scan != NULL) + treemap_node *up = ((void *)0); + while (scan != ((void *)0)) { - if (scan->left != NULL) + if (scan->left != ((void *)0)) { treemap_node *left = scan->left; scan->left = up; up = scan; scan = left; } - else if (scan->right != NULL) + else if (scan->right != ((void *)0)) { treemap_node *right = scan->right; scan->left = up; - scan->right = NULL; + scan->right = ((void *)0); up = scan; scan = right; } else { - if (up == NULL) + if (up == ((void *)0)) { + if (deallocator) + deallocator(scan->key, scan->value); free(scan); - scan = NULL; + scan = ((void *)0); } - while (up != NULL) + while (up != ((void *)0)) { + if (deallocator) + deallocator(scan->key, scan->value); free(scan); - if (up->right != NULL) + if (up->right != ((void *)0)) { scan = up->right; - up->right = NULL; + up->right = ((void *)0); break; } else @@ -135,26 +132,26 @@ void tm_clear(treemap *_map_) } } _map_->count = 0; - _map_->root = NULL; + _map_->root = ((void *)0); } -void tm_free(treemap *_map_) +void tm_free(treemap *_map_, void (*deallocator)(size_t, size_t)) { - tm_clear(_map_); + tm_clear(_map_, deallocator); free(_map_); } -bool tm_insert(treemap *_map_, size_t key, size_t value) +_Bool tm_insert(treemap *_map_, size_t key, size_t value) { if (tm_empty(_map_)) { _map_->root = tm_impl_new_node(key, value); if (!_map_->root) - return false; + return 0; } else { treemap_node *scan = _map_->root; treemap_node *parent = scan; - while (scan != NULL) + while (scan != ((void *)0)) { parent = scan; if (_map_->cmp(scan->key, key) > 0) @@ -162,14 +159,14 @@ bool tm_insert(treemap *_map_, size_t key, size_t value) else if (_map_->cmp(scan->key, key) < 0) scan = scan->right; else - return false; + return 0; } treemap_node *node; if (_map_->cmp(parent->key, key) > 0) { parent->left = tm_impl_new_node(key, value); if (!parent->left) - return false; + return 0; parent->left->parent = parent; node = parent->left; } @@ -177,43 +174,54 @@ bool tm_insert(treemap *_map_, size_t key, size_t value) { parent->right = tm_impl_new_node(key, value); if (!parent->right) - return false; + return 0; parent->right->parent = parent; node = parent->right; } tm_impl_rebalance(_map_, node); } _map_->count++; - return true; + return 1; } -bool tm_remove(treemap *_map_, size_t key, size_t *value) +_Bool tm_update(treemap *_map_, size_t key, size_t new_value, size_t *old_value) { treemap_node *node = tm_impl_get_node(_map_, key); if (!node) - return false; - *value = node->value; - treemap_node *temp = NULL, *unbalanced = NULL; - bool is_root = node->parent == NULL; - if (node->left == NULL && node->right == NULL) + return 0; + if (old_value) + *old_value = node->value; + node->value = new_value; + return 1; +} +_Bool tm_remove(treemap *_map_, size_t key, size_t *out_value) +{ + treemap_node *node = tm_impl_get_node(_map_, key); + if (!node) + return 0; + if (out_value) + *out_value = node->value; + 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 = NULL; + _map_->root = ((void *)0); else { unbalanced = node->parent; if (node->parent->right == node) - node->parent->right = NULL; + node->parent->right = ((void *)0); else - node->parent->left = NULL; + node->parent->left = ((void *)0); } free(node); } - else if (node->left == NULL) + else if (node->left == ((void *)0)) { if (is_root) { _map_->root = node->right; - _map_->root->parent = NULL; + _map_->root->parent = ((void *)0); } else { @@ -226,12 +234,12 @@ bool tm_remove(treemap *_map_, size_t key, size_t *value) } free(node); } - else if (node->right == NULL) + else if (node->right == ((void *)0)) { if (is_root) { _map_->root = node->left; - _map_->root->parent = NULL; + _map_->root->parent = ((void *)0); } else { @@ -247,19 +255,19 @@ bool tm_remove(treemap *_map_, size_t key, size_t *value) else { temp = node->right; - while (temp->left != NULL) + 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 == NULL && temp->right == NULL) + if (temp->left == ((void *)0) && temp->right == ((void *)0)) { if (temp->parent->right == temp) - temp->parent->right = NULL; + temp->parent->right = ((void *)0); else - temp->parent->left = NULL; + temp->parent->left = ((void *)0); } - else if (temp->left == NULL) + else if (temp->left == ((void *)0)) { temp->right->parent = temp->parent; if (temp->parent->right == temp) @@ -267,7 +275,7 @@ bool tm_remove(treemap *_map_, size_t key, size_t *value) else temp->parent->left = temp->right; } - else if (temp->right == NULL) + else if (temp->right == ((void *)0)) { temp->left->parent = temp->parent; if (temp->parent->right == temp) @@ -279,190 +287,278 @@ bool tm_remove(treemap *_map_, size_t key, size_t *value) node->key = temp_key; node->value = temp_val; } - if (unbalanced != NULL) + if (unbalanced != ((void *)0)) tm_impl_rebalance(_map_, unbalanced); _map_->count--; if (_map_->count == 0) - _map_->root = NULL; - return true; + _map_->root = ((void *)0); + return 1; } -bool tm_insert_if(treemap *_map_, size_t key, size_t value, bool condition) -{ - if (condition) - return tm_insert(_map_, key, value); - return false; -} -bool tm_remove_if(treemap *_map_, size_t key, size_t *value, bool condition) -{ - if (condition) - return tm_remove(_map_, key, value); - return false; -} -bool tm_max(treemap *_map_, size_t *key, size_t *value) +_Bool tm_max(treemap *_map_, size_t *key, size_t *value) { if (tm_empty(_map_)) - return false; + return 0; treemap_node *scan = _map_->root; - while (scan->right != NULL) + while (scan->right != ((void *)0)) scan = scan->right; *key = scan->key; *value = scan->value; - return true; + return 1; } -bool tm_min(treemap *_map_, size_t *key, size_t *value) +_Bool tm_min(treemap *_map_, size_t *key, size_t *value) { if (tm_empty(_map_)) - return false; + return 0; treemap_node *scan = _map_->root; - while (scan->left != NULL) + while (scan->left != ((void *)0)) scan = scan->left; *key = scan->key; *value = scan->value; - return true; + return 1; } size_t tm_get(treemap *_map_, size_t key) { treemap_node *node = tm_impl_get_node(_map_, key); if (!node) - return tm_impl_default_value(); + return (size_t){0}; return node->value; } size_t *tm_get_ref(treemap *_map_, size_t key) { treemap_node *node = tm_impl_get_node(_map_, key); if (!node) - return NULL; + return ((void *)0); return &(node->value); } -bool tm_contains(treemap *_map_, size_t key) +_Bool tm_contains(treemap *_map_, size_t key) { treemap_node *scan = _map_->root; - while (scan != NULL) + while (scan != ((void *)0)) { if (_map_->cmp(scan->key, key) > 0) scan = scan->left; else if (_map_->cmp(scan->key, key) < 0) scan = scan->right; else - return true; + return 1; } - return false; + return 0; } -bool tm_empty(treemap *_map_) { return _map_->count == 0; } +_Bool tm_empty(treemap *_map_) { return _map_->count == 0; } size_t tm_count(treemap *_map_) { return _map_->count; } +treemap *tm_copy_of(treemap *_map_, size_t (*key_copy_func)(size_t), size_t (*value_copy_func)(size_t)) +{ + treemap *result = tm_new(_map_->cmp); + if (!result) + return ((void *)0); + treemap_iter iter; + tm_iter_init(&iter, _map_); + if (!tm_empty(_map_)) + { + for (tm_iter_to_start(&iter); !tm_iter_end(&iter); tm_iter_next(&iter)) + { + size_t key = tm_iter_key(&iter); + size_t value = tm_iter_value(&iter); + if (key_copy_func) + key = key_copy_func(key); + if (value_copy_func) + value = value_copy_func(value); + tm_insert(result, key, value); + } + } + return result; +} +_Bool tm_equals(treemap *_map1_, treemap *_map2_, int (*value_comparator)(size_t, size_t)) +{ + if (tm_count(_map1_) != tm_count(_map2_)) + return 0; + treemap_iter iter; + tm_iter_init(&iter, _map1_); + for (tm_iter_to_start(&iter); !tm_iter_end(&iter); tm_iter_next(&iter)) + { + treemap_node *node = tm_impl_get_node(_map2_, tm_iter_key(&iter)); + if (node == ((void *)0)) + return 0; + if (value_comparator) + { + if (value_comparator(node->value, tm_iter_value(&iter)) != 0) + return 0; + } + } + return 1; +} +cmc_string tm_to_string(treemap *_map_) +{ + cmc_string str; + treemap *m_ = _map_; + const char *name = "treemap"; + snprintf(str.s, cmc_string_len, cmc_string_fmt_treemap, name, m_, m_->root, m_->count, m_->cmp); + return str; +} treemap_iter *tm_iter_new(treemap *target) { treemap_iter *iter = malloc(sizeof(treemap_iter)); if (!iter) - return NULL; + return ((void *)0); tm_iter_init(iter, target); return iter; } void tm_iter_free(treemap_iter *iter) { free(iter); } void tm_iter_init(treemap_iter *iter, treemap *target) { + memset(iter, 0, sizeof(treemap_iter)); iter->target = target; - iter->index = 0; - iter->start = true; + iter->start = 1; iter->end = tm_empty(target); iter->cursor = target->root; - while (iter->cursor->left != NULL) - iter->cursor = iter->cursor->left; - iter->first = iter->cursor; - iter->last = target->root; - while (iter->last->right != NULL) - iter->last = iter->last->right; + 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; + } } -bool tm_iter_start(treemap_iter *iter) { return tm_empty(iter->target) || iter->start; } -bool tm_iter_end(treemap_iter *iter) { return tm_empty(iter->target) || iter->end; } +_Bool tm_iter_start(treemap_iter *iter) { return tm_empty(iter->target) || iter->start; } +_Bool tm_iter_end(treemap_iter *iter) { return tm_empty(iter->target) || iter->end; } void tm_iter_to_start(treemap_iter *iter) { - iter->index = 0; - iter->start = true; - iter->end = tm_empty(iter->target); - iter->cursor = iter->first; + if (!tm_empty(iter->target)) + { + iter->index = 0; + iter->start = 1; + iter->end = tm_empty(iter->target); + iter->cursor = iter->first; + } } void tm_iter_to_end(treemap_iter *iter) { - iter->index = iter->target->count - 1; - iter->start = tm_empty(iter->target); - iter->end = true; - iter->cursor = iter->last; + if (!tm_empty(iter->target)) + { + iter->index = iter->target->count - 1; + iter->start = tm_empty(iter->target); + iter->end = 1; + iter->cursor = iter->last; + } } -bool tm_iter_next(treemap_iter *iter) +_Bool tm_iter_next(treemap_iter *iter) { if (iter->end) - return false; - iter->start = false; - if (iter->cursor->right != NULL) + 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 != NULL) + while (iter->cursor->left != ((void *)0)) iter->cursor = iter->cursor->left; iter->index++; - return true; + return 1; } - while (true) + while (1) { - if (iter->cursor == iter->last) - { - iter->end = true; - return true; - } if (iter->cursor->parent->left == iter->cursor) { iter->cursor = iter->cursor->parent; iter->index++; - return true; + return 1; } iter->cursor = iter->cursor->parent; } } -bool tm_iter_prev(treemap_iter *iter) +_Bool tm_iter_prev(treemap_iter *iter) { if (iter->start) - return false; - iter->end = false; - if (iter->cursor->left != NULL) + 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 != NULL) + while (iter->cursor->right != ((void *)0)) iter->cursor = iter->cursor->right; iter->index--; - return true; + return 1; } - while (true) + while (1) { - if (iter->cursor == iter->first) - { - iter->start = true; - return true; - } if (iter->cursor->parent->right == iter->cursor) { iter->cursor = iter->cursor->parent; iter->index--; - return true; + return 1; } iter->cursor = iter->cursor->parent; } } +_Bool tm_iter_advance(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 >= tm_count(iter->target)) + return 0; + iter->index += steps; + for (size_t i = 0; i < steps; i++) + tm_iter_next(iter); + return 1; +} +_Bool tm_iter_rewind(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; + iter->index -= steps; + for (size_t i = 0; i < steps; i++) + tm_iter_prev(iter); + return 1; +} +_Bool tm_iter_go_to(treemap_iter *iter, size_t index) +{ + if (index >= tm_count(iter->target)) + 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(treemap_iter *iter) { if (tm_empty(iter->target)) - return tm_impl_default_key(); + return (size_t){0}; return iter->cursor->key; } size_t tm_iter_value(treemap_iter *iter) { if (tm_empty(iter->target)) - return tm_impl_default_value(); + return (size_t){0}; return iter->cursor->value; } size_t *tm_iter_rvalue(treemap_iter *iter) { if (tm_empty(iter->target)) - return NULL; + return ((void *)0); return &(iter->cursor->value); } size_t tm_iter_index(treemap_iter *iter) { return iter->index; } @@ -470,21 +566,21 @@ static treemap_node *tm_impl_new_node(size_t key, size_t value) { treemap_node *node = malloc(sizeof(treemap_node)); if (!node) - return NULL; + return ((void *)0); node->key = key; node->value = value; - node->right = NULL; - node->left = NULL; - node->parent = NULL; + node->right = ((void *)0); + node->left = ((void *)0); + node->parent = ((void *)0); node->height = 0; return node; } static treemap_node *tm_impl_get_node(treemap *_map_, size_t key) { if (tm_empty(_map_)) - return NULL; + return ((void *)0); treemap_node *scan = _map_->root; - while (scan != NULL) + while (scan != ((void *)0)) { if (_map_->cmp(scan->key, key) > 0) scan = scan->left; @@ -493,17 +589,17 @@ static treemap_node *tm_impl_get_node(treemap *_map_, size_t key) else return scan; } - return NULL; + return ((void *)0); } static unsigned char tm_impl_h(treemap_node *node) { - if (node == NULL) + if (node == ((void *)0)) return 0; return node->height; } static unsigned char tm_impl_hupdate(treemap_node *node) { - if (node == NULL) + if (node == ((void *)0)) return 0; unsigned char h_l = tm_impl_h(node->left); unsigned char h_r = tm_impl_h(node->right); @@ -513,7 +609,7 @@ static void tm_impl_rotate_right(treemap_node **Z) { treemap_node *root = *Z; treemap_node *new_root = root->left; - if (root->parent != NULL) + if (root->parent != ((void *)0)) { if (root->parent->left == root) root->parent->left = new_root; @@ -534,7 +630,7 @@ static void tm_impl_rotate_left(treemap_node **Z) { treemap_node *root = *Z; treemap_node *new_root = root->right; - if (root->parent != NULL) + if (root->parent != ((void *)0)) { if (root->parent->right == root) root->parent->right = new_root; @@ -553,13 +649,13 @@ static void tm_impl_rotate_left(treemap_node **Z) } static void tm_impl_rebalance(treemap *_map_, treemap_node *node) { - treemap_node *scan = node, *child = NULL; + treemap_node *scan = node, *child = ((void *)0); int balance; - bool is_root = false; - while (scan != NULL) + _Bool is_root = 0; + while (scan != ((void *)0)) { - if (scan->parent == NULL) - is_root = true; + 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) @@ -579,7 +675,7 @@ static void tm_impl_rebalance(treemap *_map_, treemap_node *node) if (is_root) { _map_->root = scan; - is_root = false; + is_root = 0; } scan = scan->parent; } diff --git a/tests/codecov/src/treeset.c b/tests/codecov/src/treeset.c index b63093b..1730619 100644 --- a/tests/codecov/src/treeset.c +++ b/tests/codecov/src/treeset.c @@ -1,6 +1,6 @@ -#include "cmc/treeset.h" +#include -//TREESET_GENERATE(ts, treeset, , size_t) +//CMC_GENERATE_TREESET(ts, treeset, size_t) typedef struct treeset_s { @@ -25,39 +25,43 @@ typedef struct treeset_iter_s struct treeset_node_s *first; struct treeset_node_s *last; size_t index; - bool start; - bool end; + _Bool start; + _Bool end; } treeset_iter, *treeset_iter_ptr; treeset *ts_new(int (*compare)(size_t, size_t)); -void ts_clear(treeset *_set_); -void ts_free(treeset *_set_); -bool ts_insert(treeset *_set_, size_t element); -bool ts_remove(treeset *_set_, size_t element); -bool ts_insert_if(treeset *_set_, size_t element, bool condition); -bool ts_remove_if(treeset *_set_, size_t element, bool condition); -bool ts_max(treeset *_set_, size_t *value); -bool ts_min(treeset *_set_, size_t *value); -bool ts_contains(treeset *_set_, size_t element); -bool ts_empty(treeset *_set_); +void ts_clear(treeset *_set_, void (*deallocator)(size_t)); +void ts_free(treeset *_set_, void (*deallocator)(size_t)); +_Bool ts_insert(treeset *_set_, size_t element); +_Bool ts_remove(treeset *_set_, size_t element); +_Bool ts_max(treeset *_set_, size_t *value); +_Bool ts_min(treeset *_set_, size_t *value); +_Bool ts_contains(treeset *_set_, size_t element); +_Bool ts_empty(treeset *_set_); size_t ts_count(treeset *_set_); +treeset *ts_copy_of(treeset *_set_, size_t (*copy_func)(size_t)); +_Bool ts_equals(treeset *_set1_, treeset *_set2_); +cmc_string ts_to_string(treeset *_set_); treeset *ts_union(treeset *_set1_, treeset *_set2_); treeset *ts_intersection(treeset *_set1_, treeset *_set2_); treeset *ts_difference(treeset *_set1_, treeset *_set2_); treeset *ts_symmetric_difference(treeset *_set1_, treeset *_set2_); -bool ts_is_subset(treeset *_set1_, treeset *_set2_); -bool ts_is_superset(treeset *_set1_, treeset *_set2_); -bool ts_is_proper_subset(treeset *_set1_, treeset *_set2_); -bool ts_is_proper_superset(treeset *_set1_, treeset *_set2_); -bool ts_is_disjointset(treeset *_set1_, treeset *_set2_); +_Bool ts_is_subset(treeset *_set1_, treeset *_set2_); +_Bool ts_is_superset(treeset *_set1_, treeset *_set2_); +_Bool ts_is_proper_subset(treeset *_set1_, treeset *_set2_); +_Bool ts_is_proper_superset(treeset *_set1_, treeset *_set2_); +_Bool ts_is_disjointset(treeset *_set1_, treeset *_set2_); treeset_iter *ts_iter_new(treeset *target); void ts_iter_free(treeset_iter *iter); void ts_iter_init(treeset_iter *iter, treeset *target); -bool ts_iter_start(treeset_iter *iter); -bool ts_iter_end(treeset_iter *iter); +_Bool ts_iter_start(treeset_iter *iter); +_Bool ts_iter_end(treeset_iter *iter); void ts_iter_to_start(treeset_iter *iter); void ts_iter_to_end(treeset_iter *iter); -bool ts_iter_next(treeset_iter *iter); -bool ts_iter_prev(treeset_iter *iter); +_Bool ts_iter_next(treeset_iter *iter); +_Bool ts_iter_prev(treeset_iter *iter); +_Bool ts_iter_advance(treeset_iter *iter, size_t steps); +_Bool ts_iter_rewind(treeset_iter *iter, size_t steps); +_Bool ts_iter_go_to(treeset_iter *iter, size_t index); size_t ts_iter_value(treeset_iter *iter); size_t ts_iter_index(treeset_iter *iter); static inline size_t ts_impl_default_value(void) @@ -79,49 +83,53 @@ treeset *ts_new(int (*compare)(size_t, size_t)) { treeset *_set_ = malloc(sizeof(treeset)); if (!_set_) - return NULL; + return ((void *)0); _set_->count = 0; - _set_->root = NULL; + _set_->root = ((void *)0); _set_->cmp = compare; _set_->it_start = ts_impl_it_start; _set_->it_end = ts_impl_it_end; return _set_; } -void ts_clear(treeset *_set_) +void ts_clear(treeset *_set_, void (*deallocator)(size_t)) { treeset_node *scan = _set_->root; - treeset_node *up = NULL; - while (scan != NULL) + treeset_node *up = ((void *)0); + while (scan != ((void *)0)) { - if (scan->left != NULL) + if (scan->left != ((void *)0)) { treeset_node *left = scan->left; scan->left = up; up = scan; scan = left; } - else if (scan->right != NULL) + else if (scan->right != ((void *)0)) { treeset_node *right = scan->right; scan->left = up; - scan->right = NULL; + scan->right = ((void *)0); up = scan; scan = right; } else { - if (up == NULL) + if (up == ((void *)0)) { + if (deallocator) + deallocator(scan->value); free(scan); - scan = NULL; + scan = ((void *)0); } - while (up != NULL) + while (up != ((void *)0)) { + if (deallocator) + deallocator(scan->value); free(scan); - if (up->right != NULL) + if (up->right != ((void *)0)) { scan = up->right; - up->right = NULL; + up->right = ((void *)0); break; } else @@ -133,26 +141,26 @@ void ts_clear(treeset *_set_) } } _set_->count = 0; - _set_->root = NULL; + _set_->root = ((void *)0); } -void ts_free(treeset *_set_) +void ts_free(treeset *_set_, void (*deallocator)(size_t)) { - ts_clear(_set_); + ts_clear(_set_, deallocator); free(_set_); } -bool ts_insert(treeset *_set_, size_t element) +_Bool ts_insert(treeset *_set_, size_t element) { if (ts_empty(_set_)) { _set_->root = ts_impl_new_node(element); if (!_set_->root) - return false; + return 0; } else { treeset_node *scan = _set_->root; treeset_node *parent = scan; - while (scan != NULL) + while (scan != ((void *)0)) { parent = scan; if (_set_->cmp(scan->value, element) > 0) @@ -160,14 +168,14 @@ bool ts_insert(treeset *_set_, size_t element) else if (_set_->cmp(scan->value, element) < 0) scan = scan->right; else - return false; + return 0; } treeset_node *node; if (_set_->cmp(parent->value, element) > 0) { parent->left = ts_impl_new_node(element); if (!parent->left) - return false; + return 0; parent->left->parent = parent; node = parent->left; } @@ -175,42 +183,42 @@ bool ts_insert(treeset *_set_, size_t element) { parent->right = ts_impl_new_node(element); if (!parent->right) - return false; + return 0; parent->right->parent = parent; node = parent->right; } ts_impl_rebalance(_set_, node); } _set_->count++; - return true; + return 1; } -bool ts_remove(treeset *_set_, size_t element) +_Bool ts_remove(treeset *_set_, size_t element) { treeset_node *node = ts_impl_get_node(_set_, element); if (!node) - return false; - treeset_node *temp = NULL, *unbalanced = NULL; - bool is_root = node->parent == NULL; - if (node->left == NULL && node->right == NULL) + return 0; + 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 = NULL; + _set_->root = ((void *)0); else { unbalanced = node->parent; if (node->parent->right == node) - node->parent->right = NULL; + node->parent->right = ((void *)0); else - node->parent->left = NULL; + node->parent->left = ((void *)0); } free(node); } - else if (node->left == NULL) + else if (node->left == ((void *)0)) { if (is_root) { _set_->root = node->right; - _set_->root->parent = NULL; + _set_->root->parent = ((void *)0); } else { @@ -223,12 +231,12 @@ bool ts_remove(treeset *_set_, size_t element) } free(node); } - else if (node->right == NULL) + else if (node->right == ((void *)0)) { if (is_root) { _set_->root = node->left; - _set_->root->parent = NULL; + _set_->root->parent = ((void *)0); } else { @@ -244,18 +252,18 @@ bool ts_remove(treeset *_set_, size_t element) else { temp = node->right; - while (temp->left != NULL) + while (temp->left != ((void *)0)) temp = temp->left; size_t temp_value = temp->value; unbalanced = temp->parent; - if (temp->left == NULL && temp->right == NULL) + if (temp->left == ((void *)0) && temp->right == ((void *)0)) { if (temp->parent->right == temp) - temp->parent->right = NULL; + temp->parent->right = ((void *)0); else - temp->parent->left = NULL; + temp->parent->left = ((void *)0); } - else if (temp->left == NULL) + else if (temp->left == ((void *)0)) { temp->right->parent = temp->parent; if (temp->parent->right == temp) @@ -263,7 +271,7 @@ bool ts_remove(treeset *_set_, size_t element) else temp->parent->left = temp->right; } - else if (temp->right == NULL) + else if (temp->right == ((void *)0)) { temp->left->parent = temp->parent; if (temp->parent->right == temp) @@ -274,66 +282,94 @@ bool ts_remove(treeset *_set_, size_t element) free(temp); node->value = temp_value; } - if (unbalanced != NULL) + if (unbalanced != ((void *)0)) ts_impl_rebalance(_set_, unbalanced); _set_->count--; if (_set_->count == 0) - _set_->root = NULL; - return true; + _set_->root = ((void *)0); + return 1; } -bool ts_insert_if(treeset *_set_, size_t element, bool condition) -{ - if (condition) - return ts_insert(_set_, element); - return false; -} -bool ts_remove_if(treeset *_set_, size_t element, bool condition) -{ - if (condition) - return ts_remove(_set_, element); - return false; -} -bool ts_max(treeset *_set_, size_t *value) +_Bool ts_max(treeset *_set_, size_t *value) { if (ts_empty(_set_)) - return false; + return 0; treeset_node *scan = _set_->root; - while (scan->right != NULL) + while (scan->right != ((void *)0)) scan = scan->right; *value = scan->value; - return true; + return 1; } -bool ts_min(treeset *_set_, size_t *value) +_Bool ts_min(treeset *_set_, size_t *value) { if (ts_empty(_set_)) - return false; + return 0; treeset_node *scan = _set_->root; - while (scan->left != NULL) + while (scan->left != ((void *)0)) scan = scan->left; *value = scan->value; - return true; + return 1; } -bool ts_contains(treeset *_set_, size_t element) +_Bool ts_contains(treeset *_set_, size_t element) { treeset_node *scan = _set_->root; - while (scan != NULL) + while (scan != ((void *)0)) { if (_set_->cmp(scan->value, element) > 0) scan = scan->left; else if (_set_->cmp(scan->value, element) < 0) scan = scan->right; else - return true; + return 1; } - return false; + return 0; } -bool ts_empty(treeset *_set_) { return _set_->count == 0; } +_Bool ts_empty(treeset *_set_) { return _set_->count == 0; } size_t ts_count(treeset *_set_) { return _set_->count; } +treeset *ts_copy_of(treeset *_set_, size_t (*copy_func)(size_t)) +{ + treeset *result = ts_new(_set_->cmp); + if (!result) + return ((void *)0); + treeset_iter iter; + ts_iter_init(&iter, _set_); + if (!ts_empty(_set_)) + { + for (ts_iter_to_start(&iter); !ts_iter_end(&iter); ts_iter_next(&iter)) + { + if (copy_func) + ts_insert(result, copy_func(ts_iter_value(&iter))); + else + ts_insert(result, ts_iter_value(&iter)); + } + } + return result; +} +_Bool ts_equals(treeset *_set1_, treeset *_set2_) +{ + if (ts_count(_set1_) != ts_count(_set2_)) + return 0; + treeset_iter iter; + ts_iter_init(&iter, _set1_); + for (ts_iter_to_start(&iter); !ts_iter_end(&iter); ts_iter_next(&iter)) + { + if (ts_impl_get_node(_set2_, ts_iter_value(&iter)) == ((void *)0)) + return 0; + } + return 1; +} +cmc_string ts_to_string(treeset *_set_) +{ + cmc_string str; + treeset *s_ = _set_; + const char *name = "treeset"; + snprintf(str.s, cmc_string_len, cmc_string_fmt_treeset, name, s_, s_->root, s_->count, s_->cmp); + return str; +} treeset *ts_union(treeset *_set1_, treeset *_set2_) { treeset *_set_r_ = ts_new(_set1_->cmp); if (!_set_r_) - return NULL; + return ((void *)0); treeset_iter iter1, iter2; ts_iter_init(&iter1, _set1_); ts_iter_init(&iter2, _set2_); @@ -351,7 +387,7 @@ treeset *ts_intersection(treeset *_set1_, treeset *_set2_) { treeset *_set_r_ = ts_new(_set1_->cmp); if (!_set_r_) - return NULL; + return ((void *)0); treeset *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; treeset *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; treeset_iter iter; @@ -359,7 +395,7 @@ treeset *ts_intersection(treeset *_set1_, treeset *_set2_) for (ts_iter_to_start(&iter); !ts_iter_end(&iter); ts_iter_next(&iter)) { size_t value = ts_iter_value(&iter); - if (ts_impl_get_node(_set_B_, value) != NULL) + if (ts_impl_get_node(_set_B_, value) != ((void *)0)) ts_insert(_set_r_, value); } return _set_r_; @@ -368,13 +404,13 @@ treeset *ts_difference(treeset *_set1_, treeset *_set2_) { treeset *_set_r_ = ts_new(_set1_->cmp); if (!_set_r_) - return NULL; + return ((void *)0); treeset_iter iter; ts_iter_init(&iter, _set1_); for (ts_iter_to_start(&iter); !ts_iter_end(&iter); ts_iter_next(&iter)) { size_t value = ts_iter_value(&iter); - if (ts_impl_get_node(_set2_, value) == NULL) + if (ts_impl_get_node(_set2_, value) == ((void *)0)) ts_insert(_set_r_, value); } return _set_r_; @@ -383,51 +419,51 @@ treeset *ts_symmetric_difference(treeset *_set1_, treeset *_set2_) { treeset *_set_r_ = ts_new(_set1_->cmp); if (!_set_r_) - return NULL; + return ((void *)0); treeset_iter iter1, iter2; ts_iter_init(&iter1, _set1_); ts_iter_init(&iter2, _set2_); for (ts_iter_to_start(&iter1); !ts_iter_end(&iter1); ts_iter_next(&iter1)) { size_t value = ts_iter_value(&iter1); - if (ts_impl_get_node(_set2_, value) == NULL) + if (ts_impl_get_node(_set2_, value) == ((void *)0)) ts_insert(_set_r_, value); } for (ts_iter_to_start(&iter2); !ts_iter_end(&iter2); ts_iter_next(&iter2)) { size_t value = ts_iter_value(&iter2); - if (ts_impl_get_node(_set1_, value) == NULL) + if (ts_impl_get_node(_set1_, value) == ((void *)0)) ts_insert(_set_r_, value); } return _set_r_; } -bool ts_is_subset(treeset *_set1_, treeset *_set2_) +_Bool ts_is_subset(treeset *_set1_, treeset *_set2_) { if (ts_count(_set1_) > ts_count(_set2_)) - return false; + return 0; if (ts_empty(_set1_)) - return true; + return 1; treeset_iter iter; ts_iter_init(&iter, _set1_); for (ts_iter_to_start(&iter); !ts_iter_end(&iter); ts_iter_next(&iter)) { size_t value = ts_iter_value(&iter); if (!ts_contains(_set2_, value)) - return false; + return 0; } - return true; + return 1; } -bool ts_is_superset(treeset *_set1_, treeset *_set2_) { return ts_is_subset(_set2_, _set1_); } -bool ts_is_proper_subset(treeset *_set1_, treeset *_set2_) +_Bool ts_is_superset(treeset *_set1_, treeset *_set2_) { return ts_is_subset(_set2_, _set1_); } +_Bool ts_is_proper_subset(treeset *_set1_, treeset *_set2_) { if (ts_count(_set1_) >= ts_count(_set2_)) - return false; + return 0; if (ts_empty(_set1_)) { if (!ts_empty(_set2_)) - return true; + return 1; else - return false; + return 0; } treeset_iter iter; ts_iter_init(&iter, _set1_); @@ -435,126 +471,177 @@ bool ts_is_proper_subset(treeset *_set1_, treeset *_set2_) { size_t value = ts_iter_value(&iter); if (!ts_contains(_set2_, value)) - return false; + return 0; } - return true; + return 1; } -bool ts_is_proper_superset(treeset *_set1_, treeset *_set2_) { return ts_is_proper_subset(_set2_, _set1_); } -bool ts_is_disjointset(treeset *_set1_, treeset *_set2_) +_Bool ts_is_proper_superset(treeset *_set1_, treeset *_set2_) { return ts_is_proper_subset(_set2_, _set1_); } +_Bool ts_is_disjointset(treeset *_set1_, treeset *_set2_) { if (ts_empty(_set1_)) - return true; + return 1; treeset_iter iter; ts_iter_init(&iter, _set1_); for (ts_iter_to_start(&iter); !ts_iter_end(&iter); ts_iter_next(&iter)) { size_t value = ts_iter_value(&iter); if (ts_contains(_set2_, value)) - return false; + return 0; } - return true; + return 1; } treeset_iter *ts_iter_new(treeset *target) { treeset_iter *iter = malloc(sizeof(treeset_iter)); if (!iter) - return NULL; + return ((void *)0); ts_iter_init(iter, target); return iter; } void ts_iter_free(treeset_iter *iter) { free(iter); } void ts_iter_init(treeset_iter *iter, treeset *target) { + memset(iter, 0, sizeof(treeset_iter)); iter->target = target; - iter->index = 0; - iter->start = true; + iter->start = 1; iter->end = ts_empty(target); iter->cursor = target->root; - while (iter->cursor->left != NULL) - iter->cursor = iter->cursor->left; - iter->first = iter->cursor; - iter->last = target->root; - while (iter->last->right != NULL) - iter->last = iter->last->right; + 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; + } } -bool ts_iter_start(treeset_iter *iter) { return ts_empty(iter->target) || iter->start; } -bool ts_iter_end(treeset_iter *iter) { return ts_empty(iter->target) || iter->end; } +_Bool ts_iter_start(treeset_iter *iter) { return ts_empty(iter->target) || iter->start; } +_Bool ts_iter_end(treeset_iter *iter) { return ts_empty(iter->target) || iter->end; } void ts_iter_to_start(treeset_iter *iter) { - iter->index = 0; - iter->start = true; - iter->end = ts_empty(iter->target); - iter->cursor = iter->first; + if (!ts_empty(iter->target)) + { + iter->index = 0; + iter->start = 1; + iter->end = ts_empty(iter->target); + iter->cursor = iter->first; + } } void ts_iter_to_end(treeset_iter *iter) { - iter->index = iter->target->count - 1; - iter->start = ts_empty(iter->target); - iter->end = true; - iter->cursor = iter->last; + if (!ts_empty(iter->target)) + { + iter->index = iter->target->count - 1; + iter->start = ts_empty(iter->target); + iter->end = 1; + iter->cursor = iter->last; + } } -bool ts_iter_next(treeset_iter *iter) +_Bool ts_iter_next(treeset_iter *iter) { if (iter->end) - return false; + return 0; + if (iter->cursor == iter->last) + { + iter->end = 1; + return 1; + } iter->start = ts_empty(iter->target); - if (iter->cursor->right != NULL) + if (iter->cursor->right != ((void *)0)) { iter->cursor = iter->cursor->right; - while (iter->cursor->left != NULL) + while (iter->cursor->left != ((void *)0)) iter->cursor = iter->cursor->left; iter->index++; - return true; + return 1; } - while (true) + while (1) { - if (iter->cursor == iter->last) - { - iter->end = true; - return true; - } if (iter->cursor->parent->left == iter->cursor) { iter->cursor = iter->cursor->parent; iter->index++; - return true; + return 1; } iter->cursor = iter->cursor->parent; } } -bool ts_iter_prev(treeset_iter *iter) +_Bool ts_iter_prev(treeset_iter *iter) { if (iter->start) - return false; + return 0; + if (iter->cursor == iter->first) + { + iter->start = 1; + return 1; + } iter->end = ts_empty(iter->target); - if (iter->cursor->left != NULL) + if (iter->cursor->left != ((void *)0)) { iter->cursor = iter->cursor->left; - while (iter->cursor->right != NULL) + while (iter->cursor->right != ((void *)0)) iter->cursor = iter->cursor->right; iter->index--; - return true; + return 1; } - while (true) + while (1) { - if (iter->cursor == iter->first) - { - iter->start = true; - return true; - } if (iter->cursor->parent->right == iter->cursor) { iter->cursor = iter->cursor->parent; iter->index--; - return true; + return 1; } iter->cursor = iter->cursor->parent; } } +_Bool ts_iter_advance(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 >= ts_count(iter->target)) + return 0; + iter->index += steps; + for (size_t i = 0; i < steps; i++) + ts_iter_next(iter); + return 1; +} +_Bool ts_iter_rewind(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; + iter->index -= steps; + for (size_t i = 0; i < steps; i++) + ts_iter_prev(iter); + return 1; +} +_Bool ts_iter_go_to(treeset_iter *iter, size_t index) +{ + if (index >= ts_count(iter->target)) + 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(treeset_iter *iter) { if (ts_empty(iter->target)) - return ts_impl_default_value(); + return (size_t){0}; return iter->cursor->value; } size_t ts_iter_index(treeset_iter *iter) { return iter->index; } @@ -562,20 +649,20 @@ static treeset_node *ts_impl_new_node(size_t element) { treeset_node *node = malloc(sizeof(treeset_node)); if (!node) - return NULL; + return ((void *)0); node->value = element; - node->right = NULL; - node->left = NULL; - node->parent = NULL; + node->right = ((void *)0); + node->left = ((void *)0); + node->parent = ((void *)0); node->height = 0; return node; } static treeset_node *ts_impl_get_node(treeset *_set_, size_t element) { if (ts_empty(_set_)) - return NULL; + return ((void *)0); treeset_node *scan = _set_->root; - while (scan != NULL) + while (scan != ((void *)0)) { if (_set_->cmp(scan->value, element) > 0) scan = scan->left; @@ -584,17 +671,17 @@ static treeset_node *ts_impl_get_node(treeset *_set_, size_t element) else return scan; } - return NULL; + return ((void *)0); } static unsigned char ts_impl_h(treeset_node *node) { - if (node == NULL) + if (node == ((void *)0)) return 0; return node->height; } static unsigned char ts_impl_hupdate(treeset_node *node) { - if (node == NULL) + if (node == ((void *)0)) return 0; unsigned char h_l = ts_impl_h(node->left); unsigned char h_r = ts_impl_h(node->right); @@ -604,7 +691,7 @@ static void ts_impl_rotate_right(treeset_node **Z) { treeset_node *root = *Z; treeset_node *new_root = root->left; - if (root->parent != NULL) + if (root->parent != ((void *)0)) { if (root->parent->left == root) root->parent->left = new_root; @@ -625,7 +712,7 @@ static void ts_impl_rotate_left(treeset_node **Z) { treeset_node *root = *Z; treeset_node *new_root = root->right; - if (root->parent != NULL) + if (root->parent != ((void *)0)) { if (root->parent->right == root) root->parent->right = new_root; @@ -644,13 +731,13 @@ static void ts_impl_rotate_left(treeset_node **Z) } static void ts_impl_rebalance(treeset *_set_, treeset_node *node) { - treeset_node *scan = node, *child = NULL; + treeset_node *scan = node, *child = ((void *)0); int balance; - bool is_root = false; - while (scan != NULL) + _Bool is_root = 0; + while (scan != ((void *)0)) { - if (scan->parent == NULL) - is_root = true; + 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) @@ -670,7 +757,7 @@ static void ts_impl_rebalance(treeset *_set_, treeset_node *node) if (is_root) { _set_->root = scan; - is_root = false; + is_root = 0; } scan = scan->parent; } diff --git a/tests/codecov/unt/bidimap.c b/tests/codecov/unt/bidimap.c new file mode 100644 index 0000000..7245b4d --- /dev/null +++ b/tests/codecov/unt/bidimap.c @@ -0,0 +1,33 @@ +#include "utl.c" +#include +#include +#include + +#include "../src/bidimap.c" + +CMC_CREATE_UNIT(bidimap_test, false, { + CMC_CREATE_TEST(new, { + bidimap *map = bm_new(100, 0.6, cmp, hash, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + bm_free(map, NULL); + }); + + CMC_CREATE_TEST(clear[count], { + bidimap *map = bm_new(100, 0.6, cmp, hash, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + for (size_t i = 0; i < 50; i++) + cmc_assert(bm_insert(map, i, i)); + + cmc_assert_equals(size_t, 50, bm_count(map)); + + bm_clear(map, NULL); + + cmc_assert_equals(size_t, 0, bm_count(map)); + + bm_free(map, NULL); + }); +}); diff --git a/tests/codecov/unt/deque.c b/tests/codecov/unt/deque.c index f31cb9a..ed03065 100644 --- a/tests/codecov/unt/deque.c +++ b/tests/codecov/unt/deque.c @@ -1,5 +1,8 @@ -#include "utl/assert.h" -#include "utl/test.h" +#include "utl.c" +#include +#include +#include + #include "../src/deque.c" CMC_CREATE_UNIT(deque_test, false, { @@ -11,16 +14,16 @@ CMC_CREATE_UNIT(deque_test, false, { cmc_assert_equals(size_t, 1000000, d->capacity); cmc_assert_equals(size_t, 0, d_count(d)); - d_free(d); + d_free(d, NULL); }); - CMC_CREATE_TEST(new[edge_case:capacity = 0], { + CMC_CREATE_TEST(new[capacity = 0], { deque *d = d_new(0); cmc_assert_equals(ptr, NULL, d); }); - CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], { + CMC_CREATE_TEST(new[capacity = UINT64_MAX], { deque *d = d_new(UINT64_MAX); cmc_assert_equals(ptr, NULL, d); @@ -36,15 +39,15 @@ CMC_CREATE_UNIT(deque_test, false, { cmc_assert_equals(size_t, 50, d_count(d)); - d_clear(d); + d_clear(d, NULL); cmc_assert_equals(size_t, 0, d_count(d)); cmc_assert_equals(size_t, 100, d_capacity(d)); - d_free(d); + d_free(d, NULL); }); - CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], { + CMC_CREATE_TEST(buffer_growth[capacity = 1], { deque *d = d_new(1); cmc_assert_not_equals(ptr, NULL, d); @@ -55,7 +58,574 @@ CMC_CREATE_UNIT(deque_test, false, { cmc_assert_equals(size_t, 50, d_count(d)); cmc_assert_lesser_equals(size_t, d_capacity(d), d_count(d)); - d_free(d); + d_free(d, NULL); }); + CMC_CREATE_TEST(buffer_growth[item preservation], { + deque *d = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d); + + for (size_t i = 1; i <= 1200; i++) + { + if (i % 2 == 0) + d_push_front(d, i); + else + d_push_back(d, i); + } + + size_t sum = 0; + for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++) + sum += d->buffer[i]; + + cmc_assert_equals(size_t, 1200, d_count(d)); + cmc_assert_equals(size_t, 720600, sum); + + d_free(d, NULL); + }); + + CMC_CREATE_TEST(push_front[count capacity], { + deque *d = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d); + + for (size_t i = 0; i < 150; i++) + cmc_assert(d_push_front(d, i)); + + cmc_assert_equals(size_t, 150, d_count(d)); + cmc_assert_greater(size_t, 100, d_capacity(d)); + + d_free(d, NULL); + }); + + CMC_CREATE_TEST(push_front[item preservation], { + deque *d = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d); + + for (size_t i = 1; i <= 100; i++) + cmc_assert(d_push_front(d, i)); + + size_t sum = 0; + + for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++) + { + sum += d->buffer[i]; + } + + cmc_assert_equals(size_t, 5050, sum); + + d_free(d, NULL); + }); + + CMC_CREATE_TEST(push_back[count capacity], { + deque *d = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d); + + for (size_t i = 0; i < 150; i++) + cmc_assert(d_push_back(d, i)); + + cmc_assert_equals(size_t, 150, d_count(d)); + cmc_assert_greater(size_t, 100, d_capacity(d)); + + d_free(d, NULL); + }); + + CMC_CREATE_TEST(push_back[item preservation], { + deque *d = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d); + + for (size_t i = 1; i <= 100; i++) + cmc_assert(d_push_back(d, i)); + + size_t sum = 0; + + for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++) + { + sum += d->buffer[i]; + } + + cmc_assert_equals(size_t, 5050, sum); + + d_free(d, NULL); + }); + + CMC_CREATE_TEST(pop_front[count capacity], { + deque *d = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d); + + cmc_assert(d_push_front(d, 10)); + cmc_assert(d_pop_front(d)); + + cmc_assert_equals(size_t, 0, d_count(d)); + + cmc_assert(d_push_back(d, 10)); + cmc_assert(d_pop_front(d)); + + cmc_assert_equals(size_t, 0, d_count(d)); + + d_free(d, NULL); + }); + + CMC_CREATE_TEST(pop_front[item preservation], { + deque *d = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d); + + for (size_t i = 1; i <= 200; i++) + cmc_assert(d_push_front(d, i)); + + for (size_t i = 0; i < 100; i++) + cmc_assert(d_pop_front(d)); + + size_t sum = 0; + + for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++) + { + sum += d->buffer[i]; + } + + cmc_assert_equals(size_t, 5050, sum); + + d_free(d, NULL); + }); + + CMC_CREATE_TEST(pop_back[count capacity], { + deque *d = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d); + + cmc_assert(d_push_front(d, 10)); + cmc_assert(d_pop_back(d)); + + cmc_assert_equals(size_t, 0, d_count(d)); + + cmc_assert(d_push_back(d, 10)); + cmc_assert(d_pop_back(d)); + + cmc_assert_equals(size_t, 0, d_count(d)); + + d_free(d, NULL); + }); + + CMC_CREATE_TEST(pop_back[item preservation], { + deque *d = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d); + + for (size_t i = 1; i <= 200; i++) + cmc_assert(d_push_back(d, i)); + + for (size_t i = 0; i < 100; i++) + cmc_assert(d_pop_back(d)); + + size_t sum = 0; + + for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++) + { + sum += d->buffer[i]; + } + + cmc_assert_equals(size_t, 5050, sum); + + d_free(d, NULL); + }); + + CMC_CREATE_TEST(Mixed IO, { + deque *d = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d); + + cmc_assert(d_push_front(d, 10)); + cmc_assert(d_push_front(d, 10)); + cmc_assert(d_pop_back(d)); + cmc_assert(d_pop_back(d)); + + cmc_assert_equals(size_t, 0, d_count(d)); + + cmc_assert(d_push_back(d, 10)); + cmc_assert(d_push_back(d, 10)); + cmc_assert(d_pop_back(d)); + cmc_assert(d_pop_back(d)); + + cmc_assert_equals(size_t, 0, d_count(d)); + + cmc_assert(d_push_front(d, 10)); + cmc_assert(d_push_front(d, 10)); + cmc_assert(d_pop_front(d)); + cmc_assert(d_pop_front(d)); + + cmc_assert_equals(size_t, 0, d_count(d)); + + cmc_assert(d_push_back(d, 10)); + cmc_assert(d_push_back(d, 10)); + cmc_assert(d_pop_front(d)); + cmc_assert(d_pop_front(d)); + + cmc_assert_equals(size_t, 0, d_count(d)); + // ---------- + cmc_assert(d_push_back(d, 10)); + cmc_assert(d_push_front(d, 10)); + cmc_assert(d_pop_back(d)); + cmc_assert(d_pop_front(d)); + + cmc_assert_equals(size_t, 0, d_count(d)); + + cmc_assert(d_push_back(d, 10)); + cmc_assert(d_push_front(d, 10)); + cmc_assert(d_pop_front(d)); + cmc_assert(d_pop_back(d)); + + cmc_assert_equals(size_t, 0, d_count(d)); + + cmc_assert(d_push_front(d, 10)); + cmc_assert(d_push_back(d, 10)); + cmc_assert(d_pop_back(d)); + cmc_assert(d_pop_front(d)); + + cmc_assert_equals(size_t, 0, d_count(d)); + + cmc_assert(d_push_front(d, 10)); + cmc_assert(d_push_back(d, 10)); + cmc_assert(d_pop_front(d)); + cmc_assert(d_pop_back(d)); + + cmc_assert_equals(size_t, 0, d_count(d)); + + d_free(d, NULL); + }); + + CMC_CREATE_TEST(front[count = 0], { + deque *d = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d); + + size_t r = d_front(d); + + cmc_assert_equals(size_t, (size_t){0}, r); + + d_free(d, NULL); + }); + + CMC_CREATE_TEST(front[sum], { + deque *d = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d); + + size_t sum = 0; + + for (size_t i = 0; i <= 100; i++) + { + if (i % 2 == 0) + cmc_assert(d_push_back(d, i)); + else + cmc_assert(d_push_front(d, i)); + } + + while (!d_empty(d)) + { + size_t r = d_front(d); + + sum += r; + + cmc_assert(d_pop_front(d)); + } + + cmc_assert_equals(size_t, 5050, sum); + + d_free(d, NULL); + }); + + CMC_CREATE_TEST(back[count = 0], { + deque *d = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d); + + size_t r = d_back(d); + + cmc_assert_equals(size_t, (size_t){0}, r); + + d_free(d, NULL); + }); + + CMC_CREATE_TEST(back[sum], { + deque *d = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d); + + size_t sum = 0; + + for (size_t i = 0; i <= 100; i++) + { + if (i % 2 == 0) + cmc_assert(d_push_back(d, i)); + else + cmc_assert(d_push_front(d, i)); + } + + while (!d_empty(d)) + { + size_t r = d_back(d); + + sum += r; + + cmc_assert(d_pop_back(d)); + } + + cmc_assert_equals(size_t, 5050, sum); + + d_free(d, NULL); + }); + + CMC_CREATE_TEST(contains, { + deque *d = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d); + + for (size_t i = 1; i <= 20; i++) + cmc_assert(d_push_back(d, i)); + + for (size_t i = 1; i <= 20; i++) + cmc_assert(d_contains(d, i, cmp)); + + d_clear(d, NULL); + + for (size_t i = 1; i <= 20; i++) + cmc_assert(d_push_front(d, i)); + + for (size_t i = 1; i <= 20; i++) + cmc_assert(d_contains(d, i, cmp)); + + d_free(d, NULL); + }); + + CMC_CREATE_TEST(contains[count = 0], { + deque *d = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d); + + cmc_assert(!d_contains(d, 10, cmp)); + + d_free(d, NULL); + }); + + CMC_CREATE_TEST(contains[count = 1], { + deque *d = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d); + + cmc_assert(!d_contains(d, 10, cmp)); + + cmc_assert(d_push_back(d, 100)); + + cmc_assert(d_contains(d, 100, cmp)); + cmc_assert(!d_contains(d, 101, cmp)); + + cmc_assert(d_pop_front(d)); + cmc_assert(d_push_front(d, 100)); + + cmc_assert(d_contains(d, 100, cmp)); + cmc_assert(!d_contains(d, 101, cmp)); + + d_free(d, NULL); + }); + + CMC_CREATE_TEST(empty, { + deque *d = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d); + + cmc_assert(d_empty(d)); + + cmc_assert(d_push_front(d, 1)); + + cmc_assert(!d_empty(d)); + + d_free(d, NULL); + }); + + CMC_CREATE_TEST(full, { + deque *d = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d); + + cmc_assert(!d_full(d)); + + for (size_t i = 0; i != d_capacity(d); i++) + cmc_assert(d_push_front(d, i)); + + cmc_assert(d_full(d)); + + d_free(d, NULL); + }); + + CMC_CREATE_TEST(count, { + deque *d = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d); + + cmc_assert_equals(size_t, 0, d_count(d)); + + for (size_t i = 0; i < 100; i++) + cmc_assert(d_push_back(d, i)); + + cmc_assert_equals(size_t, 100, d_count(d)); + + d_free(d, NULL); + }); + + CMC_CREATE_TEST(capacity, { + deque *d = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d); + + cmc_assert_equals(size_t, 100, d_capacity(d)); + + d_free(d, NULL); + }); + + CMC_CREATE_TEST(resize, { + deque *d = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d); + + for (size_t i = 0; i < 150; i++) + { + if (i % 2 == 0) + cmc_assert(d_push_back(d, i)); + else + cmc_assert(d_push_front(d, i)); + } + + cmc_assert_equals(size_t, 150, d_count(d)); + cmc_assert(d_resize(d, d_count(d))); + cmc_assert_equals(size_t, 150, d_capacity(d)); + + d_free(d, NULL); + }); + + CMC_CREATE_TEST(resize[item preservation], { + deque *d = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d); + + for (size_t i = 1; i <= 150; i++) + { + if (i % 2 != 0) + cmc_assert(d_push_back(d, i)); + else + cmc_assert(d_push_front(d, i)); + } + + cmc_assert(d_resize(d, d_count(d))); + + size_t sum = 0; + + for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++) + { + sum += d->buffer[i]; + } + + cmc_assert_equals(size_t, 11325, sum); + + d_free(d, NULL); + }); + + CMC_CREATE_TEST(copy_of, { + deque *d1 = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d1); + + for (size_t i = 1; i <= 150; i++) + { + if (i % 2 != 0) + cmc_assert(d_push_back(d1, i)); + else + cmc_assert(d_push_front(d1, i)); + } + + deque *d2 = d_copy_of(d1, NULL); + + cmc_assert_not_equals(ptr, NULL, d2); + cmc_assert_equals(size_t, d_count(d1), d_count(d2)); + + for (size_t i1 = d1->front, i2 = d2->front, j = 0; j < d1->count; j++) + { + cmc_assert_equals(size_t, d1->buffer[i1], d2->buffer[i2]); + + i1 = (i1 + 1) % d1->capacity; + i2 = (i2 + 1) % d2->capacity; + } + + d_free(d1, NULL); + d_free(d2, NULL); + }); + + CMC_CREATE_TEST(equals, { + deque *d1 = d_new(100); + deque *d2 = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d1); + cmc_assert_not_equals(ptr, NULL, d2); + + for (size_t i = 1; i <= 150; i++) + { + if (i % 2 != 0) + { + cmc_assert(d_push_back(d1, i)); + cmc_assert(d_push_back(d2, i)); + } + else + { + cmc_assert(d_push_front(d1, i)); + cmc_assert(d_push_front(d2, i)); + } + } + + cmc_assert(d_equals(d1, d2, cmp)); + + d_free(d1, NULL); + d_free(d2, NULL); + }); + + CMC_CREATE_TEST(equals[from copy], { + deque *d1 = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d1); + + for (size_t i = 1; i <= 150; i++) + { + if (i % 2 != 0) + cmc_assert(d_push_back(d1, i)); + else + cmc_assert(d_push_front(d1, i)); + } + + deque *d2 = d_copy_of(d1, NULL); + + cmc_assert_not_equals(ptr, NULL, d2); + + cmc_assert(d_equals(d1, d2, cmp)); + + d_free(d1, NULL); + d_free(d2, NULL); + }); + + CMC_CREATE_TEST(equals[count = 0], { + deque *d1 = d_new(100); + + cmc_assert_not_equals(ptr, NULL, d1); + + deque *d2 = d_copy_of(d1, NULL); + + cmc_assert_not_equals(ptr, NULL, d2); + + cmc_assert(d_equals(d1, d2, cmp)); + + d_free(d1, NULL); + d_free(d2, NULL); + }); }); diff --git a/tests/codecov/unt/hashmap.c b/tests/codecov/unt/hashmap.c index cc5cce5..8f96cac 100644 --- a/tests/codecov/unt/hashmap.c +++ b/tests/codecov/unt/hashmap.c @@ -1,8 +1,9 @@ -#include "utl/assert.h" -#include "utl/test.h" -#include "../src/hashmap.c" - #include "utl.c" +#include +#include +#include + +#include "../src/hashmap.c" CMC_CREATE_UNIT(hashmap_test, false, { CMC_CREATE_TEST(new, { @@ -13,17 +14,17 @@ CMC_CREATE_UNIT(hashmap_test, false, { cmc_assert_equals(size_t, 0, hm_count(map)); cmc_assert_greater_equals(size_t, (943722 / 0.6), hm_capacity(map)); - hm_free(map); + hm_free(map, NULL); }); - CMC_CREATE_TEST(new[edge_case:capacity = 0], { + CMC_CREATE_TEST(new[capacity = 0], { hashmap *map = hm_new(0, 0.6, cmp, hash); cmc_assert_equals(ptr, NULL, map); }); - CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], { - hashmap *map = hm_new(UINT64_MAX, 0.6, cmp, hash); + CMC_CREATE_TEST(new[capacity = UINT64_MAX], { + hashmap *map = hm_new(UINT64_MAX, 0.99, cmp, hash); cmc_assert_equals(ptr, NULL, map); }); @@ -38,11 +39,415 @@ CMC_CREATE_UNIT(hashmap_test, false, { cmc_assert_equals(size_t, 50, hm_count(map)); - hm_clear(map); + hm_clear(map, NULL); cmc_assert_equals(size_t, 0, hm_count(map)); - hm_free(map); + hm_free(map, NULL); }); + CMC_CREATE_TEST(insert, { + hashmap *map = hm_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + cmc_assert(hm_insert(map, 1, 1)); + cmc_assert_equals(size_t, 1, hm_count(map)); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(insert[smallest capacity], { + hashmap *map = hm_new(1, 0.99, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + cmc_assert_equals(size_t, cmc_hashtable_primes[0], hm_capacity(map)); + cmc_assert(hm_insert(map, 1, 1)); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(insert[element position], { + // Using the numhash the key is the hash itself + hashmap *map = hm_new(1, 0.99, cmp, numhash); + + cmc_assert_not_equals(ptr, NULL, map); + + size_t capacity = hm_capacity(map); + + cmc_assert_greater(size_t, 0, capacity); + + cmc_assert(hm_insert(map, capacity - 1, capacity - 1)); + cmc_assert(hm_insert(map, capacity, capacity)); + + cmc_assert_equals(size_t, capacity - 1, map->buffer[capacity - 1].key); + cmc_assert_equals(size_t, capacity, map->buffer[0].key); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(insert[distance], { + hashmap *map = hm_new(500, 0.6, cmp, hash0); + + cmc_assert_not_equals(ptr, NULL, map); + + for (size_t i = 0; i < 200; i++) + cmc_assert(hm_insert(map, i, i)); + + // Everything is hashed to 0 so key 0 should have dist 0, key 1 dist 1, etc + for (size_t i = 0; i < 200; i++) + cmc_assert_equals(size_t, i, map->buffer[i].dist); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(insert[distance wrap], { + hashmap *map = hm_new(1, 0.99, cmp, hashcapminus1); + + cmc_assert_not_equals(ptr, NULL, map); + + size_t capacity = hm_capacity(map); + + // Just to be sure, not part of the test + cmc_assert_equals(size_t, cmc_hashtable_primes[0] - 1, hashcapminus1(0)); + cmc_assert_equals(size_t, capacity - 1, hashcapminus1(0)); + + cmc_assert(hm_insert(map, 0, 0)); + cmc_assert(hm_insert(map, 1, 1)); + + cmc_assert_equals(size_t, 0, map->buffer[capacity - 1].dist); + cmc_assert_equals(size_t, 1, map->buffer[0].dist); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(insert[distances], { + hashmap *map = hm_new(1, 0.99, cmp, hashcapminus4); + + cmc_assert_not_equals(ptr, NULL, map); + + cmc_assert_equals(size_t, cmc_hashtable_primes[0], hm_capacity(map)); + + for (size_t i = 0; i < 6; i++) + cmc_assert(hm_insert(map, i, i)); + + for (size_t i = 0; i < 6; i++) + cmc_assert_equals(size_t, i, hm_impl_get_entry(map, i)->dist); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(insert[buffer growth and item preservation], { + hashmap *map = hm_new(1, 0.99, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + cmc_assert_equals(size_t, cmc_hashtable_primes[0], hm_capacity(map)); + + size_t p = 0; + for (size_t i = 0; i < 100000; i++) + { + if (hm_full(map)) + p++; + + cmc_assert(hm_insert(map, i, i)); + } + + cmc_assert_equals(size_t, cmc_hashtable_primes[p], hm_capacity(map)); + + for (size_t i = 0; i < 100000; i++) + cmc_assert(hm_contains(map, i)); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(update, { + hashmap *map = hm_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + cmc_assert(hm_insert(map, 1, 1)); + + size_t old; + cmc_assert(hm_update(map, 1, 2, &old)); + + cmc_assert_equals(size_t, 1, old); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(update[key not found], { + hashmap *map = hm_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + for (size_t i = 0; i < 100; i++) + cmc_assert(hm_insert(map, i, i)); + + cmc_assert(!hm_update(map, 120, 120, NULL)); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(remove, { + hashmap *map = hm_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + for (size_t i = 0; i < 100; i++) + cmc_assert(hm_insert(map, i, i)); + + for (size_t i = 0; i < 100; i++) + cmc_assert(hm_remove(map, i, NULL)); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(remove[count = 0], { + hashmap *map = hm_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + for (size_t i = 100; i < 200; i++) + cmc_assert(!hm_remove(map, i, NULL)); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(remove[key not found], { + hashmap *map = hm_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + for (size_t i = 0; i < 100; i++) + cmc_assert(hm_insert(map, i, i)); + + for (size_t i = 100; i < 200; i++) + cmc_assert(!hm_remove(map, i, NULL)); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(max, { + hashmap *map = hm_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + for (size_t i = 1; i <= 100; i++) + cmc_assert(hm_insert(map, i, i)); + + size_t key; + size_t val; + cmc_assert(hm_max(map, &key, &val)); + + cmc_assert_equals(size_t, 100, key); + cmc_assert_equals(size_t, 100, val); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(max[count = 0], { + hashmap *map = hm_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + cmc_assert(!hm_min(map, NULL, NULL)); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(min, { + hashmap *map = hm_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + for (size_t i = 1; i <= 100; i++) + cmc_assert(hm_insert(map, i, i)); + + size_t key; + size_t val; + cmc_assert(hm_min(map, &key, &val)); + + cmc_assert_equals(size_t, 1, key); + cmc_assert_equals(size_t, 1, val); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(min[count = 0], { + hashmap *map = hm_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + cmc_assert(!hm_min(map, NULL, NULL)); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(get, { + hashmap *map = hm_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + cmc_assert(hm_insert(map, 4321, 1234)); + + cmc_assert_equals(size_t, 1234, hm_get(map, 4321)); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(get[count = 0], { + hashmap *map = hm_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + cmc_assert_equals(size_t, (size_t){0}, hm_get(map, 4321)); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(get_ref, { + hashmap *map = hm_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + cmc_assert(hm_insert(map, 4321, 1234)); + + size_t *result = hm_get_ref(map, 4321); + + cmc_assert_not_equals(ptr, NULL, result); + cmc_assert_equals(size_t, 1234, *result); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(get_ref[count = 0], { + hashmap *map = hm_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + cmc_assert_equals(ptr, NULL, hm_get_ref(map, 4321)); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(contains, { + hashmap *map = hm_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + cmc_assert(hm_insert(map, 987654321, 1)); + + cmc_assert(hm_contains(map, 987654321)); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(contains[count = 0], { + hashmap *map = hm_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + cmc_assert(!hm_contains(map, 987654321)); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(contains[sum], { + hashmap *map = hm_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + for (size_t i = 101; i <= 200; i++) + cmc_assert(hm_insert(map, i, i)); + + size_t sum = 0; + for (size_t i = 1; i <= 300; i++) + if (hm_contains(map, i)) + sum += i; + + cmc_assert_equals(size_t, 15050, sum); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(empty, { + hashmap *map = hm_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + cmc_assert(hm_empty(map)); + + cmc_assert(hm_insert(map, 1, 1)); + + cmc_assert(!hm_empty(map)); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(full, { + hashmap *map = hm_new(cmc_hashtable_primes[0], 0.99999, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + cmc_assert_equals(size_t, cmc_hashtable_primes[0], hm_capacity(map)); + + for (size_t i = 0; i < hm_capacity(map); i++) + cmc_assert(hm_insert(map, i, i)); + + cmc_assert(hm_full(map)); + + cmc_assert(hm_insert(map, 10000, 10000)); + + cmc_assert_equals(size_t, cmc_hashtable_primes[1], hm_capacity(map)); + + cmc_assert(!hm_full(map)); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(count, { + hashmap *map = hm_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + for (size_t i = 1; i < 100; i++) + { + cmc_assert(hm_insert(map, i, i)); + cmc_assert_equals(size_t, i, hm_count(map)); + } + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(capacity, { + hashmap *map = hm_new(2500, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + cmc_assert_greater_equals(size_t, (size_t)(2500 / 0.6), hm_capacity(map)); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(capacity[small], { + hashmap *map = hm_new(1, 0.99, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + cmc_assert_equals(size_t, cmc_hashtable_primes[0], hm_capacity(map)); + + hm_free(map, NULL); + }); + + CMC_CREATE_TEST(load, { + hashmap *map = hm_new(1, 0.99, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + cmc_assert_in_range(double, 0.99 - 0.0001, 0.99 + 0.0001, hm_load(map)); + + hm_free(map, NULL); + }); }); diff --git a/tests/codecov/unt/hashset.c b/tests/codecov/unt/hashset.c index 5cbe83f..ad8e464 100644 --- a/tests/codecov/unt/hashset.c +++ b/tests/codecov/unt/hashset.c @@ -1,8 +1,9 @@ -#include "utl/assert.h" -#include "utl/test.h" -#include "../src/hashset.c" - #include "utl.c" +#include +#include +#include + +#include "../src/hashset.c" CMC_CREATE_UNIT(hashset_test, false, { CMC_CREATE_TEST(new, { @@ -13,17 +14,17 @@ CMC_CREATE_UNIT(hashset_test, false, { cmc_assert_equals(size_t, 0, hs_count(set)); cmc_assert_greater_equals(size_t, (943722 / 0.6), hs_capacity(set)); - hs_free(set); + hs_free(set, NULL); }); - CMC_CREATE_TEST(new[edge_case:capacity = 0], { + CMC_CREATE_TEST(new[capacity = 0], { hashset *set = hs_new(0, 0.6, cmp, hash); cmc_assert_equals(ptr, NULL, set); }); - CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], { - hashset *set = hs_new(UINT64_MAX, 0.6, cmp, hash); + CMC_CREATE_TEST(new[capacity = UINT64_MAX], { + hashset *set = hs_new(UINT64_MAX, 0.99, cmp, hash); cmc_assert_equals(ptr, NULL, set); }); @@ -38,11 +39,320 @@ CMC_CREATE_UNIT(hashset_test, false, { cmc_assert_equals(size_t, 50, hs_count(set)); - hs_clear(set); + hs_clear(set, NULL); cmc_assert_equals(size_t, 0, hs_count(set)); - hs_free(set); + hs_free(set, NULL); }); + CMC_CREATE_TEST(insert, { + hashset *set = hs_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, set); + + cmc_assert(hs_insert(set, 1)); + cmc_assert_equals(size_t, 1, hs_count(set)); + + hs_free(set, NULL); + }); + + CMC_CREATE_TEST(insert[smallest capacity], { + hashset *set = hs_new(1, 0.99, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, set); + + cmc_assert_equals(size_t, cmc_hashtable_primes[0], hs_capacity(set)); + cmc_assert(hs_insert(set, 1)); + + hs_free(set, NULL); + }); + + CMC_CREATE_TEST(insert[element position], { + // Using the numhash the key is the hash itself + hashset *set = hs_new(1, 0.99, cmp, numhash); + + cmc_assert_not_equals(ptr, NULL, set); + + size_t capacity = hs_capacity(set); + + cmc_assert_greater(size_t, 0, capacity); + + cmc_assert(hs_insert(set, capacity - 1)); + cmc_assert(hs_insert(set, capacity)); + + cmc_assert_equals(size_t, capacity - 1, set->buffer[capacity - 1].value); + cmc_assert_equals(size_t, capacity, set->buffer[0].value); + + hs_free(set, NULL); + }); + + CMC_CREATE_TEST(insert[distance], { + hashset *set = hs_new(500, 0.6, cmp, hash0); + + cmc_assert_not_equals(ptr, NULL, set); + + for (size_t i = 0; i < 200; i++) + cmc_assert(hs_insert(set, i)); + + // Everything is hashed to 0 so key 0 should have dist 0, key 1 dist 1, etc + for (size_t i = 0; i < 200; i++) + cmc_assert_equals(size_t, i, set->buffer[i].dist); + + hs_free(set, NULL); + }); + + CMC_CREATE_TEST(insert[distance wrap], { + hashset *set = hs_new(1, 0.99, cmp, hashcapminus1); + + cmc_assert_not_equals(ptr, NULL, set); + + size_t capacity = hs_capacity(set); + + // Just to be sure, not part of the test + cmc_assert_equals(size_t, cmc_hashtable_primes[0] - 1, hashcapminus1(0)); + cmc_assert_equals(size_t, capacity - 1, hashcapminus1(0)); + + cmc_assert(hs_insert(set, 0)); + cmc_assert(hs_insert(set, 1)); + + cmc_assert_equals(size_t, 0, set->buffer[capacity - 1].dist); + cmc_assert_equals(size_t, 1, set->buffer[0].dist); + + hs_free(set, NULL); + }); + + CMC_CREATE_TEST(insert[buffer growth and item preservation], { + hashset *set = hs_new(1, 0.99, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, set); + + cmc_assert_equals(size_t, cmc_hashtable_primes[0], hs_capacity(set)); + + size_t p = 0; + for (size_t i = 0; i < 100000; i++) + { + if (hs_full(set)) + p++; + + cmc_assert(hs_insert(set, i)); + } + + cmc_assert_equals(size_t, cmc_hashtable_primes[p], hs_capacity(set)); + + for (size_t i = 0; i < 100000; i++) + cmc_assert(hs_contains(set, i)); + + hs_free(set, NULL); + }); + + CMC_CREATE_TEST(remove, { + hashset *set = hs_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, set); + + for (size_t i = 0; i < 100; i++) + cmc_assert(hs_insert(set, i)); + + for (size_t i = 0; i < 100; i++) + cmc_assert(hs_remove(set, i)); + + hs_free(set, NULL); + }); + + CMC_CREATE_TEST(remove[count = 0], { + hashset *set = hs_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, set); + + for (size_t i = 100; i < 200; i++) + cmc_assert(!hs_remove(set, i)); + + hs_free(set, NULL); + }); + + CMC_CREATE_TEST(remove[key not found], { + hashset *set = hs_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, set); + + for (size_t i = 0; i < 100; i++) + cmc_assert(hs_insert(set, i)); + + for (size_t i = 100; i < 200; i++) + cmc_assert(!hs_remove(set, i)); + + hs_free(set, NULL); + }); + + CMC_CREATE_TEST(max, { + hashset *set = hs_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, set); + + for (size_t i = 1; i <= 100; i++) + cmc_assert(hs_insert(set, i)); + + size_t val; + cmc_assert(hs_max(set, &val)); + + cmc_assert_equals(size_t, 100, val); + + hs_free(set, NULL); + }); + + CMC_CREATE_TEST(max[count = 0], { + hashset *set = hs_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, set); + + cmc_assert(!hs_min(set, NULL)); + + hs_free(set, NULL); + }); + + CMC_CREATE_TEST(min, { + hashset *set = hs_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, set); + + for (size_t i = 1; i <= 100; i++) + cmc_assert(hs_insert(set, i)); + + size_t val; + cmc_assert(hs_min(set, &val)); + + cmc_assert_equals(size_t, 1, val); + + hs_free(set, NULL); + }); + + CMC_CREATE_TEST(min[count = 0], { + hashset *set = hs_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, set); + + cmc_assert(!hs_min(set, NULL)); + + hs_free(set, NULL); + }); + + CMC_CREATE_TEST(contains, { + hashset *set = hs_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, set); + + cmc_assert(hs_insert(set, 987654321)); + + cmc_assert(hs_contains(set, 987654321)); + + hs_free(set, NULL); + }); + + CMC_CREATE_TEST(contains[count = 0], { + hashset *set = hs_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, set); + + cmc_assert(!hs_contains(set, 987654321)); + + hs_free(set, NULL); + }); + + CMC_CREATE_TEST(contains[sum], { + hashset *set = hs_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, set); + + for (size_t i = 101; i <= 200; i++) + cmc_assert(hs_insert(set, i)); + + size_t sum = 0; + for (size_t i = 1; i <= 300; i++) + if (hs_contains(set, i)) + sum += i; + + cmc_assert_equals(size_t, 15050, sum); + + hs_free(set, NULL); + }); + + CMC_CREATE_TEST(empty, { + hashset *set = hs_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, set); + + cmc_assert(hs_empty(set)); + + cmc_assert(hs_insert(set, 1)); + + cmc_assert(!hs_empty(set)); + + hs_free(set, NULL); + }); + + CMC_CREATE_TEST(full, { + hashset *set = hs_new(cmc_hashtable_primes[0], 0.99999, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, set); + + cmc_assert_equals(size_t, cmc_hashtable_primes[0], hs_capacity(set)); + + for (size_t i = 0; i < hs_capacity(set); i++) + cmc_assert(hs_insert(set, i)); + + cmc_assert(hs_full(set)); + + cmc_assert(hs_insert(set, 10000)); + + cmc_assert_equals(size_t, cmc_hashtable_primes[1], hs_capacity(set)); + + cmc_assert(!hs_full(set)); + + hs_free(set, NULL); + }); + + CMC_CREATE_TEST(count, { + hashset *set = hs_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, set); + + for (size_t i = 1; i < 100; i++) + { + cmc_assert(hs_insert(set, i)); + cmc_assert_equals(size_t, i, hs_count(set)); + } + + hs_free(set, NULL); + }); + + CMC_CREATE_TEST(capacity, { + hashset *set = hs_new(2500, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, set); + + cmc_assert_greater_equals(size_t, (size_t)(2500 / 0.6), hs_capacity(set)); + + hs_free(set, NULL); + }); + + CMC_CREATE_TEST(capacity[small], { + hashset *set = hs_new(1, 0.99, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, set); + + cmc_assert_equals(size_t, cmc_hashtable_primes[0], hs_capacity(set)); + + hs_free(set, NULL); + }); + + CMC_CREATE_TEST(load, { + hashset *set = hs_new(1, 0.99, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, set); + + cmc_assert_in_range(double, 0.99 - 0.0001, 0.99 + 0.0001, hs_load(set)); + + hs_free(set, NULL); + }); }); diff --git a/tests/codecov/unt/heap.c b/tests/codecov/unt/heap.c index d02747b..936c231 100644 --- a/tests/codecov/unt/heap.c +++ b/tests/codecov/unt/heap.c @@ -1,8 +1,9 @@ -#include "utl/assert.h" -#include "utl/test.h" -#include "../src/heap.c" - #include "utl.c" +#include +#include +#include + +#include "../src/heap.c" CMC_CREATE_UNIT(heap_test, false, { CMC_CREATE_TEST(new, { @@ -13,16 +14,16 @@ CMC_CREATE_UNIT(heap_test, false, { cmc_assert_equals(size_t, 1000000, h_capacity(h)); cmc_assert_equals(size_t, 0, h_count(h)); - h_free(h); + h_free(h, NULL); }); - CMC_CREATE_TEST(new[edge_case:capacity = 0], { + CMC_CREATE_TEST(new[edge_case capacity = 0], { heap *h = h_new(0, cmc_max_heap, cmp); cmc_assert_equals(ptr, NULL, h); }); - CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], { + CMC_CREATE_TEST(new[edge_case capacity = UINT64_MAX], { heap *h = h_new(UINT64_MAX, cmc_max_heap, cmp); cmc_assert_equals(ptr, NULL, h); @@ -38,25 +39,124 @@ CMC_CREATE_UNIT(heap_test, false, { cmc_assert_equals(size_t, 50, h_count(h)); - h_clear(h); + h_clear(h, NULL); cmc_assert_equals(size_t, 0, h_count(h)); cmc_assert_equals(size_t, 100, h_capacity(h)); - h_free(h); + h_free(h, NULL); }); - CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], { + CMC_CREATE_TEST(buffer_growth[edge_case capacity = 1], { heap *h = h_new(1, cmc_max_heap, cmp); cmc_assert_not_equals(ptr, NULL, h); for (size_t i = 0; i < 50; i++) - h_insert(h, i); + cmc_assert(h_insert(h, i)); cmc_assert_equals(size_t, 50, h_count(h)); - h_free(h); + h_free(h, NULL); }); + CMC_CREATE_TEST(insert, { + heap *h = h_new(100, cmc_max_heap, cmp); + + cmc_assert_not_equals(ptr, NULL, h); + + cmc_assert(h_insert(h, 10)); + + h_free(h, NULL); + }); + + CMC_CREATE_TEST(insert[item preservation], { + heap *h = h_new(50, cmc_max_heap, cmp); + + cmc_assert_not_equals(ptr, NULL, h); + + for (size_t i = 0; i <= 100; i++) + cmc_assert(h_insert(h, i)); + + size_t sum = 0; + for (size_t i = 0; i < h_count(h); i++) + sum += h->buffer[i]; + + cmc_assert_equals(size_t, 5050, sum); + + h_free(h, NULL); + }); + + CMC_CREATE_TEST(remove, { + heap *h = h_new(50, cmc_max_heap, cmp); + + cmc_assert_not_equals(ptr, NULL, h); + + for (size_t i = 0; i <= 100; i++) + cmc_assert(h_insert(h, i)); + + size_t r; + cmc_assert(h_remove(h, &r)); + + cmc_assert_equals(size_t, 100, r); + + h_free(h, NULL); + }); + + CMC_CREATE_TEST(remove[count = 0], { + heap *h = h_new(100, cmc_max_heap, cmp); + + cmc_assert_not_equals(ptr, NULL, h); + + size_t _; + cmc_assert(!h_remove(h, &_)); + + h_free(h, NULL); + }); + + CMC_CREATE_TEST(remove[sorted], { + heap *h = h_new(100, cmc_min_heap, cmp); + + cmc_assert_not_equals(ptr, NULL, h); + + for (size_t i = 1; i <= 100; i++) + cmc_assert(h_insert(h, i)); + + size_t r; + size_t i = 0; + size_t arr[100]; + while (!h_empty(h)) + { + cmc_assert(h_remove(h, &r)); + + arr[i++] = r; + } + + cmc_assert_array_sorted_any(size_t, arr, cmp, 0, 99); + + h_free(h, NULL); + }); + + CMC_CREATE_TEST(peek, { + heap *h = h_new(100, cmc_max_heap, cmp); + + cmc_assert_not_equals(ptr, NULL, h); + + for (size_t i = 1; i <= 100; i++) + cmc_assert(h_insert(h, i)); + + cmc_assert_equals(size_t, 100, h_peek(h)); + + h_free(h, NULL); + }); + + CMC_CREATE_TEST(peek[count = 0], { + heap *h = h_new(100, cmc_max_heap, cmp); + + cmc_assert_not_equals(ptr, NULL, h); + + cmc_assert_equals(size_t, (size_t){0}, h_peek(h)); + + h_free(h, NULL); + }); }); diff --git a/tests/codecov/unt/intervalheap.c b/tests/codecov/unt/intervalheap.c new file mode 100644 index 0000000..b5b3a25 --- /dev/null +++ b/tests/codecov/unt/intervalheap.c @@ -0,0 +1,132 @@ +#include "utl.c" +#include +#include +#include + +#include "../src/intervalheap.c" + +CMC_CREATE_UNIT(intervalheap_test, false, { + CMC_CREATE_TEST(new, { + intervalheap *ih = ih_new(1000000, cmp); + + cmc_assert_not_equals(ptr, NULL, ih); + cmc_assert_not_equals(ptr, NULL, ih->buffer); + cmc_assert_equals(size_t, 500000, ih_capacity(ih)); + cmc_assert_equals(size_t, 0, ih_count(ih)); + + ih_free(ih, NULL); + }); + + CMC_CREATE_TEST(new[capacity = 0], { + intervalheap *ih = ih_new(0, cmp); + + cmc_assert_equals(ptr, NULL, ih); + + if (ih) + ih_free(ih, NULL); + }); + + CMC_CREATE_TEST(new[capacity], { + intervalheap *ih = ih_new(1, cmp); + + cmc_assert_not_equals(ptr, NULL, ih); + cmc_assert_equals(size_t, 1, ih_capacity(ih)); + + ih_free(ih, NULL); + + ih = ih_new(2, cmp); + + cmc_assert_not_equals(ptr, NULL, ih); + cmc_assert_equals(size_t, 1, ih_capacity(ih)); + + ih_free(ih, NULL); + + ih = ih_new(3, cmp); + + cmc_assert_not_equals(ptr, NULL, ih); + cmc_assert_equals(size_t, 2, ih_capacity(ih)); + + ih_free(ih, NULL); + + ih = ih_new(4, cmp); + + cmc_assert_not_equals(ptr, NULL, ih); + cmc_assert_equals(size_t, 2, ih_capacity(ih)); + + ih_free(ih, NULL); + }); + + CMC_CREATE_TEST(new[capacity = UINT64_MAX], { + intervalheap *ih = ih_new(UINT64_MAX, cmp); + + cmc_assert_equals(ptr, NULL, ih); + + if (ih) + ih_free(ih, NULL); + }); + + CMC_CREATE_TEST(clear[count capacity], { + intervalheap *ih = ih_new(100, cmp); + + cmc_assert_not_equals(ptr, NULL, ih); + + for (size_t i = 0; i < 50; i++) + cmc_assert(ih_insert(ih, i)); + + cmc_assert_equals(size_t, 50, ih_count(ih)); + + ih_clear(ih, NULL); + + cmc_assert_equals(size_t, 0, ih_count(ih)); + cmc_assert_equals(size_t, 50, ih_capacity(ih)); + + ih_free(ih, NULL); + }); + + CMC_CREATE_TEST(buffer_growth[capacity = 1], { + intervalheap *ih = ih_new(1, cmp); + + cmc_assert_not_equals(ptr, NULL, ih); + + for (size_t i = 0; i < 50; i++) + cmc_assert(ih_insert(ih, i)); + + cmc_assert_equals(size_t, 50, ih_count(ih)); + cmc_assert_greater(size_t, 50, ih_capacity(ih) * 2); + + ih_free(ih, NULL); + }); + + CMC_CREATE_TEST(insert[count], { + intervalheap *ih = ih_new(100, cmp); + + cmc_assert_not_equals(ptr, NULL, ih); + + cmc_assert(ih_insert(ih, 1)); + cmc_assert(ih_insert(ih, 0)); + + cmc_assert_equals(size_t, 2, ih_count(ih)); + + ih_free(ih, NULL); + }); + + CMC_CREATE_TEST(insert[max min], { + intervalheap *ih = ih_new(1, cmp); + + cmc_assert_not_equals(ptr, NULL, ih); + + cmc_assert(ih_insert(ih, 1)); + cmc_assert(ih_insert(ih, 0)); + + size_t min; + size_t max; + + cmc_assert(ih_min(ih, &min)); + cmc_assert(ih_max(ih, &max)); + + cmc_assert_equals(size_t, 0, min); + cmc_assert_equals(size_t, 1, max); + + ih_free(ih, NULL); + }); +}); diff --git a/tests/codecov/unt/linkedlist.c b/tests/codecov/unt/linkedlist.c index 84ca867..827e657 100644 --- a/tests/codecov/unt/linkedlist.c +++ b/tests/codecov/unt/linkedlist.c @@ -1,5 +1,8 @@ -#include "utl/assert.h" -#include "utl/test.h" +#include "utl.c" +#include +#include +#include + #include "../src/linkedlist.c" CMC_CREATE_UNIT(linkedlist_test, false, { @@ -11,7 +14,7 @@ CMC_CREATE_UNIT(linkedlist_test, false, { cmc_assert_equals(ptr, NULL, ll->head); cmc_assert_equals(ptr, NULL, ll->tail); - ll_free(ll); + ll_free(ll, NULL); }); CMC_CREATE_TEST(clear[count capacity], { @@ -24,23 +27,23 @@ CMC_CREATE_UNIT(linkedlist_test, false, { cmc_assert_equals(size_t, 50, ll_count(ll)); - ll_clear(ll); + ll_clear(ll, NULL); cmc_assert_equals(size_t, 0, ll_count(ll)); - ll_free(ll); + ll_free(ll, NULL); }); - CMC_CREATE_TEST(clear[edge_case:count = 0], { + CMC_CREATE_TEST(clear[count = 0], { linkedlist *ll = ll_new(); cmc_assert_not_equals(ptr, NULL, ll); - ll_clear(ll); + ll_clear(ll, NULL); cmc_assert_equals(size_t, 0, ll_count(ll)); - ll_free(ll); + ll_free(ll, NULL); }); CMC_CREATE_TEST(push_front[count], { @@ -54,10 +57,10 @@ CMC_CREATE_UNIT(linkedlist_test, false, { cmc_assert_not_equals(ptr, NULL, ll->tail); cmc_assert_equals(size_t, 1, ll_count(ll)); - ll_free(ll); + ll_free(ll, NULL); }); - CMC_CREATE_TEST(push_front[item_preservation], { + CMC_CREATE_TEST(push_front[item preservation], { linkedlist *ll = ll_new(); cmc_assert_not_equals(ptr, NULL, ll); @@ -68,7 +71,6 @@ CMC_CREATE_UNIT(linkedlist_test, false, { for (size_t i = 0; i < ll_count(ll); i++) cmc_assert_equals(size_t, ll_get(ll, i), ll_count(ll) - i - 1); - ll_free(ll); + ll_free(ll, NULL); }); - }); diff --git a/tests/codecov/unt/list.c b/tests/codecov/unt/list.c index c3f81d1..b1c297c 100644 --- a/tests/codecov/unt/list.c +++ b/tests/codecov/unt/list.c @@ -1,5 +1,8 @@ -#include "utl/assert.h" -#include "utl/test.h" +#include "utl.c" +#include +#include +#include + #include "../src/list.c" CMC_CREATE_UNIT(list_test, false, { @@ -11,22 +14,22 @@ CMC_CREATE_UNIT(list_test, false, { cmc_assert_equals(size_t, 1000000, l_capacity(l)); cmc_assert_equals(size_t, 0, l_count(l)); - l_free(l); + l_free(l, NULL); }); - CMC_CREATE_TEST(new[edge_case:capacity = 0], { + CMC_CREATE_TEST(new[capacity = 0], { list *l = l_new(0); cmc_assert_equals(ptr, NULL, l); }); - CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], { + CMC_CREATE_TEST(new[capacity = UINT64_MAX], { list *l = l_new(UINT64_MAX); cmc_assert_equals(ptr, NULL, l); }); - CMC_CREATE_TEST(new_from[count item_preservation], { + CMC_CREATE_TEST(new_from[count and item preservation], { size_t v[5]; for (size_t i = 0; i < 5; i++) @@ -41,10 +44,10 @@ CMC_CREATE_UNIT(list_test, false, { for (size_t i = 0; i < 5; i++) cmc_assert_equals(size_t, i, l_get(l, i)); - l_free(l); + l_free(l, NULL); }); - CMC_CREATE_TEST(new_from[edge_case:size = 1], { + CMC_CREATE_TEST(new_from[size = 1], { size_t a = 10; size_t *values = &a; @@ -53,7 +56,7 @@ CMC_CREATE_UNIT(list_test, false, { cmc_assert_not_equals(ptr, NULL, l); - l_free(l); + l_free(l, NULL); }); CMC_CREATE_TEST(clear[count capacity], { @@ -66,15 +69,15 @@ CMC_CREATE_UNIT(list_test, false, { cmc_assert_equals(size_t, 50, l_count(l)); - l_clear(l); + l_clear(l, NULL); cmc_assert_equals(size_t, 0, l_count(l)); cmc_assert_equals(size_t, 100, l_capacity(l)); - l_free(l); + l_free(l, NULL); }); - CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], { + CMC_CREATE_TEST(buffer_growth[capacity = 1], { list *l = l_new(1); cmc_assert_not_equals(ptr, NULL, l); @@ -87,7 +90,7 @@ CMC_CREATE_UNIT(list_test, false, { for (size_t i = 0; i < 100; i++) cmc_assert_equals(size_t, i, l_get(l, i)); - l_free(l); + l_free(l, NULL); }); CMC_CREATE_TEST(push_front[count], { @@ -100,7 +103,7 @@ CMC_CREATE_UNIT(list_test, false, { cmc_assert_equals(size_t, 250, l_count(l)); - l_free(l); + l_free(l, NULL); }); CMC_CREATE_TEST(push_front[capacity], { @@ -113,10 +116,10 @@ CMC_CREATE_UNIT(list_test, false, { cmc_assert_lesser_equals(size_t, l_capacity(l), l_count(l)); - l_free(l); + l_free(l, NULL); }); - CMC_CREATE_TEST(push_front[item_preservation], { + CMC_CREATE_TEST(push_front[item preservation], { list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); @@ -127,10 +130,10 @@ CMC_CREATE_UNIT(list_test, false, { for (size_t i = 0; i < l_count(l); i++) cmc_assert_equals(size_t, l_get(l, i), l_count(l) - i - 1); - l_free(l); + l_free(l, NULL); }); - CMC_CREATE_TEST(push[count], { + CMC_CREATE_TEST(push_at[count], { list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); @@ -139,14 +142,14 @@ CMC_CREATE_UNIT(list_test, false, { cmc_assert(l_push_back(l, 249)); for (size_t i = 1; i < 249; i++) - cmc_assert(l_push(l, i, l_count(l) - 1)); + cmc_assert(l_push_at(l, i, l_count(l) - 1)); cmc_assert_equals(size_t, 250, l_count(l)); - l_free(l); + l_free(l, NULL); }); - CMC_CREATE_TEST(push[capacity], { + CMC_CREATE_TEST(push_at[capacity], { list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); @@ -155,14 +158,14 @@ CMC_CREATE_UNIT(list_test, false, { cmc_assert(l_push_back(l, 249)); for (size_t i = 1; i < 249; i++) - cmc_assert(l_push(l, i, l_count(l) - 1)); + cmc_assert(l_push_at(l, i, l_count(l) - 1)); cmc_assert_lesser_equals(size_t, l_capacity(l), l_count(l)); - l_free(l); + l_free(l, NULL); }); - CMC_CREATE_TEST(push[item_preservation], { + CMC_CREATE_TEST(push_at[item preservation], { list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); @@ -171,12 +174,12 @@ CMC_CREATE_UNIT(list_test, false, { cmc_assert(l_push_back(l, 249)); for (size_t i = 1; i < 249; i++) - cmc_assert(l_push(l, i, l_count(l) - 1)); + cmc_assert(l_push_at(l, i, l_count(l) - 1)); for (size_t i = 0; i < l_count(l); i++) cmc_assert_equals(size_t, l_get(l, i), i); - l_free(l); + l_free(l, NULL); }); CMC_CREATE_TEST(push_back[count], { @@ -189,7 +192,7 @@ CMC_CREATE_UNIT(list_test, false, { cmc_assert_equals(size_t, 250, l_count(l)); - l_free(l); + l_free(l, NULL); }); CMC_CREATE_TEST(push_back[capacity], { @@ -202,10 +205,10 @@ CMC_CREATE_UNIT(list_test, false, { cmc_assert_lesser_equals(size_t, l_capacity(l), l_count(l)); - l_free(l); + l_free(l, NULL); }); - CMC_CREATE_TEST(push_back[item_preservation], { + CMC_CREATE_TEST(push_back[item preservation], { list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); @@ -216,7 +219,7 @@ CMC_CREATE_UNIT(list_test, false, { for (size_t i = 0; i < l_count(l); i++) cmc_assert_equals(size_t, l_get(l, i), i); - l_free(l); + l_free(l, NULL); }); CMC_CREATE_TEST(pop_front[count], { @@ -229,10 +232,10 @@ CMC_CREATE_UNIT(list_test, false, { cmc_assert(l_pop_front(l)); - l_free(l); + l_free(l, NULL); }); - CMC_CREATE_TEST(pop_front[item_preservation], { + CMC_CREATE_TEST(pop_front[item preservation], { list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); @@ -245,26 +248,26 @@ CMC_CREATE_UNIT(list_test, false, { for (size_t i = 0; i < l_count(l); i++) cmc_assert_equals(size_t, l_get(l, i), i + 1); - l_free(l); + l_free(l, NULL); }); - CMC_CREATE_TEST(pop_front[edge_case:count = 0], { + CMC_CREATE_TEST(pop_front[count = 0], { list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); cmc_assert(!l_pop_front(l)); - l_free(l); + l_free(l, NULL); }); - CMC_CREATE_TEST(pop_front[edge_case:count = 1], { + CMC_CREATE_TEST(pop_front[count = 1], { list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); cmc_assert(l_push_back(l, 10)); cmc_assert(l_pop_front(l)); - l_free(l); + l_free(l, NULL); }); CMC_CREATE_TEST(pop_front[buffer_clear], { @@ -278,58 +281,58 @@ CMC_CREATE_UNIT(list_test, false, { cmc_assert_equals(size_t, 0, l->buffer[1]); - l_free(l); + l_free(l, NULL); }); - CMC_CREATE_TEST(pop[edge_case:count = 0], { + CMC_CREATE_TEST(pop_at[count = 0], { list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); - cmc_assert(!l_pop(l, 1)); + cmc_assert(!l_pop_at(l, 1)); - l_free(l); + l_free(l, NULL); }); - CMC_CREATE_TEST(pop[edge_case:count = 1], { + CMC_CREATE_TEST(pop_at[count = 1], { list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); cmc_assert(l_push_back(l, 1)); - cmc_assert(l_pop(l, 0)); + cmc_assert(l_pop_at(l, 0)); cmc_assert_equals(size_t, 0, l->buffer[0]); - l_free(l); + l_free(l, NULL); }); - CMC_CREATE_TEST(pop[buffer_clear], { + CMC_CREATE_TEST(pop_at[buffer_clear], { list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); cmc_assert(l_push_back(l, 1)); cmc_assert(l_push_back(l, 2)); cmc_assert(l_push_back(l, 3)); - cmc_assert(l_pop(l, 1)); + cmc_assert(l_pop_at(l, 1)); - l_free(l); + l_free(l, NULL); }); - CMC_CREATE_TEST(pop_back[edge_case:count = 0], { + CMC_CREATE_TEST(pop_back[count = 0], { list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); cmc_assert(!l_pop_back(l)); - l_free(l); + l_free(l, NULL); }); - CMC_CREATE_TEST(pop_back[edge_case:count = 1], { + CMC_CREATE_TEST(pop_back[count = 1], { list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); cmc_assert(l_push_back(l, 10)); cmc_assert(l_pop_back(l)); - l_free(l); + l_free(l, NULL); }); }) diff --git a/tests/codecov/unt/multimap.c b/tests/codecov/unt/multimap.c index 899548b..edfe926 100644 --- a/tests/codecov/unt/multimap.c +++ b/tests/codecov/unt/multimap.c @@ -1,8 +1,9 @@ -#include "utl/assert.h" -#include "utl/test.h" -#include "../src/multimap.c" - #include "utl.c" +#include +#include +#include + +#include "../src/multimap.c" CMC_CREATE_UNIT(multimap_test, false, { CMC_CREATE_TEST(new, { @@ -13,17 +14,17 @@ CMC_CREATE_UNIT(multimap_test, false, { cmc_assert_equals(size_t, 0, mm_count(map)); cmc_assert_greater_equals(size_t, (943722 / 0.8), mm_capacity(map)); - mm_free(map); + mm_free(map, NULL); }); - CMC_CREATE_TEST(new[edge_case:capacity = 0], { + CMC_CREATE_TEST(new[capacity = 0], { multimap *map = mm_new(0, 0.8, cmp, hash); cmc_assert_equals(ptr, NULL, map); }); - CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], { - multimap *map = mm_new(UINT64_MAX, 0.8, cmp, hash); + CMC_CREATE_TEST(new[capacity = UINT64_MAX], { + multimap *map = mm_new(UINT64_MAX, 0.99, cmp, hash); cmc_assert_equals(ptr, NULL, map); }); @@ -38,11 +39,11 @@ CMC_CREATE_UNIT(multimap_test, false, { cmc_assert_equals(size_t, 50, mm_count(map)); - mm_clear(map); + mm_clear(map, NULL); cmc_assert_equals(size_t, 0, mm_count(map)); - mm_free(map); + mm_free(map, NULL); }); CMC_CREATE_TEST(insert[count], { @@ -50,12 +51,12 @@ CMC_CREATE_UNIT(multimap_test, false, { cmc_assert_not_equals(ptr, NULL, map); - for (size_t i = 0; i < 200; i++) + for (size_t i = 0; i < 100; i++) cmc_assert(mm_insert(map, i % 20, i % 20)); - cmc_assert_equals(size_t, 200, mm_count(map)); + cmc_assert_equals(size_t, 100, mm_count(map)); - mm_free(map); + mm_free(map, NULL); }); CMC_CREATE_TEST(remove[count], { @@ -73,10 +74,10 @@ CMC_CREATE_UNIT(multimap_test, false, { cmc_assert_equals(size_t, 140, mm_count(map)); - mm_free(map); + mm_free(map, NULL); }); - CMC_CREATE_TEST(remove[edge_case:count = 0], { + CMC_CREATE_TEST(remove[count = 0], { multimap *map = mm_new(100, 0.8, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -85,10 +86,10 @@ CMC_CREATE_UNIT(multimap_test, false, { cmc_assert(!mm_remove(map, 10, &r)); - mm_free(map); + mm_free(map, NULL); }); - CMC_CREATE_TEST(remove[edge_case:count = 1], { + CMC_CREATE_TEST(remove[count = 1], { multimap *map = mm_new(100, 0.8, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -98,41 +99,10 @@ CMC_CREATE_UNIT(multimap_test, false, { cmc_assert(mm_insert(map, 10, 11)); cmc_assert(mm_remove(map, 10, &r)); - mm_free(map); + mm_free(map, NULL); }); - CMC_CREATE_TEST(insert_if, { - multimap *map = mm_new(100, 0.8, cmp, hash); - - cmc_assert_not_equals(ptr, NULL, map); - - for (size_t i = 1; i <= 100; i++) - cmc_assert(mm_insert_if(map, i % 20, i, i % 2 == 0) || i % 2 != 0); - - cmc_assert_equals(size_t, 50, mm_count(map)); - - mm_free(map); - }); - - CMC_CREATE_TEST(remove_if, { - multimap *map = mm_new(100, 0.8, cmp, hash); - - cmc_assert_not_equals(ptr, NULL, map); - - for (size_t i = 1; i <= 100; i++) - cmc_assert(mm_insert(map, i % 20, i)); - - size_t r; - - for (size_t i = 1; i <= 100; i++) - cmc_assert(mm_remove_if(map, i % 20, &r, i % 2 == 0) || i % 2 != 0); - - cmc_assert_equals(size_t, 50, mm_count(map)); - - mm_free(map); - }); - - CMC_CREATE_TEST(get[key_ordering], { + CMC_CREATE_TEST(get[key ordering], { multimap *map = mm_new(100, 0.8, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -145,7 +115,22 @@ CMC_CREATE_UNIT(multimap_test, false, { cmc_assert_equals(size_t, 100, mm_get(map, 10)); - mm_free(map); + mm_free(map, NULL); }); + CMC_CREATE_TEST(key_count, { + multimap *map = mm_new(50, 0.8, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, map); + + for (size_t i = 0; i < 1000; i++) + cmc_assert(mm_insert(map, i % 20, i % 20)); + + cmc_assert_equals(size_t, 1000, mm_count(map)); + + for (size_t i = 0; i < 20; i++) + cmc_assert_equals(size_t, 50, mm_key_count(map, i)); + + mm_free(map, NULL); + }); }); diff --git a/tests/codecov/unt/multiset.c b/tests/codecov/unt/multiset.c index 6a2a3c4..7e356ff 100644 --- a/tests/codecov/unt/multiset.c +++ b/tests/codecov/unt/multiset.c @@ -1,8 +1,9 @@ -#include "utl/assert.h" -#include "utl/test.h" -#include "../src/multiset.c" - #include "utl.c" +#include +#include +#include + +#include "../src/multiset.c" CMC_CREATE_UNIT(multiset_test, false, { CMC_CREATE_TEST(new, { @@ -13,17 +14,17 @@ CMC_CREATE_UNIT(multiset_test, false, { cmc_assert_equals(size_t, 0, ms_count(set)); cmc_assert_greater_equals(size_t, ((size_t)(943722 / 0.6)), ms_capacity(set)); - ms_free(set); + ms_free(set, NULL); }); - CMC_CREATE_TEST(new[edge_case:capacity = 0], { + CMC_CREATE_TEST(new[capacity = 0], { multiset *set = ms_new(0, 0.6, cmp, hash); cmc_assert_equals(ptr, NULL, set); }); - CMC_CREATE_TEST(new[edge_case:capacity = UINTMAX_MAX], { - multiset *set = ms_new(UINTMAX_MAX, 0.99, cmp, hash); + CMC_CREATE_TEST(new[capacity = UINT64_MAX], { + multiset *set = ms_new(UINT64_MAX, 0.99, cmp, hash); cmc_assert_equals(ptr, NULL, set); }); @@ -38,11 +39,11 @@ CMC_CREATE_UNIT(multiset_test, false, { cmc_assert_equals(size_t, 50, ms_count(set)); - ms_clear(set); + ms_clear(set, NULL); cmc_assert_equals(size_t, 0, ms_count(set)); - ms_free(set); + ms_free(set, NULL); }); CMC_CREATE_TEST(insert[count cardinality multiplicity], { @@ -63,24 +64,88 @@ CMC_CREATE_UNIT(multiset_test, false, { for (size_t i = 0; i <= 3; i++) cmc_assert_equals(size_t, i, ms_multiplicity_of(set, i)); - ms_free(set); + ms_free(set, NULL); }); - CMC_CREATE_TEST(multiplicity, { + CMC_CREATE_TEST(remove[count cardinality multiplicity], { multiset *set = ms_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); - for (size_t i = 0; i < 100; i++) + cmc_assert(ms_insert(set, 1)); + cmc_assert(ms_insert(set, 2)); + cmc_assert(ms_insert(set, 2)); + cmc_assert(ms_insert(set, 3)); + cmc_assert(ms_insert(set, 3)); + cmc_assert(ms_insert(set, 3)); + + cmc_assert_equals(size_t, 3, ms_count(set)); + cmc_assert_equals(size_t, 6, ms_cardinality(set)); + + for (size_t i = 0; i <= 3; i++) + cmc_assert_equals(size_t, i, ms_multiplicity_of(set, i)); + + cmc_assert(ms_remove(set, 1)); + cmc_assert(ms_remove(set, 2)); + cmc_assert(ms_remove(set, 3)); + + cmc_assert_equals(size_t, 2, ms_count(set)); + cmc_assert_equals(size_t, 3, ms_cardinality(set)); + + cmc_assert_equals(size_t, 0, ms_multiplicity_of(set, 0)); + cmc_assert_equals(size_t, 0, ms_multiplicity_of(set, 1)); + cmc_assert_equals(size_t, 1, ms_multiplicity_of(set, 2)); + cmc_assert_equals(size_t, 2, ms_multiplicity_of(set, 3)); + + ms_free(set, NULL); + }); + + CMC_CREATE_TEST(remove_all[count cardinality multiplicity], { + multiset *set = ms_new(100, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, set); + + cmc_assert(ms_insert(set, 1)); + cmc_assert(ms_insert(set, 2)); + cmc_assert(ms_insert(set, 2)); + cmc_assert(ms_insert(set, 3)); + cmc_assert(ms_insert(set, 3)); + cmc_assert(ms_insert(set, 3)); + + cmc_assert_equals(size_t, 3, ms_count(set)); + cmc_assert_equals(size_t, 6, ms_cardinality(set)); + + for (size_t i = 0; i <= 3; i++) + cmc_assert_equals(size_t, i, ms_multiplicity_of(set, i)); + + cmc_assert(ms_remove_all(set, 1)); + cmc_assert(ms_remove_all(set, 3)); + + cmc_assert_equals(size_t, 1, ms_count(set)); + cmc_assert_equals(size_t, 2, ms_cardinality(set)); + + cmc_assert_equals(size_t, 0, ms_multiplicity_of(set, 0)); + cmc_assert_equals(size_t, 0, ms_multiplicity_of(set, 1)); + cmc_assert_equals(size_t, 2, ms_multiplicity_of(set, 2)); + cmc_assert_equals(size_t, 0, ms_multiplicity_of(set, 3)); + + ms_free(set, NULL); + }); + + CMC_CREATE_TEST(multiplicity, { + multiset *set = ms_new(50, 0.6, cmp, hash); + + cmc_assert_not_equals(ptr, NULL, set); + + for (size_t i = 0; i < 1000; i++) cmc_assert(ms_insert(set, i % 20)); cmc_assert_equals(size_t, 20, ms_count(set)); - cmc_assert_equals(size_t, 100, ms_cardinality(set)); + cmc_assert_equals(size_t, 1000, ms_cardinality(set)); for (size_t i = 0; i < 20; i++) - cmc_assert_equals(size_t, 5, ms_multiplicity_of(set, i)); + cmc_assert_equals(size_t, 50, ms_multiplicity_of(set, i)); - ms_free(set); + ms_free(set, NULL); }); - }); diff --git a/tests/codecov/unt/queue.c b/tests/codecov/unt/queue.c index bacebb7..43e07f1 100644 --- a/tests/codecov/unt/queue.c +++ b/tests/codecov/unt/queue.c @@ -1,5 +1,8 @@ -#include "utl/assert.h" -#include "utl/test.h" +#include "utl.c" +#include +#include +#include + #include "../src/queue.c" CMC_CREATE_UNIT(queue_test, false, { @@ -12,16 +15,16 @@ CMC_CREATE_UNIT(queue_test, false, { cmc_assert_equals(size_t, 0, q_count(q)); cmc_assert_not_equals(ptr, NULL, q->buffer); - q_free(q); + q_free(q, NULL); }); - CMC_CREATE_TEST(new[edge_case:capacity = 0], { + CMC_CREATE_TEST(new[capacity = 0], { queue *q = q_new(0); cmc_assert_equals(ptr, NULL, q); }); - CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], { + CMC_CREATE_TEST(new[capacity = UINT64_MAX], { queue *q = q_new(UINT64_MAX); cmc_assert_equals(ptr, NULL, q); @@ -37,15 +40,15 @@ CMC_CREATE_UNIT(queue_test, false, { cmc_assert_equals(size_t, 50, q_count(q)); - q_clear(q); + q_clear(q, NULL); cmc_assert_equals(size_t, 0, q_count(q)); cmc_assert_equals(size_t, 100, q_capacity(q)); - q_free(q); + q_free(q, NULL); }); - CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], { + CMC_CREATE_TEST(buffer_growth[capacity = 1], { queue *q = q_new(1); cmc_assert_not_equals(ptr, NULL, q); @@ -55,7 +58,351 @@ CMC_CREATE_UNIT(queue_test, false, { cmc_assert_equals(size_t, 50, q_count(q)); - q_free(q); + q_free(q, NULL); }); + CMC_CREATE_TEST(buffer_growth[item preservation], { + queue *q = q_new(100); + + cmc_assert_not_equals(ptr, NULL, q); + + for (size_t i = 1; i <= 1200; i++) + { + q_enqueue(q, i); + } + + size_t sum = 0; + for (size_t i = q->front, j = 0; j < q->count; i = (i + 1) % q->capacity, j++) + sum += q->buffer[i]; + + cmc_assert_equals(size_t, 1200, q_count(q)); + cmc_assert_equals(size_t, 720600, sum); + + q_free(q, NULL); + }); + + CMC_CREATE_TEST(enqueue[count capacity], { + queue *q = q_new(100); + + cmc_assert_not_equals(ptr, NULL, q); + + for (size_t i = 0; i < 150; i++) + cmc_assert(q_enqueue(q, i)); + + cmc_assert_equals(size_t, 150, q_count(q)); + cmc_assert_greater(size_t, 100, q_capacity(q)); + + q_free(q, NULL); + }); + + CMC_CREATE_TEST(enqueue[item preservation], { + queue *q = q_new(100); + + cmc_assert_not_equals(ptr, NULL, q); + + for (size_t i = 1; i <= 100; i++) + cmc_assert(q_enqueue(q, i)); + + size_t sum = 0; + + for (size_t i = q->front, j = 0; j < q->count; i = (i + 1) % q->capacity, j++) + { + sum += q->buffer[i]; + } + + cmc_assert_equals(size_t, 5050, sum); + + q_free(q, NULL); + }); + + CMC_CREATE_TEST(dequeue[count capacity], { + queue *q = q_new(100); + + cmc_assert_not_equals(ptr, NULL, q); + + cmc_assert(q_enqueue(q, 10)); + cmc_assert(q_dequeue(q)); + + cmc_assert_equals(size_t, 0, q_count(q)); + + cmc_assert(q_enqueue(q, 10)); + cmc_assert(q_dequeue(q)); + + cmc_assert_equals(size_t, 0, q_count(q)); + + q_free(q, NULL); + }); + + CMC_CREATE_TEST(dequeue[item preservation], { + queue *q = q_new(100); + + cmc_assert_not_equals(ptr, NULL, q); + + for (size_t i = 200; i > 0; i--) + cmc_assert(q_enqueue(q, i)); + + for (size_t i = 0; i < 100; i++) + cmc_assert(q_dequeue(q)); + + size_t sum = 0; + + for (size_t i = q->front, j = 0; j < q->count; i = (i + 1) % q->capacity, j++) + { + sum += q->buffer[i]; + } + + cmc_assert_equals(size_t, 5050, sum); + + q_free(q, NULL); + }); + + CMC_CREATE_TEST(peek[count = 0], { + queue *q = q_new(100); + + cmc_assert_not_equals(ptr, NULL, q); + + size_t r = q_peek(q); + + cmc_assert_equals(size_t, (size_t){0}, r); + + q_free(q, NULL); + }); + + CMC_CREATE_TEST(peek[sum], { + queue *q = q_new(100); + + cmc_assert_not_equals(ptr, NULL, q); + + size_t sum = 0; + + for (size_t i = 0; i <= 100; i++) + cmc_assert(q_enqueue(q, i)); + + while (!q_empty(q)) + { + size_t r = q_peek(q); + + sum += r; + + cmc_assert(q_dequeue(q)); + } + + cmc_assert_equals(size_t, 5050, sum); + + q_free(q, NULL); + }); + + CMC_CREATE_TEST(contains, { + queue *q = q_new(100); + + cmc_assert_not_equals(ptr, NULL, q); + + for (size_t i = 1; i <= 20; i++) + cmc_assert(q_enqueue(q, i)); + + for (size_t i = 1; i <= 20; i++) + cmc_assert(q_contains(q, i, cmp)); + + q_clear(q, NULL); + + for (size_t i = 1; i <= 20; i++) + cmc_assert(!q_contains(q, i, cmp)); + + q_free(q, NULL); + }); + + CMC_CREATE_TEST(contains[count = 0], { + queue *q = q_new(100); + + cmc_assert_not_equals(ptr, NULL, q); + + cmc_assert(!q_contains(q, 10, cmp)); + + q_free(q, NULL); + }); + + CMC_CREATE_TEST(contains[count = 1], { + queue *q = q_new(100); + + cmc_assert_not_equals(ptr, NULL, q); + + cmc_assert(!q_contains(q, 10, cmp)); + + cmc_assert(q_enqueue(q, 100)); + + cmc_assert(q_contains(q, 100, cmp)); + cmc_assert(!q_contains(q, 101, cmp)); + + q_free(q, NULL); + }); + + CMC_CREATE_TEST(empty, { + queue *q = q_new(100); + + cmc_assert_not_equals(ptr, NULL, q); + + cmc_assert(q_empty(q)); + + cmc_assert(q_enqueue(q, 1)); + + cmc_assert(!q_empty(q)); + + q_free(q, NULL); + }); + + CMC_CREATE_TEST(full, { + queue *q = q_new(100); + + cmc_assert_not_equals(ptr, NULL, q); + + cmc_assert(!q_full(q)); + + for (size_t i = 0; i != q_capacity(q); i++) + cmc_assert(q_enqueue(q, i)); + + cmc_assert(q_full(q)); + + q_free(q, NULL); + }); + + CMC_CREATE_TEST(count, { + queue *q = q_new(100); + + cmc_assert_not_equals(ptr, NULL, q); + + cmc_assert_equals(size_t, 0, q_count(q)); + + for (size_t i = 0; i < 100; i++) + cmc_assert(q_enqueue(q, i)); + + cmc_assert_equals(size_t, 100, q_count(q)); + + q_free(q, NULL); + }); + + CMC_CREATE_TEST(capacity, { + queue *q = q_new(100); + + cmc_assert_not_equals(ptr, NULL, q); + + cmc_assert_equals(size_t, 100, q_capacity(q)); + + q_free(q, NULL); + }); + + CMC_CREATE_TEST(resize, { + queue *q = q_new(100); + + cmc_assert_not_equals(ptr, NULL, q); + + for (size_t i = 0; i < 150; i++) + cmc_assert(q_enqueue(q, i)); + + cmc_assert_equals(size_t, 150, q_count(q)); + cmc_assert(q_resize(q, q_count(q))); + cmc_assert_equals(size_t, 150, q_capacity(q)); + + q_free(q, NULL); + }); + + CMC_CREATE_TEST(resize[item preservation], { + queue *q = q_new(100); + + cmc_assert_not_equals(ptr, NULL, q); + + for (size_t i = 1; i <= 150; i++) + cmc_assert(q_enqueue(q, i)); + + cmc_assert(q_resize(q, q_count(q))); + + size_t sum = 0; + + for (size_t i = q->front, j = 0; j < q->count; i = (i + 1) % q->capacity, j++) + { + sum += q->buffer[i]; + } + + cmc_assert_equals(size_t, 11325, sum); + + q_free(q, NULL); + }); + + CMC_CREATE_TEST(copy_of, { + queue *d1 = q_new(100); + + cmc_assert_not_equals(ptr, NULL, d1); + + for (size_t i = 1; i <= 150; i++) + cmc_assert(q_enqueue(d1, i)); + + queue *d2 = q_copy_of(d1, NULL); + + cmc_assert_not_equals(ptr, NULL, d2); + cmc_assert_equals(size_t, q_count(d1), q_count(d2)); + + for (size_t i1 = d1->front, i2 = d2->front, j = 0; j < d1->count; j++) + { + cmc_assert_equals(size_t, d1->buffer[i1], d2->buffer[i2]); + + i1 = (i1 + 1) % d1->capacity; + i2 = (i2 + 1) % d2->capacity; + } + + q_free(d1, NULL); + q_free(d2, NULL); + }); + + CMC_CREATE_TEST(equals, { + queue *d1 = q_new(100); + queue *d2 = q_new(100); + + cmc_assert_not_equals(ptr, NULL, d1); + cmc_assert_not_equals(ptr, NULL, d2); + + for (size_t i = 1; i <= 150; i++) + { + cmc_assert(q_enqueue(d1, i)); + cmc_assert(q_enqueue(d2, i)); + } + + cmc_assert(q_equals(d1, d2, cmp)); + + q_free(d1, NULL); + q_free(d2, NULL); + }); + + CMC_CREATE_TEST(equals[from copy], { + queue *d1 = q_new(100); + + cmc_assert_not_equals(ptr, NULL, d1); + + for (size_t i = 1; i <= 150; i++) + { + cmc_assert(q_enqueue(d1, i)); + } + + queue *d2 = q_copy_of(d1, NULL); + + cmc_assert_not_equals(ptr, NULL, d2); + + cmc_assert(q_equals(d1, d2, cmp)); + + q_free(d1, NULL); + q_free(d2, NULL); + }); + + CMC_CREATE_TEST(equals[count = 0], { + queue *d1 = q_new(100); + + cmc_assert_not_equals(ptr, NULL, d1); + + queue *d2 = q_copy_of(d1, NULL); + + cmc_assert_not_equals(ptr, NULL, d2); + + cmc_assert(q_equals(d1, d2, cmp)); + + q_free(d1, NULL); + q_free(d2, NULL); + }); }); diff --git a/tests/codecov/unt/sortedlist.c b/tests/codecov/unt/sortedlist.c new file mode 100644 index 0000000..f98a46e --- /dev/null +++ b/tests/codecov/unt/sortedlist.c @@ -0,0 +1,138 @@ +#include "utl.c" +#include +#include +#include + +#include "../src/sortedlist.c" + +CMC_CREATE_UNIT(sortedlist_test, false, { + CMC_CREATE_TEST(new, { + sortedlist *sl = sl_new(1000000, cmp); + + cmc_assert_not_equals(ptr, NULL, sl); + cmc_assert_not_equals(ptr, NULL, sl->buffer); + cmc_assert_equals(size_t, 1000000, sl_capacity(sl)); + cmc_assert_equals(size_t, 0, sl_count(sl)); + cmc_assert_not_equals(ptr, NULL, sl->buffer); + + sl_free(sl, NULL); + }); + + CMC_CREATE_TEST(new[capacity = 0], { + sortedlist *sl = sl_new(0, cmp); + + cmc_assert_equals(ptr, NULL, sl); + }); + + CMC_CREATE_TEST(new[capacity = UINT64_MAX], { + sortedlist *sl = sl_new(UINT64_MAX, cmp); + + cmc_assert_equals(ptr, NULL, sl); + }); + + CMC_CREATE_TEST(clear[count capacity], { + sortedlist *sl = sl_new(100, cmp); + + cmc_assert_not_equals(ptr, NULL, sl); + + for (size_t i = 0; i < 50; i++) + cmc_assert(sl_insert(sl, i)); + + cmc_assert_equals(size_t, 50, sl_count(sl)); + + sl_clear(sl, NULL); + + cmc_assert_equals(size_t, 0, sl_count(sl)); + cmc_assert_equals(size_t, 100, sl_capacity(sl)); + + sl_free(sl, NULL); + }); + + CMC_CREATE_TEST(buffer_growth[capacity = 1], { + sortedlist *sl = sl_new(1, cmp); + + cmc_assert_not_equals(ptr, NULL, sl); + + for (size_t i = 0; i < 50; i++) + cmc_assert(sl_insert(sl, i)); + + sl_sort(sl); + + cmc_assert_equals(size_t, 50, sl_count(sl)); + cmc_assert_array_sorted_any(size_t, sl->buffer, cmp, 0, sl->count - 1); + + sl_free(sl, NULL); + }); + + CMC_CREATE_TEST(insert, { + sortedlist *sl = sl_new(100, cmp); + + cmc_assert_not_equals(ptr, NULL, sl); + + cmc_assert(sl_insert(sl, 1)); + + sl_free(sl, NULL); + }); + + CMC_CREATE_TEST(remove, { + sortedlist *sl = sl_new(100, cmp); + + cmc_assert_not_equals(ptr, NULL, sl); + + cmc_assert(sl_insert(sl, 32)); + + cmc_assert(sl_remove(sl, 0)); + + sl_free(sl, NULL); + }); + + CMC_CREATE_TEST(remove[count = 0], { + sortedlist *sl = sl_new(100, cmp); + + cmc_assert_not_equals(ptr, NULL, sl); + + cmc_assert(!sl_remove(sl, 0)); + + sl_free(sl, NULL); + }); + + CMC_CREATE_TEST(remove[out of range], { + sortedlist *sl = sl_new(100, cmp); + + cmc_assert_not_equals(ptr, NULL, sl); + + cmc_assert(sl_insert(sl, 32)); + + cmc_assert(!sl_remove(sl, 2)); + + sl_free(sl, NULL); + }); + + CMC_CREATE_TEST(indexof, { + sortedlist *sl = sl_new(1, cmp); + + cmc_assert_not_equals(ptr, NULL, sl); + + for (size_t i = 0; i < 20; i++) + cmc_assert(sl_insert(sl, i % 10)); + + /* 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9 */ + cmc_assert_equals(size_t, 4, sl_indexof(sl, 2, true)); + cmc_assert_equals(size_t, 5, sl_indexof(sl, 2, false)); + + cmc_assert_equals(size_t, 0, sl_indexof(sl, 0, true)); + cmc_assert_equals(size_t, 1, sl_indexof(sl, 0, false)); + + cmc_assert(sl_remove(sl, 0)); + + cmc_assert_equals(size_t, 0, sl_indexof(sl, 0, true)); + cmc_assert_equals(size_t, 0, sl_indexof(sl, 0, false)); + + cmc_assert(sl_remove(sl, 0)); + + cmc_assert_equals(size_t, sl_count(sl), sl_indexof(sl, 0, true)); + cmc_assert_equals(size_t, sl_count(sl), sl_indexof(sl, 0, false)); + + sl_free(sl, NULL); + }); +}); diff --git a/tests/codecov/unt/stack.c b/tests/codecov/unt/stack.c index 32f80e0..1953d52 100644 --- a/tests/codecov/unt/stack.c +++ b/tests/codecov/unt/stack.c @@ -1,8 +1,9 @@ -#include "utl/assert.h" -#include "utl/test.h" -#include "../src/stack.c" - #include "utl.c" +#include +#include +#include + +#include "../src/stack.c" CMC_CREATE_UNIT(stack_test, false, { CMC_CREATE_TEST(new, { @@ -14,16 +15,16 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert_equals(size_t, 0, s_count(s)); cmc_assert_not_equals(ptr, NULL, s->buffer); - s_free(s); + s_free(s, NULL); }); - CMC_CREATE_TEST(new[edge_case:capacity = 0], { + CMC_CREATE_TEST(new[capacity = 0], { stack *s = s_new(0); cmc_assert_equals(ptr, NULL, s); }); - CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], { + CMC_CREATE_TEST(new[capacity = UINT64_MAX], { stack *s = s_new(UINT64_MAX); cmc_assert_equals(ptr, NULL, s); @@ -39,15 +40,15 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert_equals(size_t, 50, s_count(s)); - s_clear(s); + s_clear(s, NULL); cmc_assert_equals(size_t, 0, s_count(s)); cmc_assert_equals(size_t, 100, s_capacity(s)); - s_free(s); + s_free(s, NULL); }); - CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], { + CMC_CREATE_TEST(buffer_growth[capacity = 1], { stack *s = s_new(1); cmc_assert_not_equals(ptr, NULL, s); @@ -58,7 +59,7 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert_equals(size_t, 50, s_count(s)); cmc_assert_lesser_equals(size_t, s_capacity(s), s_count(s)); - s_free(s); + s_free(s, NULL); }); CMC_CREATE_TEST(push[count], { @@ -71,7 +72,7 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert_equals(size_t, 250, s_count(s)); - s_free(s); + s_free(s, NULL); }); CMC_CREATE_TEST(push[capacity], { @@ -84,10 +85,10 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert_lesser_equals(size_t, s_capacity(s), s_count(s)); - s_free(s); + s_free(s, NULL); }); - CMC_CREATE_TEST(push[item_preservation], { + CMC_CREATE_TEST(push[item preservation], { stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -98,7 +99,7 @@ CMC_CREATE_UNIT(stack_test, false, { for (size_t i = 0; i < s_count(s); i++) cmc_assert_equals(size_t, i, s->buffer[i]); - s_free(s); + s_free(s, NULL); }); CMC_CREATE_TEST(pop[count], { @@ -113,7 +114,7 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert_equals(size_t, 249, s_count(s)); - s_free(s); + s_free(s, NULL); }); CMC_CREATE_TEST(pop[capacity], { @@ -128,10 +129,10 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert_lesser_equals(size_t, s_capacity(s), s_count(s)); - s_free(s); + s_free(s, NULL); }); - CMC_CREATE_TEST(pop[item_preservation], { + CMC_CREATE_TEST(pop[item preservation], { stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -145,48 +146,17 @@ CMC_CREATE_UNIT(stack_test, false, { for (size_t i = 0; i < s_count(s); i++) cmc_assert_equals(size_t, i, s->buffer[i]); - s_free(s); + s_free(s, NULL); }); - CMC_CREATE_TEST(pop[edge_case:count = 0], { + CMC_CREATE_TEST(pop[count = 0], { stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); cmc_assert_equals(bool, false, s_pop(s)); - s_free(s); - }); - - CMC_CREATE_TEST(push_if, { - stack *s = s_new(100); - - cmc_assert_not_equals(ptr, NULL, s); - - for (size_t i = 0; i < 250; i++) - s_push_if(s, i, i % 2 == 0); - - for (size_t i = 0; i < s_count(s); i++) - cmc_assert(s->buffer[i] % 2 == 0); - - s_free(s); - }); - - CMC_CREATE_TEST(pop_if, { - stack *s = s_new(100); - - cmc_assert_not_equals(ptr, NULL, s); - - for (size_t i = 0; i < 250; i++) - { - s_push(s, i); - s_pop_if(s, s_top(s) % 2 == 0); - } - - for (size_t i = 0; i < s_count(s); i++) - cmc_assert_not_equals(uint32_t, 0, s->buffer[i] % 2); - - s_free(s); + s_free(s, NULL); }); CMC_CREATE_TEST(top, { @@ -202,10 +172,10 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert_equals(size_t, 247, s_top(s)); - s_free(s); + s_free(s, NULL); }); - CMC_CREATE_TEST(top[edge_case:count = 0], { + CMC_CREATE_TEST(top[count = 0], { stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -214,12 +184,12 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert(s_pop(s)); - cmc_assert_equals(size_t, s_impl_default_value(), s_top(s)); + cmc_assert_equals(size_t, (size_t){0}, s_top(s)); - s_free(s); + s_free(s, NULL); }); - CMC_CREATE_TEST(top[edge_case:count = 1], { + CMC_CREATE_TEST(top[count = 1], { stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -228,7 +198,7 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert_equals(size_t, 1, s_count(s)); cmc_assert_equals(size_t, 10, s_top(s)); - s_free(s); + s_free(s, NULL); }); CMC_CREATE_TEST(contains, { @@ -242,17 +212,17 @@ CMC_CREATE_UNIT(stack_test, false, { for (size_t i = 0; i < 150; i++) cmc_assert(s_contains(s, i, cmp)); - s_free(s); + s_free(s, NULL); }); - CMC_CREATE_TEST(contains[edge_case:count = 0], { + CMC_CREATE_TEST(contains[count = 0], { stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); cmc_assert_equals(bool, false, s_contains(s, 10, cmp)); - s_free(s); + s_free(s, NULL); }); CMC_CREATE_TEST(empty, { @@ -262,7 +232,7 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert(s_empty(s)); - s_free(s); + s_free(s, NULL); }); CMC_CREATE_TEST(empty[after_io], { @@ -274,7 +244,7 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert(s_pop(s)); cmc_assert(s_empty(s)); - s_free(s); + s_free(s, NULL); }); CMC_CREATE_TEST(full, { @@ -287,10 +257,10 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert(s_full(s)); - s_free(s); + s_free(s, NULL); }); - CMC_CREATE_TEST(full[edge_case:capacity = 1], { + CMC_CREATE_TEST(full[capacity = 1], { stack *s = s_new(1); cmc_assert_not_equals(ptr, NULL, s); @@ -299,7 +269,7 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert(s_full(s)); - s_free(s); + s_free(s, NULL); }); CMC_CREATE_TEST(iter_alloc, { @@ -312,10 +282,10 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert_not_equals(ptr, NULL, iter); s_iter_free(iter); - s_free(s); + s_free(s, NULL); }); - CMC_CREATE_TEST(iter_init[edge_case:count = 0], { + CMC_CREATE_TEST(iter_init[count = 0], { stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -329,10 +299,10 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert(iter.start); cmc_assert(iter.end); - s_free(s); + s_free(s, NULL); }); - CMC_CREATE_TEST(iter_start[edge_case:count = 0], { + CMC_CREATE_TEST(iter_start[count = 0], { stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -343,10 +313,10 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert(s_iter_start(&iter)); - s_free(s); + s_free(s, NULL); }); - CMC_CREATE_TEST(iter_end[edge_case:count = 0], { + CMC_CREATE_TEST(iter_end[count = 0], { stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -357,7 +327,7 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert(s_iter_end(&iter)); - s_free(s); + s_free(s, NULL); }); CMC_CREATE_TEST(iteration, { @@ -384,7 +354,7 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert_equals(size_t, 40200, total); - s_free(s); + s_free(s, NULL); }); CMC_CREATE_TEST(iteration[while loop], { @@ -414,10 +384,10 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert_equals(size_t, 40200, total); - s_free(s); + s_free(s, NULL); }); - CMC_CREATE_TEST(iteration[edge_case:count = 1], { + CMC_CREATE_TEST(iteration[count = 1], { stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -437,10 +407,10 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert_equals(size_t, 20, total); - s_free(s); + s_free(s, NULL); }); - CMC_CREATE_TEST(iteration[edge_case:count = capacity], { + CMC_CREATE_TEST(iteration[count = capacity], { stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -466,7 +436,7 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert_equals(size_t, 2000, total); - s_free(s); + s_free(s, NULL); }); CMC_CREATE_TEST(iteration[to_start = it_start and to_end = it_end], { @@ -501,10 +471,10 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert_equals(bool, it1.start, it2.start); cmc_assert_equals(bool, it1.end, it2.end); - s_free(s); + s_free(s, NULL); }); - CMC_CREATE_TEST(iteration[boundaries:count = 0], { + CMC_CREATE_TEST(iteration[boundaries count = 0], { stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -520,10 +490,10 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert_equals(bool, false, s_iter_prev(&iter)); - s_free(s); + s_free(s, NULL); }); - CMC_CREATE_TEST(iteration[boundaries:count > 0], { + CMC_CREATE_TEST(iteration[boundaries count > 0], { stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -542,10 +512,10 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert_equals(bool, false, s_iter_prev(&iter)); - s_free(s); + s_free(s, NULL); }); - CMC_CREATE_TEST(iter_value[edge_case:count = 0], { + CMC_CREATE_TEST(iter_value[count = 0], { stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -554,12 +524,12 @@ CMC_CREATE_UNIT(stack_test, false, { s_iter_init(&iter, s); - cmc_assert_equals(size_t, s_impl_default_value(), s_iter_value(&iter)); + cmc_assert_equals(size_t, (size_t){0}, s_iter_value(&iter)); - s_free(s); + s_free(s, NULL); }); - CMC_CREATE_TEST(iter_rvalue[edge_case:count = 0], { + CMC_CREATE_TEST(iter_rvalue[count = 0], { stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -570,7 +540,7 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert_equals(ptr, NULL, s_iter_rvalue(&iter)); - s_free(s); + s_free(s, NULL); }); CMC_CREATE_TEST(index, { @@ -585,12 +555,12 @@ CMC_CREATE_UNIT(stack_test, false, { size_t total = 0; - for (stack_iter it = s->it_start(s); false; ) + for (stack_iter it = s->it_start(s); false;) { cmc_assert_equals(size_t, 0, s_iter_index(&it)); } - for (stack_iter it = s->it_start(s); false; ) + for (stack_iter it = s->it_start(s); false;) { cmc_assert_equals(size_t, s_count(s) - 1, s_iter_index(&it)); } @@ -609,10 +579,10 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert_equals(size_t, 90, total); - s_free(s); + s_free(s, NULL); }); - CMC_CREATE_TEST(index[edge_case:count = 0], { + CMC_CREATE_TEST(index[count = 0], { stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -622,7 +592,6 @@ CMC_CREATE_UNIT(stack_test, false, { cmc_assert_equals(size_t, 0, s_iter_index(&iter)); - s_free(s); + s_free(s, NULL); }); - }); diff --git a/tests/codecov/unt/treemap.c b/tests/codecov/unt/treemap.c index c9d873b..db695f9 100644 --- a/tests/codecov/unt/treemap.c +++ b/tests/codecov/unt/treemap.c @@ -1,8 +1,9 @@ -#include "utl/assert.h" -#include "utl/test.h" -#include "../src/treemap.c" - #include "utl.c" +#include +#include +#include + +#include "../src/treemap.c" CMC_CREATE_UNIT(treemap_test, false, { CMC_CREATE_TEST(new, { @@ -10,7 +11,7 @@ CMC_CREATE_UNIT(treemap_test, false, { cmc_assert_not_equals(ptr, NULL, map); - tm_free(map); + tm_free(map, NULL); }); CMC_CREATE_TEST(clear[count], { @@ -23,12 +24,11 @@ CMC_CREATE_UNIT(treemap_test, false, { cmc_assert_equals(size_t, 50, tm_count(map)); - tm_clear(map); + tm_clear(map, NULL); cmc_assert_equals(size_t, 0, tm_count(map)); cmc_assert_equals(ptr, NULL, map->root); - tm_free(map); + tm_free(map, NULL); }); - }); diff --git a/tests/codecov/unt/treeset.c b/tests/codecov/unt/treeset.c index b8bb64b..6cf8e05 100644 --- a/tests/codecov/unt/treeset.c +++ b/tests/codecov/unt/treeset.c @@ -1,8 +1,9 @@ -#include "utl/assert.h" -#include "utl/test.h" -#include "../src/treeset.c" - #include "utl.c" +#include +#include +#include + +#include "../src/treeset.c" CMC_CREATE_UNIT(treeset_test, false, { CMC_CREATE_TEST(new, { @@ -10,7 +11,7 @@ CMC_CREATE_UNIT(treeset_test, false, { cmc_assert_not_equals(ptr, NULL, set); - ts_free(set); + ts_free(set, NULL); }); CMC_CREATE_TEST(clear[count], { @@ -23,12 +24,11 @@ CMC_CREATE_UNIT(treeset_test, false, { cmc_assert_equals(size_t, 50, ts_count(set)); - ts_clear(set); + ts_clear(set, NULL); cmc_assert_equals(size_t, 0, ts_count(set)); cmc_assert_equals(ptr, NULL, set->root); - ts_free(set); + ts_free(set, NULL); }); - }); diff --git a/tests/codecov/unt/utl.c b/tests/codecov/unt/utl.c index b42a9e4..5844154 100644 --- a/tests/codecov/unt/utl.c +++ b/tests/codecov/unt/utl.c @@ -3,6 +3,7 @@ #define CMC_UNIT_TEST_UTL__ #include +#include int cmp(size_t a, size_t b) { @@ -20,4 +21,24 @@ size_t hash(size_t a) return a; } +size_t numhash(size_t a) +{ + return a; +} + +size_t hashcapminus1(size_t a) +{ + return cmc_hashtable_primes[0] - 1; +} + +size_t hashcapminus4(size_t a) +{ + return cmc_hashtable_primes[0] - 1; +} + +size_t hash0(size_t a) +{ + return 0; +} + #endif /* CMC_UNIT_TEST_UTL__ */