From 89254ab5db45eda00553dc21fd3139426cbc44c4 Mon Sep 17 00:00:00 2001 From: Leonardo Vencovsky Date: Fri, 29 May 2020 20:19:47 -0300 Subject: [PATCH] Started migrating things to EXT --- src/cmc/hashmap.h | 579 +++++++----------------------- src/cmc/hashmultimap.h | 649 +++++++--------------------------- src/ext/cmc/deque.h | 1 + src/ext/cmc/hashmap.h | 337 +++++++++++++++++- src/ext/cmc/hashmultimap.h | 472 +++++++++++++++++++++++++ src/macro_collections.h | 67 ++-- tests/main/src/deque.c | 21 -- tests/main/src/hashmap.c | 26 -- tests/main/src/hashmultimap.c | 27 -- tests/main/unt/utl.c | 9 + tests/to_string.c | 14 +- 11 files changed, 1131 insertions(+), 1071 deletions(-) create mode 100644 src/ext/cmc/hashmultimap.h diff --git a/src/cmc/hashmap.h b/src/cmc/hashmap.h index 2127ab8..ad25ae0 100644 --- a/src/cmc/hashmap.h +++ b/src/cmc/hashmap.h @@ -47,187 +47,138 @@ /* ------------------------------------------------------------------------- * Header * ------------------------------------------------------------------------- */ -#define CMC_CMC_HASHMAP_CORE_HEADER_(PFX, SNAME, K, V) \ - \ - /* Hashmap Structure */ \ - struct SNAME \ - { \ - /* Array of Entries */ \ - struct CMC_DEF_ENTRY(SNAME) * buffer; \ - \ - /* Current array capacity */ \ - size_t capacity; \ - \ - /* Current amount of keys */ \ - size_t count; \ - \ - /* Load factor in range (0.0, 1.0) */ \ - double load; \ - \ - /* Flags indicating errors or success */ \ - int flag; \ - \ - /* Key function table */ \ - struct CMC_DEF_FKEY(SNAME) * f_key; \ - \ - /* Value function table */ \ - struct CMC_DEF_FVAL(SNAME) * f_val; \ - \ - /* Custom allocation functions */ \ - struct cmc_alloc_node *alloc; \ - \ - /* Custom callback functions */ \ - struct cmc_callbacks *callbacks; \ - }; \ - \ - /* Hashmap Entry */ \ - struct CMC_DEF_ENTRY(SNAME) \ - { \ - /* Entry Key */ \ - K key; \ - \ - /* Entry Value */ \ - V value; \ - \ - /* The distance of this node to its original position, used by */ \ - /* robin-hood hashing */ \ - size_t dist; \ - \ - /* The sate of this node (DELETED, EMPTY, FILLED) */ \ - enum cmc_entry_state state; \ - }; \ - \ - /* Key struct function table */ \ - struct CMC_DEF_FKEY(SNAME) \ - { \ - /* Comparator function */ \ - int (*cmp)(K, K); \ - \ - /* Copy function */ \ - K (*cpy)(K); \ - \ - /* To string function */ \ - bool (*str)(FILE *, K); \ - \ - /* Free from memory function */ \ - void (*free)(K); \ - \ - /* Hash function */ \ - size_t (*hash)(K); \ - \ - /* Priority function */ \ - int (*pri)(K, K); \ - }; \ - \ - /* Value struct function table */ \ - struct CMC_DEF_FVAL(SNAME) \ - { \ - /* Comparator function */ \ - int (*cmp)(V, V); \ - \ - /* Copy function */ \ - V (*cpy)(V); \ - \ - /* To string function */ \ - bool (*str)(FILE *, V); \ - \ - /* Free from memory function */ \ - void (*free)(V); \ - \ - /* Hash function */ \ - size_t (*hash)(V); \ - \ - /* Priority function */ \ - int (*pri)(V, V); \ - }; \ - \ - /* Hashmap Iterator */ \ - struct CMC_DEF_ITER(SNAME) \ - { \ - /* Target hashmap */ \ - struct SNAME *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* The index of the first element */ \ - size_t first; \ - \ - /* The index of the last element */ \ - size_t last; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - }; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - struct SNAME *CMC_(PFX, _new)(size_t capacity, double load, \ - struct CMC_DEF_FKEY(SNAME) * f_key, \ - struct CMC_DEF_FVAL(SNAME) * f_val); \ - struct SNAME *CMC_(PFX, _new_custom)( \ - size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, \ - struct CMC_DEF_FVAL(SNAME) * f_val, struct cmc_alloc_node * alloc, \ - struct cmc_callbacks * callbacks); \ - void CMC_(PFX, _clear)(struct SNAME * _map_); \ - void CMC_(PFX, _free)(struct SNAME * _map_); \ - void CMC_(PFX, _release)(struct SNAME _map_); \ - /* Customization of Allocation and Callbacks */ \ - void CMC_(PFX, _customize)(struct SNAME * _map_, \ - struct cmc_alloc_node * alloc, \ - struct cmc_callbacks * callbacks); \ - /* Collection Input and Output */ \ - bool CMC_(PFX, _insert)(struct SNAME * _map_, K key, V value); \ - bool CMC_(PFX, _update)(struct SNAME * _map_, K key, V new_value, \ - V * old_value); \ - bool CMC_(PFX, _remove)(struct SNAME * _map_, K key, V * out_value); \ - /* Element Access */ \ - bool CMC_(PFX, _max)(struct SNAME * _map_, K * key, V * value); \ - bool CMC_(PFX, _min)(struct SNAME * _map_, K * key, V * value); \ - V CMC_(PFX, _get)(struct SNAME * _map_, K key); \ - V *CMC_(PFX, _get_ref)(struct SNAME * _map_, K key); \ - /* Collection State */ \ - bool CMC_(PFX, _contains)(struct SNAME * _map_, K key); \ - bool CMC_(PFX, _empty)(struct SNAME * _map_); \ - bool CMC_(PFX, _full)(struct SNAME * _map_); \ - size_t CMC_(PFX, _count)(struct SNAME * _map_); \ - size_t CMC_(PFX, _capacity)(struct SNAME * _map_); \ - double CMC_(PFX, _load)(struct SNAME * _map_); \ - int CMC_(PFX, _flag)(struct SNAME * _map_); \ - /* Collection Utility */ \ - bool CMC_(PFX, _resize)(struct SNAME * _map_, size_t capacity); \ - struct SNAME *CMC_(PFX, _copy_of)(struct SNAME * _map_); \ - bool CMC_(PFX, _equals)(struct SNAME * _map1_, struct SNAME * _map2_); \ - \ - /* Iterator Functions */ \ - /* Iterator Initialization */ \ - struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target); \ - struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target); \ - /* Iterator State */ \ - bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter); \ - bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter); \ - /* Iterator Movement */ \ - bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); \ - bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter); \ - bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter); \ - bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter); \ - bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, \ - size_t steps); \ - bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, \ - size_t steps); \ - bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, \ - size_t index); \ - /* Iterator Access */ \ - K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter); \ - V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); \ - V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter); \ - size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter); +#define CMC_CMC_HASHMAP_CORE_HEADER_(PFX, SNAME, K, V) \ + \ + /* Hashmap Structure */ \ + struct SNAME \ + { \ + /* Array of Entries */ \ + struct CMC_DEF_ENTRY(SNAME) * buffer; \ + \ + /* Current array capacity */ \ + size_t capacity; \ + \ + /* Current amount of keys */ \ + size_t count; \ + \ + /* Load factor in range (0.0, 1.0) */ \ + double load; \ + \ + /* Flags indicating errors or success */ \ + int flag; \ + \ + /* Key function table */ \ + struct CMC_DEF_FKEY(SNAME) * f_key; \ + \ + /* Value function table */ \ + struct CMC_DEF_FVAL(SNAME) * f_val; \ + \ + /* Custom allocation functions */ \ + struct cmc_alloc_node *alloc; \ + \ + /* Custom callback functions */ \ + struct cmc_callbacks *callbacks; \ + }; \ + \ + /* Hashmap Entry */ \ + struct CMC_DEF_ENTRY(SNAME) \ + { \ + /* Entry Key */ \ + K key; \ + \ + /* Entry Value */ \ + V value; \ + \ + /* The distance of this node to its original position, used by */ \ + /* robin-hood hashing */ \ + size_t dist; \ + \ + /* The sate of this node (DELETED, EMPTY, FILLED) */ \ + enum cmc_entry_state state; \ + }; \ + \ + /* Key struct function table */ \ + struct CMC_DEF_FKEY(SNAME) \ + { \ + /* Comparator function */ \ + int (*cmp)(K, K); \ + \ + /* Copy function */ \ + K (*cpy)(K); \ + \ + /* To string function */ \ + bool (*str)(FILE *, K); \ + \ + /* Free from memory function */ \ + void (*free)(K); \ + \ + /* Hash function */ \ + size_t (*hash)(K); \ + \ + /* Priority function */ \ + int (*pri)(K, K); \ + }; \ + \ + /* Value struct function table */ \ + struct CMC_DEF_FVAL(SNAME) \ + { \ + /* Comparator function */ \ + int (*cmp)(V, V); \ + \ + /* Copy function */ \ + V (*cpy)(V); \ + \ + /* To string function */ \ + bool (*str)(FILE *, V); \ + \ + /* Free from memory function */ \ + void (*free)(V); \ + \ + /* Hash function */ \ + size_t (*hash)(V); \ + \ + /* Priority function */ \ + int (*pri)(V, V); \ + }; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + struct SNAME *CMC_(PFX, _new)(size_t capacity, double load, \ + struct CMC_DEF_FKEY(SNAME) * f_key, \ + struct CMC_DEF_FVAL(SNAME) * f_val); \ + struct SNAME *CMC_(PFX, _new_custom)( \ + size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, \ + struct CMC_DEF_FVAL(SNAME) * f_val, struct cmc_alloc_node * alloc, \ + struct cmc_callbacks * callbacks); \ + void CMC_(PFX, _clear)(struct SNAME * _map_); \ + void CMC_(PFX, _free)(struct SNAME * _map_); \ + void CMC_(PFX, _release)(struct SNAME _map_); \ + /* Customization of Allocation and Callbacks */ \ + void CMC_(PFX, _customize)(struct SNAME * _map_, \ + struct cmc_alloc_node * alloc, \ + struct cmc_callbacks * callbacks); \ + /* Collection Input and Output */ \ + bool CMC_(PFX, _insert)(struct SNAME * _map_, K key, V value); \ + bool CMC_(PFX, _update)(struct SNAME * _map_, K key, V new_value, \ + V * old_value); \ + bool CMC_(PFX, _remove)(struct SNAME * _map_, K key, V * out_value); \ + /* Element Access */ \ + bool CMC_(PFX, _max)(struct SNAME * _map_, K * key, V * value); \ + bool CMC_(PFX, _min)(struct SNAME * _map_, K * key, V * value); \ + V CMC_(PFX, _get)(struct SNAME * _map_, K key); \ + V *CMC_(PFX, _get_ref)(struct SNAME * _map_, K key); \ + /* Collection State */ \ + bool CMC_(PFX, _contains)(struct SNAME * _map_, K key); \ + bool CMC_(PFX, _empty)(struct SNAME * _map_); \ + bool CMC_(PFX, _full)(struct SNAME * _map_); \ + size_t CMC_(PFX, _count)(struct SNAME * _map_); \ + size_t CMC_(PFX, _capacity)(struct SNAME * _map_); \ + double CMC_(PFX, _load)(struct SNAME * _map_); \ + int CMC_(PFX, _flag)(struct SNAME * _map_); \ + /* Collection Utility */ \ + bool CMC_(PFX, _resize)(struct SNAME * _map_, size_t capacity); \ + struct SNAME *CMC_(PFX, _copy_of)(struct SNAME * _map_); \ + bool CMC_(PFX, _equals)(struct SNAME * _map1_, struct SNAME * _map2_); /* ------------------------------------------------------------------------- * Source @@ -842,272 +793,6 @@ return true; \ } \ \ - struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \ - { \ - struct CMC_DEF_ITER(SNAME) iter; \ - \ - iter.target = target; \ - iter.cursor = 0; \ - iter.index = 0; \ - iter.first = 0; \ - iter.last = 0; \ - iter.start = true; \ - iter.end = CMC_(PFX, _empty)(target); \ - \ - if (!CMC_(PFX, _empty)(target)) \ - { \ - for (size_t i = 0; i < target->capacity; i++) \ - { \ - if (target->buffer[i].state == CMC_ES_FILLED) \ - { \ - iter.first = i; \ - break; \ - } \ - } \ - \ - iter.cursor = iter.first; \ - \ - for (size_t i = target->capacity; i > 0; i--) \ - { \ - if (target->buffer[i - 1].state == CMC_ES_FILLED) \ - { \ - iter.last = i - 1; \ - break; \ - } \ - } \ - } \ - \ - return iter; \ - } \ - \ - struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target) \ - { \ - struct CMC_DEF_ITER(SNAME) iter; \ - \ - iter.target = target; \ - iter.cursor = 0; \ - iter.index = 0; \ - iter.first = 0; \ - iter.last = 0; \ - iter.start = CMC_(PFX, _empty)(target); \ - iter.end = true; \ - \ - if (!CMC_(PFX, _empty)(target)) \ - { \ - for (size_t i = 0; i < target->capacity; i++) \ - { \ - if (target->buffer[i].state == CMC_ES_FILLED) \ - { \ - iter.first = i; \ - break; \ - } \ - } \ - \ - for (size_t i = target->capacity; i > 0; i--) \ - { \ - if (target->buffer[i - 1].state == CMC_ES_FILLED) \ - { \ - iter.last = i - 1; \ - break; \ - } \ - } \ - \ - iter.cursor = iter.last; \ - iter.index = target->count - 1; \ - } \ - \ - return iter; \ - } \ - \ - bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) \ - { \ - return CMC_(PFX, _empty)(iter->target) || iter->start; \ - } \ - \ - bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) \ - { \ - return CMC_(PFX, _empty)(iter->target) || iter->end; \ - } \ - \ - bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) \ - { \ - if (!CMC_(PFX, _empty)(iter->target)) \ - { \ - iter->cursor = iter->first; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = CMC_(PFX, _empty)(iter->target); \ - \ - return true; \ - } \ - \ - return false; \ - } \ - \ - bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) \ - { \ - if (!CMC_(PFX, _empty)(iter->target)) \ - { \ - iter->cursor = iter->last; \ - iter->index = iter->target->count - 1; \ - iter->start = CMC_(PFX, _empty)(iter->target); \ - iter->end = true; \ - \ - return true; \ - } \ - \ - return false; \ - } \ - \ - bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->index + 1 == iter->target->count) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - iter->start = CMC_(PFX, _empty)(iter->target); \ - \ - struct CMC_DEF_ENTRY(SNAME) *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 true; \ - } \ - \ - bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->index == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - iter->end = CMC_(PFX, _empty)(iter->target); \ - \ - struct CMC_DEF_ENTRY(SNAME) *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 true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, \ - size_t steps) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->index + 1 == iter->target->count) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index + steps >= iter->target->count) \ - return false; \ - \ - for (size_t i = 0; i < steps; i++) \ - CMC_(PFX, _iter_next)(iter); \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, \ - size_t steps) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->index == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index < steps) \ - return false; \ - \ - for (size_t i = 0; i < steps; i++) \ - CMC_(PFX, _iter_prev)(iter); \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator was able to be positioned at the */ \ - /* given index */ \ - bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, \ - size_t index) \ - { \ - if (index >= iter->target->count) \ - return false; \ - \ - if (iter->index > index) \ - return CMC_(PFX, _iter_rewind)(iter, iter->index - index); \ - else if (iter->index < index) \ - return CMC_(PFX, _iter_advance)(iter, index - iter->index); \ - \ - return true; \ - } \ - \ - K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter) \ - { \ - if (CMC_(PFX, _empty)(iter->target)) \ - return (K){ 0 }; \ - \ - return iter->target->buffer[iter->cursor].key; \ - } \ - \ - V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \ - { \ - if (CMC_(PFX, _empty)(iter->target)) \ - return (V){ 0 }; \ - \ - return iter->target->buffer[iter->cursor].value; \ - } \ - \ - V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter) \ - { \ - if (CMC_(PFX, _empty)(iter->target)) \ - return NULL; \ - \ - return &(iter->target->buffer[iter->cursor].value); \ - } \ - \ - size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \ - { \ - return iter->index; \ - } \ - \ static struct CMC_DEF_ENTRY(SNAME) * \ CMC_(PFX, _impl_get_entry)(struct SNAME * _map_, K key) \ { \ diff --git a/src/cmc/hashmultimap.h b/src/cmc/hashmultimap.h index cc4461b..029bc8d 100644 --- a/src/cmc/hashmultimap.h +++ b/src/cmc/hashmultimap.h @@ -54,22 +54,6 @@ * ------------------------------------------------------------------------- */ #include "../cor/hashtable.h" -/* ------------------------------------------------------------------------- - * HashMultiMap specific - * ------------------------------------------------------------------------- */ -/* to_string format */ -static const char *cmc_cmc_string_fmt_hashmultimap = "struct %s<%s, %s> " - "at %p { " - "buffer:%p, " - "capacity:%" PRIuMAX ", " - "count:%" PRIuMAX ", " - "load:%lf, " - "flag:%d, " - "f_key:%p, " - "f_val:%p, " - "alloc:%p, " - "callbacks:%p }"; - /** * Core HashMultiMap implementation */ @@ -90,194 +74,141 @@ static const char *cmc_cmc_string_fmt_hashmultimap = "struct %s<%s, %s> " /* ------------------------------------------------------------------------- * Header * ------------------------------------------------------------------------- */ -#define CMC_CMC_HASHMULTIMAP_CORE_HEADER_(PFX, SNAME, K, V) \ - \ - /* HashMultimap Structure */ \ - struct SNAME \ - { \ - /* Array of linked list to entries */ \ - struct CMC_DEF_ENTRY(SNAME) * (*buffer)[2]; \ - \ - /* Current array capacity */ \ - size_t capacity; \ - \ - /* Current amount of keys */ \ - size_t count; \ - \ - /* Load factor in range (0.0, infinity) */ \ - double load; \ - \ - /* Flags indicating errors or success */ \ - int flag; \ - \ - /* Key function table */ \ - struct CMC_DEF_FKEY(SNAME) * f_key; \ - \ - /* Value function table */ \ - struct CMC_DEF_FVAL(SNAME) * f_val; \ - \ - /* Custom allocation functions */ \ - struct cmc_alloc_node *alloc; \ - \ - /* Custom callback functions */ \ - struct cmc_callbacks *callbacks; \ - }; \ - \ - /* HashMultimap Entry */ \ - struct CMC_DEF_ENTRY(SNAME) \ - { \ - /* Entry Key */ \ - K key; \ - \ - /* Entry Value */ \ - V value; \ - \ - /* Next entry on the linked list */ \ - struct CMC_DEF_ENTRY(SNAME) * next; \ - \ - /* Previous entry on the linked list */ \ - struct CMC_DEF_ENTRY(SNAME) * prev; \ - }; \ - \ - /* Key struct function table */ \ - struct CMC_DEF_FKEY(SNAME) \ - { \ - /* Comparator function */ \ - int (*cmp)(K, K); \ - \ - /* Copy function */ \ - K (*cpy)(K); \ - \ - /* To string function */ \ - bool (*str)(FILE *, K); \ - \ - /* Free from memory function */ \ - void (*free)(K); \ - \ - /* Hash function */ \ - size_t (*hash)(K); \ - \ - /* Priority function */ \ - int (*pri)(K, K); \ - }; \ - \ - /* Value struct function table */ \ - struct CMC_DEF_FVAL(SNAME) \ - { \ - /* Comparator function */ \ - int (*cmp)(V, V); \ - \ - /* Copy function */ \ - V (*cpy)(V); \ - \ - /* To string function */ \ - bool (*str)(FILE *, V); \ - \ - /* Free from memory function */ \ - void (*free)(V); \ - \ - /* Hash function */ \ - size_t (*hash)(V); \ - \ - /* Priority function */ \ - int (*pri)(V, V); \ - }; \ - \ - struct CMC_DEF_ITER(SNAME) \ - { \ - /* Target hashmultimap */ \ - struct SNAME *target; \ - \ - /* Current entry */ \ - struct CMC_DEF_ENTRY(SNAME) * curr_entry; \ - \ - /* Cursor`s position (index) */ \ - size_t cursor; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* The index of the first element */ \ - size_t first; \ - \ - /* The index of the last element */ \ - size_t last; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - }; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - struct SNAME *CMC_(PFX, _new)(size_t capacity, double load, \ - struct CMC_DEF_FKEY(SNAME) * f_key, \ - struct CMC_DEF_FVAL(SNAME) * f_val); \ - struct SNAME *CMC_(PFX, _new_custom)( \ - size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, \ - struct CMC_DEF_FVAL(SNAME) * f_val, struct cmc_alloc_node * alloc, \ - struct cmc_callbacks * callbacks); \ - void CMC_(PFX, _clear)(struct SNAME * _map_); \ - void CMC_(PFX, _free)(struct SNAME * _map_); \ - /* Customization of Allocation and Callbacks */ \ - void CMC_(PFX, _customize)(struct SNAME * _map_, \ - struct cmc_alloc_node * alloc, \ - struct cmc_callbacks * callbacks); \ - /* Collection Input and Output */ \ - bool CMC_(PFX, _insert)(struct SNAME * _map_, K key, V value); \ - bool CMC_(PFX, _update)(struct SNAME * _map_, K key, V new_value, \ - V * old_value); \ - size_t CMC_(PFX, _update_all)(struct SNAME * _map_, K key, V new_value, \ - V * *old_values); \ - bool CMC_(PFX, _remove)(struct SNAME * _map_, K key, V * out_value); \ - size_t CMC_(PFX, _remove_all)(struct SNAME * _map_, K key, \ - V * *out_values); \ - /* Element Access */ \ - bool CMC_(PFX, _max)(struct SNAME * _map_, K * key, V * value); \ - bool CMC_(PFX, _min)(struct SNAME * _map_, K * key, V * value); \ - V CMC_(PFX, _get)(struct SNAME * _map_, K key); \ - V *CMC_(PFX, _get_ref)(struct SNAME * _map_, K key); \ - /* Collection State */ \ - bool CMC_(PFX, _contains)(struct SNAME * _map_, K key); \ - bool CMC_(PFX, _empty)(struct SNAME * _map_); \ - bool CMC_(PFX, _full)(struct SNAME * _map_); \ - size_t CMC_(PFX, _count)(struct SNAME * _map_); \ - size_t CMC_(PFX, _key_count)(struct SNAME * _map_, K key); \ - size_t CMC_(PFX, _capacity)(struct SNAME * _map_); \ - double CMC_(PFX, _load)(struct SNAME * _map_); \ - int CMC_(PFX, _flag)(struct SNAME * _map_); \ - /* Collection Utility */ \ - bool CMC_(PFX, _resize)(struct SNAME * _map_, size_t capacity); \ - struct SNAME *CMC_(PFX, _copy_of)(struct SNAME * _map_); \ - bool CMC_(PFX, _equals)(struct SNAME * _map1_, struct SNAME * _map2_); \ - struct cmc_string CMC_(PFX, _to_string)(struct SNAME * _map_); \ - bool CMC_(PFX, _print)(struct SNAME * _map_, FILE * fptr); \ - \ - /* Iterator Functions */ \ - /* Iterator Initialization */ \ - struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target); \ - struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target); \ - /* Iterator State */ \ - bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter); \ - bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter); \ - /* Iterator Movement */ \ - bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); \ - bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter); \ - bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter); \ - bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter); \ - bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, \ - size_t steps); \ - bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, \ - size_t steps); \ - bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, \ - size_t index); \ - /* Iterator Access */ \ - K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter); \ - V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); \ - V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter); \ - size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter); +#define CMC_CMC_HASHMULTIMAP_CORE_HEADER_(PFX, SNAME, K, V) \ + \ + /* HashMultimap Structure */ \ + struct SNAME \ + { \ + /* Array of linked list to entries */ \ + struct CMC_DEF_ENTRY(SNAME) * (*buffer)[2]; \ + \ + /* Current array capacity */ \ + size_t capacity; \ + \ + /* Current amount of keys */ \ + size_t count; \ + \ + /* Load factor in range (0.0, infinity) */ \ + double load; \ + \ + /* Flags indicating errors or success */ \ + int flag; \ + \ + /* Key function table */ \ + struct CMC_DEF_FKEY(SNAME) * f_key; \ + \ + /* Value function table */ \ + struct CMC_DEF_FVAL(SNAME) * f_val; \ + \ + /* Custom allocation functions */ \ + struct cmc_alloc_node *alloc; \ + \ + /* Custom callback functions */ \ + struct cmc_callbacks *callbacks; \ + }; \ + \ + /* HashMultimap Entry */ \ + struct CMC_DEF_ENTRY(SNAME) \ + { \ + /* Entry Key */ \ + K key; \ + \ + /* Entry Value */ \ + V value; \ + \ + /* Next entry on the linked list */ \ + struct CMC_DEF_ENTRY(SNAME) * next; \ + \ + /* Previous entry on the linked list */ \ + struct CMC_DEF_ENTRY(SNAME) * prev; \ + }; \ + \ + /* Key struct function table */ \ + struct CMC_DEF_FKEY(SNAME) \ + { \ + /* Comparator function */ \ + int (*cmp)(K, K); \ + \ + /* Copy function */ \ + K (*cpy)(K); \ + \ + /* To string function */ \ + bool (*str)(FILE *, K); \ + \ + /* Free from memory function */ \ + void (*free)(K); \ + \ + /* Hash function */ \ + size_t (*hash)(K); \ + \ + /* Priority function */ \ + int (*pri)(K, K); \ + }; \ + \ + /* Value struct function table */ \ + struct CMC_DEF_FVAL(SNAME) \ + { \ + /* Comparator function */ \ + int (*cmp)(V, V); \ + \ + /* Copy function */ \ + V (*cpy)(V); \ + \ + /* To string function */ \ + bool (*str)(FILE *, V); \ + \ + /* Free from memory function */ \ + void (*free)(V); \ + \ + /* Hash function */ \ + size_t (*hash)(V); \ + \ + /* Priority function */ \ + int (*pri)(V, V); \ + }; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + struct SNAME *CMC_(PFX, _new)(size_t capacity, double load, \ + struct CMC_DEF_FKEY(SNAME) * f_key, \ + struct CMC_DEF_FVAL(SNAME) * f_val); \ + struct SNAME *CMC_(PFX, _new_custom)( \ + size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, \ + struct CMC_DEF_FVAL(SNAME) * f_val, struct cmc_alloc_node * alloc, \ + struct cmc_callbacks * callbacks); \ + void CMC_(PFX, _clear)(struct SNAME * _map_); \ + void CMC_(PFX, _free)(struct SNAME * _map_); \ + /* Customization of Allocation and Callbacks */ \ + void CMC_(PFX, _customize)(struct SNAME * _map_, \ + struct cmc_alloc_node * alloc, \ + struct cmc_callbacks * callbacks); \ + /* Collection Input and Output */ \ + bool CMC_(PFX, _insert)(struct SNAME * _map_, K key, V value); \ + bool CMC_(PFX, _update)(struct SNAME * _map_, K key, V new_value, \ + V * old_value); \ + size_t CMC_(PFX, _update_all)(struct SNAME * _map_, K key, V new_value, \ + V * *old_values); \ + bool CMC_(PFX, _remove)(struct SNAME * _map_, K key, V * out_value); \ + size_t CMC_(PFX, _remove_all)(struct SNAME * _map_, K key, \ + V * *out_values); \ + /* Element Access */ \ + bool CMC_(PFX, _max)(struct SNAME * _map_, K * key, V * value); \ + bool CMC_(PFX, _min)(struct SNAME * _map_, K * key, V * value); \ + V CMC_(PFX, _get)(struct SNAME * _map_, K key); \ + V *CMC_(PFX, _get_ref)(struct SNAME * _map_, K key); \ + /* Collection State */ \ + bool CMC_(PFX, _contains)(struct SNAME * _map_, K key); \ + bool CMC_(PFX, _empty)(struct SNAME * _map_); \ + bool CMC_(PFX, _full)(struct SNAME * _map_); \ + size_t CMC_(PFX, _count)(struct SNAME * _map_); \ + size_t CMC_(PFX, _key_count)(struct SNAME * _map_, K key); \ + size_t CMC_(PFX, _capacity)(struct SNAME * _map_); \ + double CMC_(PFX, _load)(struct SNAME * _map_); \ + int CMC_(PFX, _flag)(struct SNAME * _map_); \ + /* Collection Utility */ \ + bool CMC_(PFX, _resize)(struct SNAME * _map_, size_t capacity); \ + struct SNAME *CMC_(PFX, _copy_of)(struct SNAME * _map_); \ + bool CMC_(PFX, _equals)(struct SNAME * _map1_, struct SNAME * _map2_); /* ------------------------------------------------------------------------- * Source @@ -1111,316 +1042,6 @@ static const char *cmc_cmc_string_fmt_hashmultimap = "struct %s<%s, %s> " return true; \ } \ \ - struct cmc_string CMC_(PFX, _to_string)(struct SNAME * _map_) \ - { \ - struct cmc_string str; \ - struct SNAME *m_ = _map_; \ - \ - int n = snprintf( \ - str.s, cmc_string_len, cmc_cmc_string_fmt_hashmultimap, #SNAME, \ - #K, #V, m_, m_->buffer, m_->capacity, m_->count, m_->load, \ - m_->flag, m_->f_key, m_->f_val, m_->alloc, m_->callbacks); \ - \ - return n >= 0 ? str : (struct cmc_string){ 0 }; \ - } \ - \ - bool CMC_(PFX, _print)(struct SNAME * _map_, FILE * fptr) \ - { \ - for (size_t i = 0; i < _map_->capacity; i++) \ - { \ - struct CMC_DEF_ENTRY(SNAME) *scan = _map_->buffer[i][0]; \ - \ - while (scan != NULL) \ - { \ - if (!_map_->f_key->str(fptr, scan->key) || \ - !_map_->f_val->str(fptr, scan->value)) \ - return false; \ - \ - scan = scan->next; \ - } \ - } \ - \ - return true; \ - } \ - \ - struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \ - { \ - struct CMC_DEF_ITER(SNAME) iter; \ - \ - iter.target = target; \ - iter.curr_entry = NULL; \ - iter.cursor = 0; \ - iter.index = 0; \ - iter.first = 0; \ - iter.last = 0; \ - iter.start = true; \ - iter.end = CMC_(PFX, _empty)(target); \ - \ - if (!CMC_(PFX, _empty)(target)) \ - { \ - for (size_t i = 0; i < target->capacity; i++) \ - { \ - if (target->buffer[i][0] != NULL) \ - { \ - iter.curr_entry = target->buffer[i][0]; \ - iter.first = i; \ - break; \ - } \ - } \ - \ - iter.cursor = iter.first; \ - \ - for (size_t i = target->capacity; i > 0; i--) \ - { \ - if (target->buffer[i - 1][1] != NULL) \ - { \ - iter.last = i - 1; \ - break; \ - } \ - } \ - } \ - \ - return iter; \ - } \ - \ - struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target) \ - { \ - struct CMC_DEF_ITER(SNAME) iter; \ - \ - iter.target = target; \ - iter.curr_entry = NULL; \ - iter.cursor = 0; \ - iter.index = 0; \ - iter.first = 0; \ - iter.last = 0; \ - iter.start = CMC_(PFX, _empty)(target); \ - iter.end = true; \ - \ - if (!CMC_(PFX, _empty)(target)) \ - { \ - for (size_t i = 0; i < target->capacity; i++) \ - { \ - if (target->buffer[i][0] != NULL) \ - { \ - iter.first = i; \ - break; \ - } \ - } \ - \ - for (size_t i = target->capacity; i > 0; i--) \ - { \ - if (target->buffer[i - 1][1] != NULL) \ - { \ - iter.curr_entry = target->buffer[i - 1][1]; \ - iter.last = i - 1; \ - break; \ - } \ - } \ - \ - iter.cursor = iter.last; \ - iter.index = target->count - 1; \ - } \ - \ - return iter; \ - } \ - \ - bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) \ - { \ - return CMC_(PFX, _empty)(iter->target) || iter->start; \ - } \ - \ - bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) \ - { \ - return CMC_(PFX, _empty)(iter->target) || iter->end; \ - } \ - \ - bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) \ - { \ - if (!CMC_(PFX, _empty)(iter->target)) \ - { \ - iter->cursor = iter->first; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = CMC_(PFX, _empty)(iter->target); \ - iter->curr_entry = iter->target->buffer[iter->first][0]; \ - \ - return true; \ - } \ - \ - return false; \ - } \ - \ - bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) \ - { \ - if (!CMC_(PFX, _empty)(iter->target)) \ - { \ - iter->cursor = iter->last; \ - iter->index = iter->target->count - 1; \ - iter->start = CMC_(PFX, _empty)(iter->target); \ - iter->end = true; \ - iter->curr_entry = iter->target->buffer[iter->last][1]; \ - \ - return true; \ - } \ - \ - return false; \ - } \ - \ - bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->curr_entry->next != NULL) \ - { \ - iter->curr_entry = iter->curr_entry->next; \ - iter->index++; \ - } \ - else \ - { \ - if (iter->cursor == iter->last) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - iter->cursor++; \ - \ - while (iter->target->buffer[iter->cursor][0] == NULL) \ - iter->cursor++; \ - \ - iter->curr_entry = iter->target->buffer[iter->cursor][0]; \ - \ - iter->index++; \ - } \ - \ - iter->start = CMC_(PFX, _empty)(iter->target); \ - \ - return true; \ - } \ - \ - bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->curr_entry->prev != NULL) \ - { \ - iter->curr_entry = iter->curr_entry->prev; \ - iter->index--; \ - } \ - else \ - { \ - if (iter->cursor == iter->first) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - iter->cursor--; \ - \ - while (iter->target->buffer[iter->cursor][1] == NULL) \ - iter->cursor--; \ - \ - iter->curr_entry = iter->target->buffer[iter->cursor][1]; \ - \ - iter->index--; \ - } \ - \ - iter->end = CMC_(PFX, _empty)(iter->target); \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, \ - size_t steps) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->index + 1 == iter->target->count) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index + steps >= iter->target->count) \ - return false; \ - \ - for (size_t i = 0; i < steps; i++) \ - CMC_(PFX, _iter_next)(iter); \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, \ - size_t steps) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->index == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index < steps) \ - return false; \ - \ - for (size_t i = 0; i < steps; i++) \ - CMC_(PFX, _iter_prev)(iter); \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator was able to be positioned at the */ \ - /* given index */ \ - bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, \ - size_t index) \ - { \ - if (index >= iter->target->count) \ - return false; \ - \ - if (iter->index > index) \ - return CMC_(PFX, _iter_rewind)(iter, iter->index - index); \ - else if (iter->index < index) \ - return CMC_(PFX, _iter_advance)(iter, index - iter->index); \ - \ - return true; \ - } \ - \ - K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter) \ - { \ - if (CMC_(PFX, _empty)(iter->target)) \ - return (K){ 0 }; \ - \ - return iter->curr_entry->key; \ - } \ - \ - V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \ - { \ - if (CMC_(PFX, _empty)(iter->target)) \ - return (V){ 0 }; \ - \ - return iter->curr_entry->value; \ - } \ - \ - V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter) \ - { \ - if (CMC_(PFX, _empty)(iter->target)) \ - return NULL; \ - \ - return &(iter->curr_entry->value); \ - } \ - \ - size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \ - { \ - return iter->index; \ - } \ - \ struct CMC_DEF_ENTRY(SNAME) * \ CMC_(PFX, _impl_new_entry)(struct SNAME * _map_, K key, V value) \ { \ diff --git a/src/ext/cmc/deque.h b/src/ext/cmc/deque.h index b868dff..6b06766 100644 --- a/src/ext/cmc/deque.h +++ b/src/ext/cmc/deque.h @@ -113,6 +113,7 @@ static const char *cmc_cmc_string_fmt_deque = "struct %s<%s> " CMC_PARAM_V(BODY)) #define CMC_EXT_CMC_DEQUE_ITER_HEADER_(PFX, SNAME, V) \ + \ /* Deque Iterator */ \ struct CMC_DEF_ITER(SNAME) \ { \ diff --git a/src/ext/cmc/hashmap.h b/src/ext/cmc/hashmap.h index 76d679b..c21658a 100644 --- a/src/ext/cmc/hashmap.h +++ b/src/ext/cmc/hashmap.h @@ -16,7 +16,7 @@ /** * All the EXT parts of CMC HashMap. */ -#define CMC_EXT_CMC_HASHMAP_PARTS INIT, STR +#define CMC_EXT_CMC_HASHMAP_PARTS INIT, ITER, STR /* Used by STR */ static const char *cmc_cmc_string_fmt_hashmap = "struct %s<%s, %s> " @@ -112,6 +112,341 @@ static const char *cmc_cmc_string_fmt_hashmap = "struct %s<%s, %s> " return _map_; \ } +/** + * ITER + */ +#define CMC_EXT_CMC_HASHMAP_ITER(BODY) \ + CMC_EXT_CMC_HASHMAP_ITER_HEADER(BODY) \ + CMC_EXT_CMC_HASHMAP_ITER_SOURCE(BODY) + +#define CMC_EXT_CMC_HASHMAP_ITER_HEADER(BODY) \ + CMC_EXT_CMC_HASHMAP_ITER_HEADER_(CMC_PARAM_PFX(BODY), \ + CMC_PARAM_SNAME(BODY), CMC_PARAM_K(BODY), \ + CMC_PARAM_V(BODY)) + +#define CMC_EXT_CMC_HASHMAP_ITER_SOURCE(BODY) \ + CMC_EXT_CMC_HASHMAP_ITER_SOURCE_(CMC_PARAM_PFX(BODY), \ + CMC_PARAM_SNAME(BODY), CMC_PARAM_K(BODY), \ + CMC_PARAM_V(BODY)) + +#define CMC_EXT_CMC_HASHMAP_ITER_HEADER_(PFX, SNAME, K, V) \ + \ + /* Hashmap Iterator */ \ + struct CMC_DEF_ITER(SNAME) \ + { \ + /* Target hashmap */ \ + struct SNAME *target; \ + \ + /* Cursor's position (index) */ \ + size_t cursor; \ + \ + /* Keeps track of relative index to the iteration of elements */ \ + size_t index; \ + \ + /* The index of the first element */ \ + size_t first; \ + \ + /* The index of the last element */ \ + size_t last; \ + \ + /* If the iterator has reached the start of the iteration */ \ + bool start; \ + \ + /* If the iterator has reached the end of the iteration */ \ + bool end; \ + }; \ + \ + /* Iterator Initialization */ \ + struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target); \ + struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target); \ + /* Iterator State */ \ + bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter); \ + bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter); \ + /* Iterator Movement */ \ + bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); \ + bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter); \ + bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter); \ + bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter); \ + bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, \ + size_t steps); \ + bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, \ + size_t steps); \ + bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, \ + size_t index); \ + /* Iterator Access */ \ + K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter); \ + V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); \ + V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter); \ + size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter); + +#define CMC_EXT_CMC_HASHMAP_ITER_SOURCE_(PFX, SNAME, K, V) \ + \ + struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \ + { \ + struct CMC_DEF_ITER(SNAME) iter; \ + \ + iter.target = target; \ + iter.cursor = 0; \ + iter.index = 0; \ + iter.first = 0; \ + iter.last = 0; \ + iter.start = true; \ + iter.end = CMC_(PFX, _empty)(target); \ + \ + if (!CMC_(PFX, _empty)(target)) \ + { \ + for (size_t i = 0; i < target->capacity; i++) \ + { \ + if (target->buffer[i].state == CMC_ES_FILLED) \ + { \ + iter.first = i; \ + break; \ + } \ + } \ + \ + iter.cursor = iter.first; \ + \ + for (size_t i = target->capacity; i > 0; i--) \ + { \ + if (target->buffer[i - 1].state == CMC_ES_FILLED) \ + { \ + iter.last = i - 1; \ + break; \ + } \ + } \ + } \ + \ + return iter; \ + } \ + \ + struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target) \ + { \ + struct CMC_DEF_ITER(SNAME) iter; \ + \ + iter.target = target; \ + iter.cursor = 0; \ + iter.index = 0; \ + iter.first = 0; \ + iter.last = 0; \ + iter.start = CMC_(PFX, _empty)(target); \ + iter.end = true; \ + \ + if (!CMC_(PFX, _empty)(target)) \ + { \ + for (size_t i = 0; i < target->capacity; i++) \ + { \ + if (target->buffer[i].state == CMC_ES_FILLED) \ + { \ + iter.first = i; \ + break; \ + } \ + } \ + \ + for (size_t i = target->capacity; i > 0; i--) \ + { \ + if (target->buffer[i - 1].state == CMC_ES_FILLED) \ + { \ + iter.last = i - 1; \ + break; \ + } \ + } \ + \ + iter.cursor = iter.last; \ + iter.index = target->count - 1; \ + } \ + \ + return iter; \ + } \ + \ + bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) \ + { \ + return CMC_(PFX, _empty)(iter->target) || iter->start; \ + } \ + \ + bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) \ + { \ + return CMC_(PFX, _empty)(iter->target) || iter->end; \ + } \ + \ + bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) \ + { \ + if (!CMC_(PFX, _empty)(iter->target)) \ + { \ + iter->cursor = iter->first; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = CMC_(PFX, _empty)(iter->target); \ + \ + return true; \ + } \ + \ + return false; \ + } \ + \ + bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) \ + { \ + if (!CMC_(PFX, _empty)(iter->target)) \ + { \ + iter->cursor = iter->last; \ + iter->index = iter->target->count - 1; \ + iter->start = CMC_(PFX, _empty)(iter->target); \ + iter->end = true; \ + \ + return true; \ + } \ + \ + return false; \ + } \ + \ + bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->index + 1 == iter->target->count) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + iter->start = CMC_(PFX, _empty)(iter->target); \ + \ + struct CMC_DEF_ENTRY(SNAME) *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 true; \ + } \ + \ + bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->index == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + iter->end = CMC_(PFX, _empty)(iter->target); \ + \ + struct CMC_DEF_ENTRY(SNAME) *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 true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, \ + size_t steps) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->index + 1 == iter->target->count) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index + steps >= iter->target->count) \ + return false; \ + \ + for (size_t i = 0; i < steps; i++) \ + CMC_(PFX, _iter_next)(iter); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, \ + size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->index == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index < steps) \ + return false; \ + \ + for (size_t i = 0; i < steps; i++) \ + CMC_(PFX, _iter_prev)(iter); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator was able to be positioned at the */ \ + /* given index */ \ + bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, \ + size_t index) \ + { \ + if (index >= iter->target->count) \ + return false; \ + \ + if (iter->index > index) \ + return CMC_(PFX, _iter_rewind)(iter, iter->index - index); \ + else if (iter->index < index) \ + return CMC_(PFX, _iter_advance)(iter, index - iter->index); \ + \ + return true; \ + } \ + \ + K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter) \ + { \ + if (CMC_(PFX, _empty)(iter->target)) \ + return (K){ 0 }; \ + \ + return iter->target->buffer[iter->cursor].key; \ + } \ + \ + V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \ + { \ + if (CMC_(PFX, _empty)(iter->target)) \ + return (V){ 0 }; \ + \ + return iter->target->buffer[iter->cursor].value; \ + } \ + \ + V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter) \ + { \ + if (CMC_(PFX, _empty)(iter->target)) \ + return NULL; \ + \ + return &(iter->target->buffer[iter->cursor].value); \ + } \ + \ + size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \ + { \ + return iter->index; \ + } + /** * STR * diff --git a/src/ext/cmc/hashmultimap.h b/src/ext/cmc/hashmultimap.h new file mode 100644 index 0000000..9a38aab --- /dev/null +++ b/src/ext/cmc/hashmultimap.h @@ -0,0 +1,472 @@ +/** + * hashmultimap.h + * + * Creation Date: 29/05/2020 + * + * Authors: + * Leonardo Vencovsky (https://github.com/LeoVen) + * + */ + +#ifndef CMC_EXT_CMC_HASHMULTIMAP_H +#define CMC_EXT_CMC_HASHMULTIMAP_H + +#include "../../cor/core.h" + +/** + * All the EXT parts of CMC HashMultiMap. + */ +#define CMC_EXT_CMC_HASHMULTIMAP_PARTS ITER, STR + +/* Used by STR */ +static const char *cmc_cmc_string_fmt_hashmultimap = "struct %s<%s, %s> " + "at %p { " + "buffer:%p, " + "capacity:%" PRIuMAX ", " + "count:%" PRIuMAX ", " + "load:%lf, " + "flag:%d, " + "f_key:%p, " + "f_val:%p, " + "alloc:%p, " + "callbacks:%p }"; + +/** + * ITER + */ +#define CMC_EXT_CMC_HASHMULTIMAP_ITER(BODY) \ + CMC_EXT_CMC_HASHMULTIMAP_ITER_HEADER(BODY) \ + CMC_EXT_CMC_HASHMULTIMAP_ITER_SOURCE(BODY) + +#define CMC_EXT_CMC_HASHMULTIMAP_ITER_HEADER(BODY) \ + CMC_EXT_CMC_HASHMULTIMAP_ITER_HEADER_( \ + CMC_PARAM_PFX(BODY), CMC_PARAM_SNAME(BODY), CMC_PARAM_K(BODY), \ + CMC_PARAM_V(BODY)) + +#define CMC_EXT_CMC_HASHMULTIMAP_ITER_SOURCE(BODY) \ + CMC_EXT_CMC_HASHMULTIMAP_ITER_SOURCE_( \ + CMC_PARAM_PFX(BODY), CMC_PARAM_SNAME(BODY), CMC_PARAM_K(BODY), \ + CMC_PARAM_V(BODY)) + +#define CMC_EXT_CMC_HASHMULTIMAP_ITER_HEADER_(PFX, SNAME, K, V) \ + \ + struct CMC_DEF_ITER(SNAME) \ + { \ + /* Target hashmultimap */ \ + struct SNAME *target; \ + \ + /* Current entry */ \ + struct CMC_DEF_ENTRY(SNAME) * curr_entry; \ + \ + /* Cursor`s position (index) */ \ + size_t cursor; \ + \ + /* Keeps track of relative index to the iteration of elements */ \ + size_t index; \ + \ + /* The index of the first element */ \ + size_t first; \ + \ + /* The index of the last element */ \ + size_t last; \ + \ + /* If the iterator has reached the start of the iteration */ \ + bool start; \ + \ + /* If the iterator has reached the end of the iteration */ \ + bool end; \ + }; \ + \ + /* Iterator Initialization */ \ + struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target); \ + struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target); \ + /* Iterator State */ \ + bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter); \ + bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter); \ + /* Iterator Movement */ \ + bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); \ + bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter); \ + bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter); \ + bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter); \ + bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, \ + size_t steps); \ + bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, \ + size_t steps); \ + bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, \ + size_t index); \ + /* Iterator Access */ \ + K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter); \ + V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); \ + V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter); \ + size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter); + +#define CMC_EXT_CMC_HASHMULTIMAP_ITER_SOURCE_(PFX, SNAME, K, V) \ + \ + struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \ + { \ + struct CMC_DEF_ITER(SNAME) iter; \ + \ + iter.target = target; \ + iter.curr_entry = NULL; \ + iter.cursor = 0; \ + iter.index = 0; \ + iter.first = 0; \ + iter.last = 0; \ + iter.start = true; \ + iter.end = CMC_(PFX, _empty)(target); \ + \ + if (!CMC_(PFX, _empty)(target)) \ + { \ + for (size_t i = 0; i < target->capacity; i++) \ + { \ + struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i][0]; \ + \ + if (entry && entry != CMC_ENTRY_DELETED) \ + { \ + iter.curr_entry = target->buffer[i][0]; \ + iter.first = i; \ + break; \ + } \ + } \ + \ + iter.cursor = iter.first; \ + \ + for (size_t i = target->capacity; i > 0; i--) \ + { \ + struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i - 1][1]; \ + \ + if (entry && entry != CMC_ENTRY_DELETED) \ + { \ + iter.last = i - 1; \ + break; \ + } \ + } \ + } \ + \ + return iter; \ + } \ + \ + struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target) \ + { \ + struct CMC_DEF_ITER(SNAME) iter; \ + \ + iter.target = target; \ + iter.curr_entry = NULL; \ + iter.cursor = 0; \ + iter.index = 0; \ + iter.first = 0; \ + iter.last = 0; \ + iter.start = CMC_(PFX, _empty)(target); \ + iter.end = true; \ + \ + if (!CMC_(PFX, _empty)(target)) \ + { \ + for (size_t i = 0; i < target->capacity; i++) \ + { \ + struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i][0]; \ + \ + if (entry && entry != CMC_ENTRY_DELETED) \ + { \ + iter.first = i; \ + break; \ + } \ + } \ + \ + for (size_t i = target->capacity; i > 0; i--) \ + { \ + struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i - 1][1]; \ + \ + if (entry && entry != CMC_ENTRY_DELETED) \ + { \ + iter.curr_entry = target->buffer[i - 1][1]; \ + iter.last = i - 1; \ + break; \ + } \ + } \ + \ + iter.cursor = iter.last; \ + iter.index = target->count - 1; \ + } \ + \ + return iter; \ + } \ + \ + bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) \ + { \ + return CMC_(PFX, _empty)(iter->target) || iter->start; \ + } \ + \ + bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) \ + { \ + return CMC_(PFX, _empty)(iter->target) || iter->end; \ + } \ + \ + bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) \ + { \ + if (!CMC_(PFX, _empty)(iter->target)) \ + { \ + iter->cursor = iter->first; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = CMC_(PFX, _empty)(iter->target); \ + iter->curr_entry = iter->target->buffer[iter->first][0]; \ + \ + return true; \ + } \ + \ + return false; \ + } \ + \ + bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) \ + { \ + if (!CMC_(PFX, _empty)(iter->target)) \ + { \ + iter->cursor = iter->last; \ + iter->index = iter->target->count - 1; \ + iter->start = CMC_(PFX, _empty)(iter->target); \ + iter->end = true; \ + iter->curr_entry = iter->target->buffer[iter->last][1]; \ + \ + return true; \ + } \ + \ + return false; \ + } \ + \ + bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->curr_entry->next != NULL) \ + { \ + iter->curr_entry = iter->curr_entry->next; \ + iter->index++; \ + } \ + else \ + { \ + if (iter->cursor == iter->last) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + iter->cursor++; \ + \ + while (iter->target->buffer[iter->cursor][0] == NULL) \ + iter->cursor++; \ + \ + iter->curr_entry = iter->target->buffer[iter->cursor][0]; \ + \ + iter->index++; \ + } \ + \ + iter->start = CMC_(PFX, _empty)(iter->target); \ + \ + return true; \ + } \ + \ + bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->curr_entry->prev != NULL) \ + { \ + iter->curr_entry = iter->curr_entry->prev; \ + iter->index--; \ + } \ + else \ + { \ + if (iter->cursor == iter->first) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + iter->cursor--; \ + \ + while (iter->target->buffer[iter->cursor][1] == NULL) \ + iter->cursor--; \ + \ + iter->curr_entry = iter->target->buffer[iter->cursor][1]; \ + \ + iter->index--; \ + } \ + \ + iter->end = CMC_(PFX, _empty)(iter->target); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, \ + size_t steps) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->index + 1 == iter->target->count) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index + steps >= iter->target->count) \ + return false; \ + \ + for (size_t i = 0; i < steps; i++) \ + CMC_(PFX, _iter_next)(iter); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, \ + size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->index == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index < steps) \ + return false; \ + \ + for (size_t i = 0; i < steps; i++) \ + CMC_(PFX, _iter_prev)(iter); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator was able to be positioned at the */ \ + /* given index */ \ + bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, \ + size_t index) \ + { \ + if (index >= iter->target->count) \ + return false; \ + \ + if (iter->index > index) \ + return CMC_(PFX, _iter_rewind)(iter, iter->index - index); \ + else if (iter->index < index) \ + return CMC_(PFX, _iter_advance)(iter, index - iter->index); \ + \ + return true; \ + } \ + \ + K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter) \ + { \ + if (CMC_(PFX, _empty)(iter->target)) \ + return (K){ 0 }; \ + \ + return iter->curr_entry->key; \ + } \ + \ + V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \ + { \ + if (CMC_(PFX, _empty)(iter->target)) \ + return (V){ 0 }; \ + \ + return iter->curr_entry->value; \ + } \ + \ + V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter) \ + { \ + if (CMC_(PFX, _empty)(iter->target)) \ + return NULL; \ + \ + return &(iter->curr_entry->value); \ + } \ + \ + size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \ + { \ + return iter->index; \ + } + +/** + * STR + */ +#define CMC_EXT_CMC_HASHMULTIMAP_STR(BODY) \ + CMC_EXT_CMC_HASHMULTIMAP_STR_HEADER(BODY) \ + CMC_EXT_CMC_HASHMULTIMAP_STR_SOURCE(BODY) + +#define CMC_EXT_CMC_HASHMULTIMAP_STR_HEADER(BODY) \ + CMC_EXT_CMC_HASHMULTIMAP_STR_HEADER_(CMC_PARAM_PFX(BODY), \ + CMC_PARAM_SNAME(BODY), \ + CMC_PARAM_K(BODY), CMC_PARAM_V(BODY)) + +#define CMC_EXT_CMC_HASHMULTIMAP_STR_SOURCE(BODY) \ + CMC_EXT_CMC_HASHMULTIMAP_STR_SOURCE_(CMC_PARAM_PFX(BODY), \ + CMC_PARAM_SNAME(BODY), \ + CMC_PARAM_K(BODY), CMC_PARAM_V(BODY)) + +#define CMC_EXT_CMC_HASHMULTIMAP_STR_HEADER_(PFX, SNAME, K, V) \ + \ + bool CMC_(PFX, _to_string)(struct SNAME * _map_, FILE * fptr); \ + bool CMC_(PFX, _print)(struct SNAME * _map_, FILE * fptr, \ + const char *start, const char *separator, \ + const char *end, const char *key_val_sep); + +#define CMC_EXT_CMC_HASHMULTIMAP_STR_SOURCE_(PFX, SNAME, K, V) \ + \ + bool CMC_(PFX, _to_string)(struct SNAME * _map_, FILE * fptr) \ + { \ + struct SNAME *m_ = _map_; \ + \ + return 0 <= fprintf(fptr, cmc_cmc_string_fmt_hashmultimap, \ + CMC_TO_STRING(SNAME), CMC_TO_STRING(K), \ + CMC_TO_STRING(V), m_, m_->buffer, m_->capacity, \ + m_->count, m_->load, m_->flag, m_->f_key, \ + m_->f_val, m_->alloc, m_->callbacks); \ + } \ + \ + bool CMC_(PFX, _print)(struct SNAME * _map_, FILE * fptr, \ + const char *start, const char *separator, \ + const char *end, const char *key_val_sep) \ + { \ + fprintf(fptr, "%s", start); \ + \ + size_t last = 0; \ + for (size_t i = _map_->capacity; i > 0; i--) \ + { \ + struct CMC_DEF_ENTRY(SNAME) *entry = _map_->buffer[i - 1][1]; \ + \ + if (entry && entry != CMC_ENTRY_DELETED) \ + { \ + last = i - 1; \ + break; \ + } \ + } \ + \ + for (size_t i = 0; i < _map_->capacity; i++) \ + { \ + struct CMC_DEF_ENTRY(SNAME) *scan = _map_->buffer[i][0]; \ + \ + while (scan != NULL) \ + { \ + if (!_map_->f_key->str(fptr, scan->key)) \ + return false; \ + \ + fprintf(fptr, "%s", key_val_sep); \ + \ + if (!_map_->f_val->str(fptr, scan->value)) \ + return false; \ + \ + scan = scan->next; \ + \ + if (i + 1 < last) \ + fprintf(fptr, "%s", separator); \ + } \ + } \ + \ + fprintf(fptr, "%s", end); \ + \ + return true; \ + } + +#endif /* CMC_EXT_CMC_HASHMULTIMAP_H */ diff --git a/src/macro_collections.h b/src/macro_collections.h index 2364541..06fc4bd 100644 --- a/src/macro_collections.h +++ b/src/macro_collections.h @@ -12,42 +12,43 @@ #define CMC_MACRO_COLLECTIONS_H // clang-format off -#include "cmc/bitset.h" /* Added in 30/04/2020 */ -#include "cmc/deque.h" /* Added in 20/03/2019 */ -#include "cmc/hashbidimap.h" /* Added in 26/09/2019 */ -#include "cmc/hashmap.h" /* Added in 03/04/2019 */ -#include "cmc/hashmultimap.h" /* Added in 26/04/2019 */ -#include "cmc/hashmultiset.h" /* Added in 10/04/2019 */ -#include "cmc/hashset.h" /* Added in 01/04/2019 */ -#include "cmc/heap.h" /* Added in 25/03/2019 */ -#include "cmc/intervalheap.h" /* Added in 06/07/2019 */ -#include "cmc/linkedlist.h" /* Added in 22/03/2019 */ -#include "cmc/list.h" /* Added in 12/02/2019 */ -#include "cmc/queue.h" /* Added in 15/02/2019 */ -#include "cmc/sortedlist.h" /* Added in 17/09/2019 */ -#include "cmc/stack.h" /* Added in 14/02/2019 */ -#include "cmc/treemap.h" /* Added in 28/03/2019 */ -#include "cmc/treeset.h" /* Added in 27/03/2019 */ +#include "cmc/bitset.h" /* Added in 30/04/2020 */ +#include "cmc/deque.h" /* Added in 20/03/2019 */ +#include "cmc/hashbidimap.h" /* Added in 26/09/2019 */ +#include "cmc/hashmap.h" /* Added in 03/04/2019 */ +#include "cmc/hashmultimap.h" /* Added in 26/04/2019 */ +#include "cmc/hashmultiset.h" /* Added in 10/04/2019 */ +#include "cmc/hashset.h" /* Added in 01/04/2019 */ +#include "cmc/heap.h" /* Added in 25/03/2019 */ +#include "cmc/intervalheap.h" /* Added in 06/07/2019 */ +#include "cmc/linkedlist.h" /* Added in 22/03/2019 */ +#include "cmc/list.h" /* Added in 12/02/2019 */ +#include "cmc/queue.h" /* Added in 15/02/2019 */ +#include "cmc/sortedlist.h" /* Added in 17/09/2019 */ +#include "cmc/stack.h" /* Added in 14/02/2019 */ +#include "cmc/treemap.h" /* Added in 28/03/2019 */ +#include "cmc/treeset.h" /* Added in 27/03/2019 */ -#include "cor/alloc.h" /* Added in 24/05/2020 */ -#include "cor/bitset.h" /* Added in 20/05/2020 */ -#include "cor/callbacks.h" /* Added in 24/05/2020 */ -#include "cor/core.h" /* Added in 17/03/2020 */ -#include "cor/flags.h" /* Added in 14/05/2020 */ -#include "cor/ftable.h" /* Added in 27/05/2020 */ -#include "cor/hashtable.h" /* Added in 17/03/2020 */ +#include "cor/alloc.h" /* Added in 24/05/2020 */ +#include "cor/bitset.h" /* Added in 20/05/2020 */ +#include "cor/callbacks.h" /* Added in 24/05/2020 */ +#include "cor/core.h" /* Added in 17/03/2020 */ +#include "cor/flags.h" /* Added in 14/05/2020 */ +#include "cor/ftable.h" /* Added in 27/05/2020 */ +#include "cor/hashtable.h" /* Added in 17/03/2020 */ -#include "ext/cmc/deque.h" /* Added in 25/05/2020 */ -#include "ext/cmc/hashmap.h" /* Added in 25/05/2020 */ +#include "ext/cmc/deque.h" /* Added in 25/05/2020 */ +#include "ext/cmc/hashmap.h" /* Added in 25/05/2020 */ +#include "ext/cmc/hashmultimap.h" /* Added in 29/05/2020 */ -#include "utl/assert.h" /* Added in 27/06/2019 */ -#include "utl/foreach.h" /* Added in 25/02/2019 */ -#include "utl/futils.h" /* Added in 15/04/2020 */ -#include "utl/log.h" /* Added in 21/06/2019 */ -#include "utl/mutex.h" /* Added in 14/05/2020 */ -#include "utl/test.h" /* Added in 26/06/2019 */ -#include "utl/thread.h" /* Added in 14/05/2020 */ -#include "utl/timer.h" /* Added in 12/04/2019 */ +#include "utl/assert.h" /* Added in 27/06/2019 */ +#include "utl/foreach.h" /* Added in 25/02/2019 */ +#include "utl/futils.h" /* Added in 15/04/2020 */ +#include "utl/log.h" /* Added in 21/06/2019 */ +#include "utl/mutex.h" /* Added in 14/05/2020 */ +#include "utl/test.h" /* Added in 26/06/2019 */ +#include "utl/thread.h" /* Added in 14/05/2020 */ +#include "utl/timer.h" /* Added in 12/04/2019 */ // clang-format on /** diff --git a/tests/main/src/deque.c b/tests/main/src/deque.c index 00c5992..ef319b7 100644 --- a/tests/main/src/deque.c +++ b/tests/main/src/deque.c @@ -361,27 +361,6 @@ _Bool d_equals(struct deque *_deque1_, struct deque *_deque2_) } return 1; } -struct cmc_string d_to_string(struct deque *_deque_) -{ - struct cmc_string str; - struct deque *d_ = _deque_; - int n = snprintf(str.s, cmc_string_len, cmc_cmc_string_fmt_deque, - "CMC_PARAM_SNAME((d, deque, , , size_t))", - "CMC_PARAM_V((d, deque, , , size_t))", d_, d_->buffer, - d_->capacity, d_->count, d_->front, d_->back, d_->flag, - d_->f_val, d_->alloc, d_->callbacks); - return n >= 0 ? str : (struct cmc_string){ 0 }; -} -_Bool d_print(struct deque *_deque_, FILE *fptr) -{ - for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) - { - if (!_deque_->f_val->str(fptr, _deque_->buffer[i])) - return 0; - i = (i + 1) % _deque_->capacity; - } - return 1; -} struct deque_iter d_iter_start(struct deque *target) { struct deque_iter iter; diff --git a/tests/main/src/hashmap.c b/tests/main/src/hashmap.c index 11c6b46..63ccc60 100644 --- a/tests/main/src/hashmap.c +++ b/tests/main/src/hashmap.c @@ -552,32 +552,6 @@ _Bool hm_equals(struct hashmap *_map1_, struct hashmap *_map2_) } return 1; } -struct cmc_string hm_to_string(struct hashmap *_map_) -{ - struct cmc_string str; - struct hashmap *m_ = _map_; - int n = snprintf(str.s, cmc_string_len, cmc_cmc_string_fmt_hashmap, - "CMC_PARAM_SNAME((hm, hashmap, , size_t, size_t))", - "CMC_PARAM_K((hm, hashmap, , size_t, size_t))", - "CMC_PARAM_V((hm, hashmap, , size_t, size_t))", m_, - m_->buffer, m_->capacity, m_->count, m_->load, m_->flag, - m_->f_key, m_->f_val, m_->alloc, m_->callbacks); - return n >= 0 ? str : (struct cmc_string){ 0 }; -} -_Bool hm_print(struct hashmap *_map_, FILE *fptr) -{ - for (size_t i = 0; i < _map_->capacity; i++) - { - struct hashmap_entry *entry = &(_map_->buffer[i]); - if (entry->state == CMC_ES_FILLED) - { - if (!_map_->f_key->str(fptr, entry->key) || - !_map_->f_val->str(fptr, entry->value)) - return 0; - } - } - return 1; -} struct hashmap_iter hm_iter_start(struct hashmap *target) { struct hashmap_iter iter; diff --git a/tests/main/src/hashmultimap.c b/tests/main/src/hashmultimap.c index ae280f9..dd64884 100644 --- a/tests/main/src/hashmultimap.c +++ b/tests/main/src/hashmultimap.c @@ -720,33 +720,6 @@ _Bool hmm_equals(struct hashmultimap *_map1_, struct hashmultimap *_map2_) } return 1; } -struct cmc_string hmm_to_string(struct hashmultimap *_map_) -{ - struct cmc_string str; - struct hashmultimap *m_ = _map_; - int n = snprintf(str.s, cmc_string_len, cmc_cmc_string_fmt_hashmultimap, - "CMC_PARAM_SNAME((hmm, hashmultimap, , size_t, size_t))", - "CMC_PARAM_K((hmm, hashmultimap, , size_t, size_t))", - "CMC_PARAM_V((hmm, hashmultimap, , size_t, size_t))", m_, - m_->buffer, m_->capacity, m_->count, m_->load, m_->flag, - m_->f_key, m_->f_val, m_->alloc, m_->callbacks); - return n >= 0 ? str : (struct cmc_string){ 0 }; -} -_Bool hmm_print(struct hashmultimap *_map_, FILE *fptr) -{ - for (size_t i = 0; i < _map_->capacity; i++) - { - struct hashmultimap_entry *scan = _map_->buffer[i][0]; - while (scan != ((void *)0)) - { - if (!_map_->f_key->str(fptr, scan->key) || - !_map_->f_val->str(fptr, scan->value)) - return 0; - scan = scan->next; - } - } - return 1; -} struct hashmultimap_iter hmm_iter_start(struct hashmultimap *target) { struct hashmultimap_iter iter; diff --git a/tests/main/unt/utl.c b/tests/main/unt/utl.c index 84cc860..44376a7 100644 --- a/tests/main/unt/utl.c +++ b/tests/main/unt/utl.c @@ -2,6 +2,15 @@ #ifndef CMC_UNIT_TEST_UTL__ #define CMC_UNIT_TEST_UTL__ +/** + * TEMPORARY + */ +struct cmc_string +{ + char s[400]; +}; +static const size_t cmc_string_len = 400; + #include #include #include diff --git a/tests/to_string.c b/tests/to_string.c index 5794037..18acdde 100644 --- a/tests/to_string.c +++ b/tests/to_string.c @@ -3,8 +3,9 @@ #include "macro_collections.h" // clang-format off -C_MACRO_COLLECTIONS_ALL(CMC, DEQUE, ( d, deque, , , int)) -C_MACRO_COLLECTIONS_ALL(CMC, HASHMAP, ( hm, hashmap, , int, int)) +C_MACRO_COLLECTIONS_ALL(CMC, DEQUE, ( d, deque, , , int)) +C_MACRO_COLLECTIONS_ALL(CMC, HASHMAP, ( hm, hashmap, , int, int)) +C_MACRO_COLLECTIONS_ALL(CMC, HASHMULTIMAP, (hmm, hashmultimap, , int, int)) struct { @@ -21,16 +22,22 @@ int main(void) struct deque *d = d_new(100, (struct deque_fval *)&int_ftab); struct hashmap *hm = hm_new(100, 0.6, (struct hashmap_fkey *)&int_ftab, (struct hashmap_fval *)&int_ftab); + struct hashmultimap *hmm = hmm_new(100, 0.6, + (struct hashmultimap_fkey *)&int_ftab, + (struct hashmultimap_fval *)&int_ftab); d_to_string(d, stdout); d_print(d, stdout, "\n[ ", ", ", " ]\n"); hm_to_string(hm, stdout); hm_print(hm, stdout, "\n[ {", "}, {", "} ]\n", " : "); + hmm_to_string(hmm, stdout); + hmm_print(hmm, stdout, "\n[ {", "}, {", "} ]\n", " : "); for (int i = 0; i < 20; i++) { d_push_back(d, i); hm_insert(hm, i, i); + hmm_insert(hmm, i, i); } fprintf(stdout, "\n"); @@ -39,9 +46,12 @@ int main(void) d_print(d, stdout, "\n[ ", ", ", " ]\n"); hm_to_string(hm, stdout); hm_print(hm, stdout, "\n[ {", "}, {", "} ]\n", " : "); + hmm_to_string(hmm, stdout); + hmm_print(hmm, stdout, "\n[ {", "}, {", "} ]\n", " : "); d_free(d); hm_free(hm); + hmm_free(hmm); } // clang-format on