From 2ca2210a7770cfb8ceff4ad582c3e4baac89fe35 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Mon, 16 Sep 2019 14:45:24 -0300 Subject: [PATCH] Added CMC prefix to all macros and removed FMOD --- src/cmc/deque.h | 306 +++--- src/cmc/hashmap.h | 1683 +++++++++++++++---------------- src/cmc/hashset.h | 1894 +++++++++++++++++------------------ src/cmc/heap.h | 280 +++--- src/cmc/linkedlist.h | 1772 ++++++++++++++++----------------- src/cmc/list.h | 330 +++---- src/cmc/queue.h | 286 +++--- src/cmc/stack.h | 988 +++++++++--------- src/cmc/treemap.h | 364 +++---- src/cmc/treeset.h | 170 ++-- src/ext/intervalheap.h | 316 +++--- src/ext/multimap.h | 2088 +++++++++++++++++++-------------------- src/ext/multiset.h | 406 ++++---- src/macro_collections.h | 26 +- src/utl/foreach.h | 40 +- tests/contains.c | 26 +- tests/foreach.c | 82 +- tests/iterators.c | 26 +- tests/sep/sep.c | 26 +- tests/sep/sep.h | 26 +- tests/types.c | 255 +++-- 21 files changed, 5691 insertions(+), 5699 deletions(-) diff --git a/src/cmc/deque.h b/src/cmc/deque.h index 0e23aeb..eff449e 100644 --- a/src/cmc/deque.h +++ b/src/cmc/deque.h @@ -37,135 +37,135 @@ #include #include "../utl/cmc_string.h" -#define DEQUE_GENERATE(PFX, SNAME, FMOD, V) \ - DEQUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - DEQUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) +#define CMC_GENERATE_DEQUE(PFX, SNAME, V) \ + CMC_GENERATE_DEQUE_HEADER(PFX, SNAME, V) \ + CMC_GENERATE_DEQUE_SOURCE(PFX, SNAME, V) -#define DEQUE_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \ - DEQUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) +#define CMC_WRAPGEN_DEQUE_HEADER(PFX, SNAME, K, V) \ + CMC_GENERATE_DEQUE_HEADER(PFX, SNAME, V) -#define DEQUE_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \ - DEQUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) +#define CMC_WRAPGEN_DEQUE_SOURCE(PFX, SNAME, K, V) \ + CMC_GENERATE_DEQUE_SOURCE(PFX, SNAME, V) /* HEADER ********************************************************************/ -#define DEQUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - \ - /* Deque Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Dynamic circular array of elements */ \ - V *buffer; \ - \ - /* Current circular array capacity */ \ - size_t capacity; \ - \ - /* Current amount of elements */ \ - size_t count; \ - \ - /* Index representing the front of the deque */ \ - size_t front; \ - \ - /* Index representing the back of the deque */ \ - size_t back; \ - \ - /* Function that returns an iterator to the start of the deque */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the deque */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Deque Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target deque */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - FMOD SNAME *PFX##_new(size_t capacity); \ - FMOD void PFX##_clear(SNAME *_deque_, void (*deallocator)(V)); \ - FMOD void PFX##_free(SNAME *_deque_, void (*deallocator)(V)); \ - /* Collection Input and Output */ \ - FMOD bool PFX##_push_front(SNAME *_deque_, V element); \ - FMOD bool PFX##_push_back(SNAME *_deque_, V element); \ - FMOD bool PFX##_pop_front(SNAME *_deque_); \ - FMOD bool PFX##_pop_back(SNAME *_deque_); \ - /* Conditional Input and Output */ \ - FMOD bool PFX##_push_front_if(SNAME *_deque_, V element, bool condition); \ - FMOD bool PFX##_push_back_if(SNAME *_deque_, V element, bool condition); \ - FMOD bool PFX##_pop_front_if(SNAME *_deque_, bool condition); \ - FMOD bool PFX##_pop_back_if(SNAME *_deque_, bool condition); \ - /* Element Access */ \ - FMOD V PFX##_front(SNAME *_deque_); \ - FMOD V PFX##_back(SNAME *_deque_); \ - /* Collection State */ \ - FMOD bool PFX##_contains(SNAME *_deque_, V element, int (*comparator)(V, V)); \ - FMOD bool PFX##_empty(SNAME *_deque_); \ - FMOD bool PFX##_full(SNAME *_deque_); \ - FMOD size_t PFX##_count(SNAME *_deque_); \ - FMOD size_t PFX##_capacity(SNAME *_deque_); \ - /* Collection Utility */ \ - FMOD SNAME *PFX##_copy_of(SNAME *_deque_, V (*copy_func)(V)); \ - FMOD bool PFX##_equals(SNAME *_deque1_, SNAME *_deque2_, int (*comparator)(V, V)); \ - FMOD cmc_string PFX##_to_string(SNAME *_deque_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ - FMOD void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - FMOD V PFX##_iter_value(SNAME##_iter *iter); \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ - /* Default Value */ \ - static inline V PFX##_impl_default_value(void) \ - { \ - V _empty_value_; \ - \ - memset(&_empty_value_, 0, sizeof(V)); \ - \ - return _empty_value_; \ - } \ - \ +#define CMC_GENERATE_DEQUE_HEADER(PFX, SNAME, V) \ + \ + /* Deque Structure */ \ + typedef struct SNAME##_s \ + { \ + /* Dynamic circular array of elements */ \ + V *buffer; \ + \ + /* Current circular array capacity */ \ + size_t capacity; \ + \ + /* Current amount of elements */ \ + size_t count; \ + \ + /* Index representing the front of the deque */ \ + size_t front; \ + \ + /* Index representing the back of the deque */ \ + size_t back; \ + \ + /* Function that returns an iterator to the start of the deque */ \ + struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + \ + /* Function that returns an iterator to the end of the deque */ \ + struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + \ + } SNAME, *SNAME##_ptr; \ + \ + /* Deque Iterator */ \ + typedef struct SNAME##_iter_s \ + { \ + /* Target deque */ \ + struct SNAME##_s *target; \ + \ + /* Cursor's position (index) */ \ + size_t cursor; \ + \ + /* Keeps track of relative index to the iteration of elements */ \ + size_t index; \ + \ + /* If the iterator has reached the start of the iteration */ \ + bool start; \ + \ + /* If the iterator has reached the end of the iteration */ \ + bool end; \ + \ + } SNAME##_iter, *SNAME##_iter_ptr; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + SNAME *PFX##_new(size_t capacity); \ + void PFX##_clear(SNAME *_deque_, void (*deallocator)(V)); \ + void PFX##_free(SNAME *_deque_, void (*deallocator)(V)); \ + /* Collection Input and Output */ \ + bool PFX##_push_front(SNAME *_deque_, V element); \ + bool PFX##_push_back(SNAME *_deque_, V element); \ + bool PFX##_pop_front(SNAME *_deque_); \ + bool PFX##_pop_back(SNAME *_deque_); \ + /* Conditional Input and Output */ \ + bool PFX##_push_front_if(SNAME *_deque_, V element, bool condition); \ + bool PFX##_push_back_if(SNAME *_deque_, V element, bool condition); \ + bool PFX##_pop_front_if(SNAME *_deque_, bool condition); \ + bool PFX##_pop_back_if(SNAME *_deque_, bool condition); \ + /* Element Access */ \ + V PFX##_front(SNAME *_deque_); \ + V PFX##_back(SNAME *_deque_); \ + /* Collection State */ \ + bool PFX##_contains(SNAME *_deque_, V element, int (*comparator)(V, V)); \ + bool PFX##_empty(SNAME *_deque_); \ + bool PFX##_full(SNAME *_deque_); \ + size_t PFX##_count(SNAME *_deque_); \ + size_t PFX##_capacity(SNAME *_deque_); \ + /* Collection Utility */ \ + SNAME *PFX##_copy_of(SNAME *_deque_, V (*copy_func)(V)); \ + bool PFX##_equals(SNAME *_deque1_, SNAME *_deque2_, int (*comparator)(V, V)); \ + cmc_string PFX##_to_string(SNAME *_deque_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + SNAME##_iter *PFX##_iter_new(SNAME *target); \ + void PFX##_iter_free(SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(SNAME##_iter *iter); \ + bool PFX##_iter_end(SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(SNAME##_iter *iter); \ + void PFX##_iter_to_end(SNAME##_iter *iter); \ + bool PFX##_iter_next(SNAME##_iter *iter); \ + bool PFX##_iter_prev(SNAME##_iter *iter); \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + V PFX##_iter_value(SNAME##_iter *iter); \ + V *PFX##_iter_rvalue(SNAME##_iter *iter); \ + size_t PFX##_iter_index(SNAME##_iter *iter); \ + \ + /* Default Value */ \ + static inline V PFX##_impl_default_value(void) \ + { \ + V _empty_value_; \ + \ + memset(&_empty_value_, 0, sizeof(V)); \ + \ + return _empty_value_; \ + } \ + \ /* SOURCE ********************************************************************/ -#define DEQUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ +#define CMC_GENERATE_DEQUE_SOURCE(PFX, SNAME, V) \ \ /* Implementation Detail Functions */ \ static bool PFX##_impl_grow(SNAME *_deque_); \ static SNAME##_iter PFX##_impl_it_start(SNAME *_deque_); \ static SNAME##_iter PFX##_impl_it_end(SNAME *_deque_); \ \ - FMOD SNAME *PFX##_new(size_t capacity) \ + SNAME *PFX##_new(size_t capacity) \ { \ if (capacity < 1) \ return NULL; \ @@ -196,7 +196,7 @@ return _deque_; \ } \ \ - FMOD void PFX##_clear(SNAME *_deque_, void (*deallocator)(V)) \ + void PFX##_clear(SNAME *_deque_, void (*deallocator)(V)) \ { \ if (deallocator) \ { \ @@ -213,7 +213,7 @@ _deque_->back = 0; \ } \ \ - FMOD void PFX##_free(SNAME *_deque_, void (*deallocator)(V)) \ + void PFX##_free(SNAME *_deque_, void (*deallocator)(V)) \ { \ if (deallocator) \ { \ @@ -227,7 +227,7 @@ free(_deque_); \ } \ \ - FMOD bool PFX##_push_front(SNAME *_deque_, V element) \ + bool PFX##_push_front(SNAME *_deque_, V element) \ { \ if (PFX##_full(_deque_)) \ { \ @@ -244,7 +244,7 @@ return true; \ } \ \ - FMOD bool PFX##_push_back(SNAME *_deque_, V element) \ + bool PFX##_push_back(SNAME *_deque_, V element) \ { \ if (PFX##_full(_deque_)) \ { \ @@ -261,7 +261,7 @@ return true; \ } \ \ - FMOD bool PFX##_pop_front(SNAME *_deque_) \ + bool PFX##_pop_front(SNAME *_deque_) \ { \ if (PFX##_empty(_deque_)) \ return false; \ @@ -275,7 +275,7 @@ return true; \ } \ \ - FMOD bool PFX##_pop_back(SNAME *_deque_) \ + bool PFX##_pop_back(SNAME *_deque_) \ { \ if (PFX##_empty(_deque_)) \ return false; \ @@ -289,7 +289,7 @@ return true; \ } \ \ - FMOD bool PFX##_push_front_if(SNAME *_deque_, V element, bool condition) \ + bool PFX##_push_front_if(SNAME *_deque_, V element, bool condition) \ { \ if (condition) \ return PFX##_push_front(_deque_, element); \ @@ -297,7 +297,7 @@ return false; \ } \ \ - FMOD bool PFX##_push_back_if(SNAME *_deque_, V element, bool condition) \ + bool PFX##_push_back_if(SNAME *_deque_, V element, bool condition) \ { \ if (condition) \ return PFX##_push_back(_deque_, element); \ @@ -305,7 +305,7 @@ return false; \ } \ \ - FMOD bool PFX##_pop_front_if(SNAME *_deque_, bool condition) \ + bool PFX##_pop_front_if(SNAME *_deque_, bool condition) \ { \ if (condition) \ return PFX##_pop_front(_deque_); \ @@ -313,7 +313,7 @@ return false; \ } \ \ - FMOD bool PFX##_pop_back_if(SNAME *_deque_, bool condition) \ + bool PFX##_pop_back_if(SNAME *_deque_, bool condition) \ { \ if (condition) \ return PFX##_pop_back(_deque_); \ @@ -321,7 +321,7 @@ return false; \ } \ \ - FMOD V PFX##_front(SNAME *_deque_) \ + V PFX##_front(SNAME *_deque_) \ { \ if (PFX##_empty(_deque_)) \ return PFX##_impl_default_value(); \ @@ -329,7 +329,7 @@ return _deque_->buffer[_deque_->front]; \ } \ \ - FMOD V PFX##_back(SNAME *_deque_) \ + V PFX##_back(SNAME *_deque_) \ { \ if (PFX##_empty(_deque_)) \ return PFX##_impl_default_value(); \ @@ -337,7 +337,7 @@ return _deque_->buffer[(_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1]; \ } \ \ - FMOD bool PFX##_contains(SNAME *_deque_, V element, int (*comparator)(V, V)) \ + bool PFX##_contains(SNAME *_deque_, V element, int (*comparator)(V, V)) \ { \ for (size_t i = _deque_->front, j = 0; j < _deque_->count; i = (i + 1) % _deque_->count, j++) \ { \ @@ -348,27 +348,27 @@ return false; \ } \ \ - FMOD bool PFX##_empty(SNAME *_deque_) \ + bool PFX##_empty(SNAME *_deque_) \ { \ return _deque_->count == 0; \ } \ \ - FMOD bool PFX##_full(SNAME *_deque_) \ + bool PFX##_full(SNAME *_deque_) \ { \ return _deque_->count >= _deque_->capacity; \ } \ \ - FMOD size_t PFX##_count(SNAME *_deque_) \ + size_t PFX##_count(SNAME *_deque_) \ { \ return _deque_->count; \ } \ \ - FMOD size_t PFX##_capacity(SNAME *_deque_) \ + size_t PFX##_capacity(SNAME *_deque_) \ { \ return _deque_->capacity; \ } \ \ - FMOD SNAME *PFX##_copy_of(SNAME *_deque_, V (*copy_func)(V)) \ + SNAME *PFX##_copy_of(SNAME *_deque_, V (*copy_func)(V)) \ { \ SNAME *result = PFX##_new(_deque_->capacity); \ \ @@ -395,7 +395,7 @@ return result; \ } \ \ - FMOD bool PFX##_equals(SNAME *_deque1_, SNAME *_deque2_, int (*comparator)(V, V)) \ + bool PFX##_equals(SNAME *_deque1_, SNAME *_deque2_, int (*comparator)(V, V)) \ { \ if (PFX##_count(_deque1_) != PFX##_count(_deque2_)) \ return false; \ @@ -413,7 +413,7 @@ return true; \ } \ \ - FMOD cmc_string PFX##_to_string(SNAME *_deque_) \ + cmc_string PFX##_to_string(SNAME *_deque_) \ { \ cmc_string str; \ SNAME *d_ = _deque_; \ @@ -425,7 +425,7 @@ return str; \ } \ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ + SNAME##_iter *PFX##_iter_new(SNAME *target) \ { \ SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ \ @@ -437,12 +437,12 @@ return iter; \ } \ \ - FMOD void PFX##_iter_free(SNAME##_iter *iter) \ + void PFX##_iter_free(SNAME##_iter *iter) \ { \ free(iter); \ } \ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ { \ iter->target = target; \ iter->cursor = target->front; \ @@ -451,17 +451,17 @@ iter->end = PFX##_empty(target); \ } \ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ + bool PFX##_iter_start(SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->start; \ } \ \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ + bool PFX##_iter_end(SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->end; \ } \ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ + void PFX##_iter_to_start(SNAME##_iter *iter) \ { \ iter->cursor = iter->target->front; \ iter->index = 0; \ @@ -469,7 +469,7 @@ iter->end = PFX##_empty(iter->target); \ } \ \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ + void PFX##_iter_to_end(SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ { \ @@ -486,7 +486,7 @@ iter->end = true; \ } \ \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ + bool PFX##_iter_next(SNAME##_iter *iter) \ { \ if (iter->end) \ return false; \ @@ -505,7 +505,7 @@ return true; \ } \ \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ + bool PFX##_iter_prev(SNAME##_iter *iter) \ { \ if (iter->start) \ return false; \ @@ -525,7 +525,7 @@ } \ \ /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ { \ if (iter->end) \ return false; \ @@ -548,7 +548,7 @@ } \ \ /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ { \ if (iter->start) \ return false; \ @@ -576,7 +576,7 @@ } \ \ /* Returns true only if the iterator was able to be positioned at the given index */ \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ { \ if (index >= PFX##_count(iter->target)) \ return false; \ @@ -589,7 +589,7 @@ return true; \ } \ \ - FMOD V PFX##_iter_value(SNAME##_iter *iter) \ + V PFX##_iter_value(SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ return PFX##_impl_default_value(); \ @@ -597,7 +597,7 @@ return iter->target->buffer[iter->cursor]; \ } \ \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \ + V *PFX##_iter_rvalue(SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ return NULL; \ @@ -605,7 +605,7 @@ return &(iter->target->buffer[iter->cursor]); \ } \ \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ + size_t PFX##_iter_index(SNAME##_iter *iter) \ { \ return iter->index; \ } \ diff --git a/src/cmc/hashmap.h b/src/cmc/hashmap.h index 938f4ea..51fb88e 100644 --- a/src/cmc/hashmap.h +++ b/src/cmc/hashmap.h @@ -69,852 +69,853 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, #endif /* CMC_HASH_TABLE_SETUP */ -#define HASHMAP_GENERATE(PFX, SNAME, FMOD, K, V) \ - HASHMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \ - HASHMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) +#define CMC_GENERATE_HASHMAP(PFX, SNAME, K, V) \ + CMC_GENERATE_HASHMAP_HEADER(PFX, SNAME, K, V) \ + CMC_GENERATE_HASHMAP_SOURCE(PFX, SNAME, K, V) -#define HASHMAP_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \ - HASHMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) +#define CMC_WRAPGEN_HASHMAP_HEADER(PFX, SNAME, K, V) \ + CMC_GENERATE_HASHMAP_HEADER(PFX, SNAME, K, V) -#define HASHMAP_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \ - HASHMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) +#define CMC_WRAPGEN_HASHMAP_SOURCE(PFX, SNAME, K, V) \ + CMC_GENERATE_HASHMAP_SOURCE(PFX, SNAME, K, V) /* HEADER ********************************************************************/ -#define HASHMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \ - \ - /* Hashmap Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Array of Entries */ \ - struct SNAME##_entry_s *buffer; \ - \ - /* Current array capacity */ \ - size_t capacity; \ - \ - /* Current amount of keys */ \ - size_t count; \ - \ - /* Load factor in range (0.0, 1.0) */ \ - double load; \ - \ - /* Key comparison function */ \ - int (*cmp)(K, K); \ - \ - /* Key hash function */ \ - size_t (*hash)(K); \ - \ - /* Function that returns an iterator to the start of the hashmap */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the hashmap */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Hashmap Entry */ \ - typedef struct SNAME##_entry_s \ - { \ - /* 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_e state; \ - \ - } SNAME##_entry, *SNAME##_entry_ptr; \ - \ - /* Hashmap Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target hashmap */ \ - struct SNAME##_s *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; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - FMOD SNAME *PFX##_new(size_t capacity, double load, int (*compare)(K, K), size_t (*hash)(K)); \ - FMOD void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)); \ - FMOD void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)); \ - /* Collection Input and Output */ \ - FMOD bool PFX##_insert(SNAME *_map_, K key, V value); \ - FMOD bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value); \ - FMOD bool PFX##_remove(SNAME *_map_, K key, V *out_value); \ - /* Conditional Input and Output */ \ - FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition); \ - FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *out_value, bool condition); \ - /* Element Access */ \ - FMOD bool PFX##_max(SNAME *_map_, K *key, V *value); \ - FMOD bool PFX##_min(SNAME *_map_, K *key, V *value); \ - FMOD V PFX##_get(SNAME *_map_, K key); \ - FMOD V *PFX##_get_ref(SNAME *_map_, K key); \ - /* Collection State */ \ - FMOD bool PFX##_contains(SNAME *_map_, K key); \ - FMOD bool PFX##_empty(SNAME *_map_); \ - FMOD size_t PFX##_count(SNAME *_map_); \ - FMOD size_t PFX##_capacity(SNAME *_map_); \ - /* Collection Utility */ \ - FMOD SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)); \ - FMOD bool PFX##_equals(SNAME *_map1_, SNAME *_map2_, int (*value_comparator)(V, V)); \ - FMOD cmc_string PFX##_to_string(SNAME *_map_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ - FMOD void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - FMOD K PFX##_iter_key(SNAME##_iter *iter); \ - FMOD V PFX##_iter_value(SNAME##_iter *iter); \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ - /* Default Key */ \ - static inline K PFX##_impl_default_key(void) \ - { \ - K _empty_key_; \ - \ - memset(&_empty_key_, 0, sizeof(K)); \ - \ - return _empty_key_; \ - } \ - \ - /* Default Value */ \ - static inline V PFX##_impl_default_value(void) \ - { \ - V _empty_value_; \ - \ - memset(&_empty_value_, 0, sizeof(V)); \ - \ - return _empty_value_; \ - } \ - \ +#define CMC_GENERATE_HASHMAP_HEADER(PFX, SNAME, K, V) \ + \ + /* Hashmap Structure */ \ + typedef struct SNAME##_s \ + { \ + /* Array of Entries */ \ + struct SNAME##_entry_s *buffer; \ + \ + /* Current array capacity */ \ + size_t capacity; \ + \ + /* Current amount of keys */ \ + size_t count; \ + \ + /* Load factor in range (0.0, 1.0) */ \ + double load; \ + \ + /* Key comparison function */ \ + int (*cmp)(K, K); \ + \ + /* Key hash function */ \ + size_t (*hash)(K); \ + \ + /* Function that returns an iterator to the start of the hashmap */ \ + struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + \ + /* Function that returns an iterator to the end of the hashmap */ \ + struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + \ + } SNAME, *SNAME##_ptr; \ + \ + /* Hashmap Entry */ \ + typedef struct SNAME##_entry_s \ + { \ + /* 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_e state; \ + \ + } SNAME##_entry, *SNAME##_entry_ptr; \ + \ + /* Hashmap Iterator */ \ + typedef struct SNAME##_iter_s \ + { \ + /* Target hashmap */ \ + struct SNAME##_s *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; \ + \ + } SNAME##_iter, *SNAME##_iter_ptr; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + SNAME *PFX##_new(size_t capacity, double load, int (*compare)(K, K), size_t (*hash)(K)); \ + void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)); \ + void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)); \ + /* Collection Input and Output */ \ + bool PFX##_insert(SNAME *_map_, K key, V value); \ + bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value); \ + bool PFX##_remove(SNAME *_map_, K key, V *out_value); \ + /* Conditional Input and Output */ \ + bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition); \ + bool PFX##_remove_if(SNAME *_map_, K key, V *out_value, bool condition); \ + /* Element Access */ \ + bool PFX##_max(SNAME *_map_, K *key, V *value); \ + bool PFX##_min(SNAME *_map_, K *key, V *value); \ + V PFX##_get(SNAME *_map_, K key); \ + V *PFX##_get_ref(SNAME *_map_, K key); \ + /* Collection State */ \ + bool PFX##_contains(SNAME *_map_, K key); \ + bool PFX##_empty(SNAME *_map_); \ + size_t PFX##_count(SNAME *_map_); \ + size_t PFX##_capacity(SNAME *_map_); \ + /* Collection Utility */ \ + SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)); \ + bool PFX##_equals(SNAME *_map1_, SNAME *_map2_, int (*value_comparator)(V, V)); \ + cmc_string PFX##_to_string(SNAME *_map_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + SNAME##_iter *PFX##_iter_new(SNAME *target); \ + void PFX##_iter_free(SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(SNAME##_iter *iter); \ + bool PFX##_iter_end(SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(SNAME##_iter *iter); \ + void PFX##_iter_to_end(SNAME##_iter *iter); \ + bool PFX##_iter_next(SNAME##_iter *iter); \ + bool PFX##_iter_prev(SNAME##_iter *iter); \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + K PFX##_iter_key(SNAME##_iter *iter); \ + V PFX##_iter_value(SNAME##_iter *iter); \ + V *PFX##_iter_rvalue(SNAME##_iter *iter); \ + size_t PFX##_iter_index(SNAME##_iter *iter); \ + \ + /* Default Key */ \ + static inline K PFX##_impl_default_key(void) \ + { \ + K _empty_key_; \ + \ + memset(&_empty_key_, 0, sizeof(K)); \ + \ + return _empty_key_; \ + } \ + \ + /* Default Value */ \ + static inline V PFX##_impl_default_value(void) \ + { \ + V _empty_value_; \ + \ + memset(&_empty_value_, 0, sizeof(V)); \ + \ + return _empty_value_; \ + } \ + \ /* SOURCE ********************************************************************/ -#define HASHMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) \ - \ - /* Implementation Detail Functions */ \ - static bool PFX##_impl_grow(SNAME *_map_); \ - static SNAME##_entry *PFX##_impl_get_entry(SNAME *_map_, K key); \ - static size_t PFX##_impl_calculate_size(size_t required); \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_map_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_map_); \ - \ - FMOD SNAME *PFX##_new(size_t capacity, double load, int (*compare)(K, K), size_t (*hash)(K)) \ - { \ - if (capacity == 0 || load <= 0 || load >= 1) \ - return NULL; \ - \ - /* Prevent integer overflow */ \ - if (capacity >= UINTMAX_MAX * load) \ - return NULL; \ - \ - size_t real_capacity = PFX##_impl_calculate_size(capacity / load); \ - \ - SNAME *_map_ = malloc(sizeof(SNAME)); \ - \ - if (!_map_) \ - return NULL; \ - \ - _map_->buffer = malloc(sizeof(SNAME##_entry) * real_capacity); \ - \ - if (!_map_->buffer) \ - { \ - free(_map_); \ - return NULL; \ - } \ - \ - memset(_map_->buffer, 0, sizeof(SNAME##_entry) * real_capacity); \ - \ - _map_->count = 0; \ - _map_->capacity = real_capacity; \ - _map_->load = load; \ - _map_->cmp = compare; \ - _map_->hash = hash; \ - \ - _map_->it_start = PFX##_impl_it_start; \ - _map_->it_end = PFX##_impl_it_end; \ - \ - return _map_; \ - } \ - \ - FMOD void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _map_->capacity; i++) \ - { \ - SNAME##_entry *entry = &(_map_->buffer[i]); \ - \ - if (entry->state == CMC_ES_FILLED) \ - { \ - deallocator(entry->key, entry->value); \ - } \ - } \ - } \ - \ - memset(_map_->buffer, 0, sizeof(SNAME##_entry) * _map_->capacity); \ - \ - _map_->count = 0; \ - } \ - \ - FMOD void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _map_->capacity; i++) \ - { \ - SNAME##_entry *entry = &(_map_->buffer[i]); \ - \ - if (entry->state == CMC_ES_FILLED) \ - { \ - deallocator(entry->key, entry->value); \ - } \ - } \ - } \ - \ - free(_map_->buffer); \ - free(_map_); \ - } \ - \ - FMOD bool PFX##_insert(SNAME *_map_, K key, V value) \ - { \ - if ((double)_map_->capacity * _map_->load <= (double)_map_->count) \ - { \ - if (!PFX##_impl_grow(_map_)) \ - return false; \ - } \ - \ - size_t hash = _map_->hash(key); \ - size_t original_pos = hash % _map_->capacity; \ - size_t pos = original_pos; \ - \ - SNAME##_entry *target = &(_map_->buffer[pos]); \ - \ - if (PFX##_impl_get_entry(_map_, key) != NULL) \ - return false; \ - \ - if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) \ - { \ - target->key = key; \ - target->value = value; \ - target->dist = 0; \ - target->state = CMC_ES_FILLED; \ - } \ - else \ - { \ - while (true) \ - { \ - pos++; \ - target = &(_map_->buffer[pos % _map_->capacity]); \ - \ - if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) \ - { \ - target->key = key; \ - target->value = value; \ - target->dist = pos - original_pos; \ - target->state = CMC_ES_FILLED; \ - \ - break; \ - } \ - else if (target->dist < original_pos - pos) \ - { \ - K tmp_k = target->key; \ - V tmp_v = target->value; \ - size_t tmp_dist = target->dist; \ - \ - target->key = key; \ - target->value = value; \ - target->dist = pos - original_pos; \ - \ - key = tmp_k; \ - value = tmp_v; \ - original_pos = pos - tmp_dist; \ - } \ - } \ - } \ - \ - _map_->count++; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value) \ - { \ - SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ - \ - if (!entry) \ - return false; \ - \ - if (old_value) \ - *old_value = entry->value; \ - \ - entry->value = new_value; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_remove(SNAME *_map_, K key, V *out_value) \ - { \ - SNAME##_entry *result = PFX##_impl_get_entry(_map_, key); \ - \ - if (result == NULL) \ - return false; \ - \ - if (out_value) \ - *out_value = result->value; \ - \ - result->key = PFX##_impl_default_key(); \ - result->value = PFX##_impl_default_value(); \ - result->dist = 0; \ - result->state = CMC_ES_DELETED; \ - \ - _map_->count--; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition) \ - { \ - if (condition) \ - return PFX##_insert(_map_, key, value); \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *out_value, bool condition) \ - { \ - if (condition) \ - return PFX##_remove(_map_, key, out_value); \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_max(SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - SNAME##_iter iter; \ - \ - for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - K result_key = PFX##_iter_key(&iter); \ - V result_value = PFX##_iter_value(&iter); \ - size_t index = PFX##_iter_index(&iter); \ - \ - if (index == 0) \ - { \ - *key = result_key; \ - *value = result_value; \ - } \ - else if (_map_->cmp(result_key, *key) > 0) \ - { \ - *key = result_key; \ - *value = result_value; \ - } \ - } \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_min(SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - SNAME##_iter iter; \ - \ - for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - K result_key = PFX##_iter_key(&iter); \ - V result_value = PFX##_iter_value(&iter); \ - size_t index = PFX##_iter_index(&iter); \ - \ - if (index == 0) \ - { \ - *key = result_key; \ - *value = result_value; \ - } \ - else if (_map_->cmp(result_key, *key) < 0) \ - { \ - *key = result_key; \ - *value = result_value; \ - } \ - } \ - \ - return true; \ - } \ - \ - FMOD V PFX##_get(SNAME *_map_, K key) \ - { \ - SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ - \ - if (!entry) \ - return PFX##_impl_default_value(); \ - \ - return entry->value; \ - } \ - \ - FMOD V *PFX##_get_ref(SNAME *_map_, K key) \ - { \ - SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ - \ - if (!entry) \ - return NULL; \ - \ - return &(entry->value); \ - } \ - \ - FMOD bool PFX##_contains(SNAME *_map_, K key) \ - { \ - return PFX##_impl_get_entry(_map_, key) != NULL; \ - } \ - \ - FMOD bool PFX##_empty(SNAME *_map_) \ - { \ - return _map_->count == 0; \ - } \ - \ - FMOD size_t PFX##_count(SNAME *_map_) \ - { \ - return _map_->count; \ - } \ - \ - FMOD size_t PFX##_capacity(SNAME *_map_) \ - { \ - return _map_->capacity; \ - } \ - \ - FMOD SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)) \ - { \ - SNAME *result = PFX##_new(_map_->capacity, _map_->load, _map_->cmp, _map_->hash); \ - \ - if (!result) \ - return NULL; \ - \ - if (key_copy_func || value_copy_func) \ - { \ - for (size_t i = 0; i < _map_->capacity; i++) \ - { \ - SNAME##_entry *scan = &(_map_->buffer[i]); \ - \ - if (scan->state != CMC_ES_EMPTY) \ - { \ - SNAME##_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(SNAME##_entry) * _map_->capacity); \ - \ - result->count = _map_->count; \ - \ - return result; \ - } \ - \ - FMOD bool PFX##_equals(SNAME *_map1_, SNAME *_map2_, int (*value_comparator)(V, V)) \ - { \ - if (PFX##_count(_map1_) != PFX##_count(_map2_)) \ - return false; \ - \ - SNAME##_iter iter; \ - PFX##_iter_init(&iter, _map1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - SNAME##_entry *entry = PFX##_impl_get_entry(_map2_, PFX##_iter_key(&iter)); \ - \ - if (entry == NULL) \ - return false; \ - \ - if (value_comparator) \ - { \ - if (value_comparator(entry->value, PFX##_iter_value(&iter)) != 0) \ - return false; \ - } \ - } \ - \ - return true; \ - } \ - \ - FMOD cmc_string PFX##_to_string(SNAME *_map_) \ - { \ - cmc_string str; \ - SNAME *m_ = _map_; \ - const char *name = #SNAME; \ - \ - snprintf(str.s, cmc_string_len, cmc_string_fmt_hashmap, \ - name, m_, m_->buffer, m_->capacity, m_->count, m_->load, m_->cmp, m_->hash); \ - \ - return str; \ - } \ - \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ - { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - FMOD void PFX##_iter_free(SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ - { \ - memset(iter, 0, sizeof(SNAME##_iter)); \ - \ - iter->target = target; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - \ - if (!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; \ - } \ - } \ - } \ - } \ - \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->first; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - } \ - } \ - \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->last; \ - iter->index = PFX##_count(iter->target) - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - } \ - } \ - \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->index + 1 == PFX##_count(iter->target)) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - SNAME##_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 true; \ - } \ - \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->index == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - SNAME##_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 true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->index + 1 == PFX##_count(iter->target)) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ - return false; \ - \ - for (size_t i = 0; i < steps; i++) \ - PFX##_iter_next(iter); \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *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++) \ - PFX##_iter_prev(iter); \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator was able to be positioned at the given index */ \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ - { \ - if (index >= PFX##_count(iter->target)) \ - return false; \ - \ - if (iter->index > index) \ - return PFX##_iter_rewind(iter, iter->index - index); \ - else if (iter->index < index) \ - return PFX##_iter_advance(iter, index - iter->index); \ - \ - return true; \ - } \ - \ - FMOD K PFX##_iter_key(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return PFX##_impl_default_key(); \ - \ - return iter->target->buffer[iter->cursor].key; \ - } \ - \ - FMOD V PFX##_iter_value(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return PFX##_impl_default_value(); \ - \ - return iter->target->buffer[iter->cursor].value; \ - } \ - \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->target->buffer[iter->cursor].value); \ - } \ - \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - static bool PFX##_impl_grow(SNAME *_map_) \ - { \ - size_t new_size = _map_->capacity + _map_->capacity / 2; \ - \ - SNAME *_new_map_ = PFX##_new(new_size, _map_->load, _map_->cmp, _map_->hash); \ - \ - if (!_new_map_) \ - return false; \ - \ - SNAME##_iter iter; \ - \ - for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - K key = PFX##_iter_key(&iter); \ - V value = PFX##_iter_value(&iter); \ - \ - PFX##_insert(_new_map_, key, value); \ - } \ - \ - if (_map_->count != _new_map_->count) \ - { \ - PFX##_free(_new_map_, NULL); \ - \ - return false; \ - } \ - \ - SNAME##_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; \ - \ - PFX##_free(_new_map_, NULL); \ - \ - return true; \ - } \ - \ - static SNAME##_entry *PFX##_impl_get_entry(SNAME *_map_, K key) \ - { \ - size_t hash = _map_->hash(key); \ - size_t pos = hash % _map_->capacity; \ - \ - SNAME##_entry *target = &(_map_->buffer[pos]); \ - \ - while (target->state == CMC_ES_FILLED || target->state == CMC_ES_DELETED) \ - { \ - if (_map_->cmp(target->key, key) == 0) \ - return target; \ - \ - pos++; \ - target = &(_map_->buffer[pos % _map_->capacity]); \ - } \ - \ - return NULL; \ - } \ - \ - static size_t PFX##_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 SNAME##_iter PFX##_impl_it_start(SNAME *_map_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _map_); \ - \ - return iter; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_map_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _map_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ +#define CMC_GENERATE_HASHMAP_SOURCE(PFX, SNAME, K, V) \ + \ + /* Implementation Detail Functions */ \ + static bool PFX##_impl_grow(SNAME *_map_); \ + static SNAME##_entry *PFX##_impl_get_entry(SNAME *_map_, K key); \ + static size_t PFX##_impl_calculate_size(size_t required); \ + static SNAME##_iter PFX##_impl_it_start(SNAME *_map_); \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_map_); \ + \ + SNAME *PFX##_new(size_t capacity, double load, int (*compare)(K, K), size_t (*hash)(K)) \ + { \ + if (capacity == 0 || load <= 0 || load >= 1) \ + return NULL; \ + \ + /* Prevent integer overflow */ \ + if (capacity >= UINTMAX_MAX * load) \ + return NULL; \ + \ + size_t real_capacity = PFX##_impl_calculate_size(capacity / load); \ + \ + SNAME *_map_ = malloc(sizeof(SNAME)); \ + \ + if (!_map_) \ + return NULL; \ + \ + _map_->buffer = malloc(sizeof(SNAME##_entry) * real_capacity); \ + \ + if (!_map_->buffer) \ + { \ + free(_map_); \ + return NULL; \ + } \ + \ + memset(_map_->buffer, 0, sizeof(SNAME##_entry) * real_capacity); \ + \ + _map_->count = 0; \ + _map_->capacity = real_capacity; \ + _map_->load = load; \ + _map_->cmp = compare; \ + _map_->hash = hash; \ + \ + _map_->it_start = PFX##_impl_it_start; \ + _map_->it_end = PFX##_impl_it_end; \ + \ + return _map_; \ + } \ + \ + void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _map_->capacity; i++) \ + { \ + SNAME##_entry *entry = &(_map_->buffer[i]); \ + \ + if (entry->state == CMC_ES_FILLED) \ + { \ + deallocator(entry->key, entry->value); \ + } \ + } \ + } \ + \ + memset(_map_->buffer, 0, sizeof(SNAME##_entry) * _map_->capacity); \ + \ + _map_->count = 0; \ + } \ + \ + void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _map_->capacity; i++) \ + { \ + SNAME##_entry *entry = &(_map_->buffer[i]); \ + \ + if (entry->state == CMC_ES_FILLED) \ + { \ + deallocator(entry->key, entry->value); \ + } \ + } \ + } \ + \ + free(_map_->buffer); \ + free(_map_); \ + } \ + \ + bool PFX##_insert(SNAME *_map_, K key, V value) \ + { \ + if ((double)_map_->capacity * _map_->load <= (double)_map_->count) \ + { \ + if (!PFX##_impl_grow(_map_)) \ + return false; \ + } \ + \ + size_t hash = _map_->hash(key); \ + size_t original_pos = hash % _map_->capacity; \ + size_t pos = original_pos; \ + \ + SNAME##_entry *target = &(_map_->buffer[pos]); \ + \ + if (PFX##_impl_get_entry(_map_, key) != NULL) \ + return false; \ + \ + if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) \ + { \ + target->key = key; \ + target->value = value; \ + target->dist = 0; \ + target->state = CMC_ES_FILLED; \ + } \ + else \ + { \ + while (true) \ + { \ + pos++; \ + target = &(_map_->buffer[pos % _map_->capacity]); \ + \ + if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) \ + { \ + target->key = key; \ + target->value = value; \ + target->dist = pos - original_pos; \ + target->state = CMC_ES_FILLED; \ + \ + break; \ + } \ + else if (target->dist < original_pos - pos) \ + { \ + K tmp_k = target->key; \ + V tmp_v = target->value; \ + size_t tmp_dist = target->dist; \ + \ + target->key = key; \ + target->value = value; \ + target->dist = pos - original_pos; \ + \ + key = tmp_k; \ + value = tmp_v; \ + original_pos = pos - tmp_dist; \ + } \ + } \ + } \ + \ + _map_->count++; \ + \ + return true; \ + } \ + \ + bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value) \ + { \ + SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ + \ + if (!entry) \ + return false; \ + \ + if (old_value) \ + *old_value = entry->value; \ + \ + entry->value = new_value; \ + \ + return true; \ + } \ + \ + bool PFX##_remove(SNAME *_map_, K key, V *out_value) \ + { \ + SNAME##_entry *result = PFX##_impl_get_entry(_map_, key); \ + \ + if (result == NULL) \ + return false; \ + \ + if (out_value) \ + *out_value = result->value; \ + \ + result->key = PFX##_impl_default_key(); \ + result->value = PFX##_impl_default_value(); \ + result->dist = 0; \ + result->state = CMC_ES_DELETED; \ + \ + _map_->count--; \ + \ + return true; \ + } \ + \ + bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition) \ + { \ + if (condition) \ + return PFX##_insert(_map_, key, value); \ + \ + return false; \ + } \ + \ + bool PFX##_remove_if(SNAME *_map_, K key, V *out_value, bool condition) \ + { \ + if (condition) \ + return PFX##_remove(_map_, key, out_value); \ + \ + return false; \ + } \ + \ + bool PFX##_max(SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + SNAME##_iter iter; \ + \ + for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + K result_key = PFX##_iter_key(&iter); \ + V result_value = PFX##_iter_value(&iter); \ + size_t index = PFX##_iter_index(&iter); \ + \ + if (index == 0) \ + { \ + *key = result_key; \ + *value = result_value; \ + } \ + else if (_map_->cmp(result_key, *key) > 0) \ + { \ + *key = result_key; \ + *value = result_value; \ + } \ + } \ + \ + return true; \ + } \ + \ + bool PFX##_min(SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + SNAME##_iter iter; \ + \ + for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + K result_key = PFX##_iter_key(&iter); \ + V result_value = PFX##_iter_value(&iter); \ + size_t index = PFX##_iter_index(&iter); \ + \ + if (index == 0) \ + { \ + *key = result_key; \ + *value = result_value; \ + } \ + else if (_map_->cmp(result_key, *key) < 0) \ + { \ + *key = result_key; \ + *value = result_value; \ + } \ + } \ + \ + return true; \ + } \ + \ + V PFX##_get(SNAME *_map_, K key) \ + { \ + SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ + \ + if (!entry) \ + return PFX##_impl_default_value(); \ + \ + return entry->value; \ + } \ + \ + V *PFX##_get_ref(SNAME *_map_, K key) \ + { \ + SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ + \ + if (!entry) \ + return NULL; \ + \ + return &(entry->value); \ + } \ + \ + bool PFX##_contains(SNAME *_map_, K key) \ + { \ + return PFX##_impl_get_entry(_map_, key) != NULL; \ + } \ + \ + bool PFX##_empty(SNAME *_map_) \ + { \ + return _map_->count == 0; \ + } \ + \ + size_t PFX##_count(SNAME *_map_) \ + { \ + return _map_->count; \ + } \ + \ + size_t PFX##_capacity(SNAME *_map_) \ + { \ + return _map_->capacity; \ + } \ + \ + SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)) \ + { \ + SNAME *result = PFX##_new(_map_->capacity, _map_->load, _map_->cmp, _map_->hash); \ + \ + if (!result) \ + return NULL; \ + \ + if (key_copy_func || value_copy_func) \ + { \ + for (size_t i = 0; i < _map_->capacity; i++) \ + { \ + SNAME##_entry *scan = &(_map_->buffer[i]); \ + \ + if (scan->state != CMC_ES_EMPTY) \ + { \ + SNAME##_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(SNAME##_entry) * _map_->capacity); \ + \ + result->count = _map_->count; \ + \ + return result; \ + } \ + \ + bool PFX##_equals(SNAME *_map1_, SNAME *_map2_, int (*value_comparator)(V, V)) \ + { \ + if (PFX##_count(_map1_) != PFX##_count(_map2_)) \ + return false; \ + \ + SNAME##_iter iter; \ + PFX##_iter_init(&iter, _map1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + SNAME##_entry *entry = PFX##_impl_get_entry(_map2_, PFX##_iter_key(&iter)); \ + \ + if (entry == NULL) \ + return false; \ + \ + if (value_comparator) \ + { \ + if (value_comparator(entry->value, PFX##_iter_value(&iter)) != 0) \ + return false; \ + } \ + } \ + \ + return true; \ + } \ + \ + cmc_string PFX##_to_string(SNAME *_map_) \ + { \ + cmc_string str; \ + SNAME *m_ = _map_; \ + const char *name = #SNAME; \ + \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_hashmap, \ + name, m_, m_->buffer, m_->capacity, m_->count, m_->load, m_->cmp, m_->hash); \ + \ + return str; \ + } \ + \ + SNAME##_iter *PFX##_iter_new(SNAME *target) \ + { \ + SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + void PFX##_iter_free(SNAME##_iter *iter) \ + { \ + free(iter); \ + } \ + \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + { \ + memset(iter, 0, sizeof(SNAME##_iter)); \ + \ + iter->target = target; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + \ + if (!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; \ + } \ + } \ + } \ + } \ + \ + bool PFX##_iter_start(SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + bool PFX##_iter_end(SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + void PFX##_iter_to_start(SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->first; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ + } \ + \ + void PFX##_iter_to_end(SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->last; \ + iter->index = PFX##_count(iter->target) - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + } \ + } \ + \ + bool PFX##_iter_next(SNAME##_iter *iter) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->index + 1 == PFX##_count(iter->target)) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + SNAME##_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 true; \ + } \ + \ + bool PFX##_iter_prev(SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->index == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + SNAME##_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 true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->index + 1 == PFX##_count(iter->target)) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ + return false; \ + \ + for (size_t i = 0; i < steps; i++) \ + PFX##_iter_next(iter); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool PFX##_iter_rewind(SNAME##_iter *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++) \ + PFX##_iter_prev(iter); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator was able to be positioned at the given index */ \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + { \ + if (index >= PFX##_count(iter->target)) \ + return false; \ + \ + if (iter->index > index) \ + return PFX##_iter_rewind(iter, iter->index - index); \ + else if (iter->index < index) \ + return PFX##_iter_advance(iter, index - iter->index); \ + \ + return true; \ + } \ + \ + K PFX##_iter_key(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return PFX##_impl_default_key(); \ + \ + return iter->target->buffer[iter->cursor].key; \ + } \ + \ + V PFX##_iter_value(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return PFX##_impl_default_value(); \ + \ + return iter->target->buffer[iter->cursor].value; \ + } \ + \ + V *PFX##_iter_rvalue(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return NULL; \ + \ + return &(iter->target->buffer[iter->cursor].value); \ + } \ + \ + size_t PFX##_iter_index(SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + static bool PFX##_impl_grow(SNAME *_map_) \ + { \ + size_t new_size = _map_->capacity + _map_->capacity / 2; \ + \ + SNAME *_new_map_ = PFX##_new(new_size, _map_->load, _map_->cmp, _map_->hash); \ + \ + if (!_new_map_) \ + return false; \ + \ + SNAME##_iter iter; \ + \ + for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + K key = PFX##_iter_key(&iter); \ + V value = PFX##_iter_value(&iter); \ + \ + PFX##_insert(_new_map_, key, value); \ + } \ + \ + if (_map_->count != _new_map_->count) \ + { \ + PFX##_free(_new_map_, NULL); \ + \ + return false; \ + } \ + \ + SNAME##_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; \ + \ + PFX##_free(_new_map_, NULL); \ + \ + return true; \ + } \ + \ + static SNAME##_entry *PFX##_impl_get_entry(SNAME *_map_, K key) \ + { \ + size_t hash = _map_->hash(key); \ + size_t pos = hash % _map_->capacity; \ + \ + SNAME##_entry *target = &(_map_->buffer[pos]); \ + \ + while (target->state == CMC_ES_FILLED || target->state == CMC_ES_DELETED) \ + { \ + if (_map_->cmp(target->key, key) == 0) \ + return target; \ + \ + pos++; \ + target = &(_map_->buffer[pos % _map_->capacity]); \ + } \ + \ + return NULL; \ + } \ + \ + static size_t PFX##_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 SNAME##_iter PFX##_impl_it_start(SNAME *_map_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _map_); \ + \ + return iter; \ + } \ + \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_map_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _map_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_HASHMAP_H */ diff --git a/src/cmc/hashset.h b/src/cmc/hashset.h index d36f6e2..bb4957e 100644 --- a/src/cmc/hashset.h +++ b/src/cmc/hashset.h @@ -68,958 +68,958 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, #endif /* CMC_HASH_TABLE_SETUP */ -#define HASHSET_GENERATE(PFX, SNAME, FMOD, V) \ - HASHSET_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - HASHSET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) +#define CMC_GENERATE_HASHSET(PFX, SNAME, V) \ + CMC_GENERATE_HASHSET_HEADER(PFX, SNAME, V) \ + CMC_GENERATE_HASHSET_SOURCE(PFX, SNAME, V) -#define HASHSET_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \ - HASHSET_GENERATE_HEADER(PFX, SNAME, FMOD, V) +#define CMC_WRAPGEN_HASHSET_HEADER(PFX, SNAME, K, V) \ + CMC_GENERATE_HASHSET_HEADER(PFX, SNAME, V) -#define HASHSET_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \ - HASHSET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) +#define CMC_WRAPGEN_HASHSET_SOURCE(PFX, SNAME, K, V) \ + CMC_GENERATE_HASHSET_SOURCE(PFX, SNAME, V) /* HEADER ********************************************************************/ -#define HASHSET_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - \ - /* Hashset Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Array of Entries */ \ - struct SNAME##_entry_s *buffer; \ - \ - /* Current Array Capcity */ \ - size_t capacity; \ - \ - /* Current amount of elements */ \ - size_t count; \ - \ - /* Load factor in range (0.0, 1.0) */ \ - double load; \ - \ - /* Element comparison function */ \ - int (*cmp)(V, V); \ - \ - /* Element hash function */ \ - size_t (*hash)(V); \ - \ - /* Function that returns an iterator to the start of the hashset */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the hashset */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - typedef struct SNAME##_entry_s \ - { \ - /* Entry element */ \ - 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_e state; \ - \ - } SNAME##_entry, *SNAME##_entry_ptr; \ - \ - /* Hashset Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target Hashset */ \ - struct SNAME##_s *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; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - FMOD SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), size_t (*hash)(V)); \ - FMOD void PFX##_clear(SNAME *_set_, void (*deallocator)(V)); \ - FMOD void PFX##_free(SNAME *_set_, void (*deallocator)(V)); \ - /* Collection Input and Output */ \ - FMOD bool PFX##_insert(SNAME *_set_, V element); \ - FMOD bool PFX##_remove(SNAME *_set_, V element); \ - /* Conditional Input and Output */ \ - FMOD bool PFX##_insert_if(SNAME *_set_, V element, bool condition); \ - FMOD bool PFX##_remove_if(SNAME *_set_, V element, bool condition); \ - /* Element Access */ \ - FMOD bool PFX##_max(SNAME *_set_, V *value); \ - FMOD bool PFX##_min(SNAME *_set_, V *value); \ - /* Collection State */ \ - FMOD bool PFX##_contains(SNAME *_set_, V element); \ - FMOD bool PFX##_empty(SNAME *_set_); \ - FMOD size_t PFX##_count(SNAME *_set_); \ - FMOD size_t PFX##_capacity(SNAME *_set_); \ - /* Collection Utility */ \ - FMOD SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)); \ - FMOD bool PFX##_equals(SNAME *_set1_, SNAME *_set2_); \ - FMOD cmc_string PFX##_to_string(SNAME *_set_); \ - \ - /* Set Operations */ \ - FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_); \ - FMOD SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_); \ - FMOD SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_); \ - FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_); \ - FMOD bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_); \ - FMOD bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_); \ - FMOD bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_); \ - FMOD bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_); \ - FMOD bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ - FMOD void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - FMOD V PFX##_iter_value(SNAME##_iter *iter); \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ - /* Default Value */ \ - static inline V PFX##_impl_default_value(void) \ - { \ - V _empty_value_; \ - \ - memset(&_empty_value_, 0, sizeof(V)); \ - \ - return _empty_value_; \ - } \ - \ +#define CMC_GENERATE_HASHSET_HEADER(PFX, SNAME, V) \ + \ + /* Hashset Structure */ \ + typedef struct SNAME##_s \ + { \ + /* Array of Entries */ \ + struct SNAME##_entry_s *buffer; \ + \ + /* Current Array Capcity */ \ + size_t capacity; \ + \ + /* Current amount of elements */ \ + size_t count; \ + \ + /* Load factor in range (0.0, 1.0) */ \ + double load; \ + \ + /* Element comparison function */ \ + int (*cmp)(V, V); \ + \ + /* Element hash function */ \ + size_t (*hash)(V); \ + \ + /* Function that returns an iterator to the start of the hashset */ \ + struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + \ + /* Function that returns an iterator to the end of the hashset */ \ + struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + \ + } SNAME, *SNAME##_ptr; \ + \ + typedef struct SNAME##_entry_s \ + { \ + /* Entry element */ \ + 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_e state; \ + \ + } SNAME##_entry, *SNAME##_entry_ptr; \ + \ + /* Hashset Iterator */ \ + typedef struct SNAME##_iter_s \ + { \ + /* Target Hashset */ \ + struct SNAME##_s *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; \ + \ + } SNAME##_iter, *SNAME##_iter_ptr; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), size_t (*hash)(V)); \ + void PFX##_clear(SNAME *_set_, void (*deallocator)(V)); \ + void PFX##_free(SNAME *_set_, void (*deallocator)(V)); \ + /* Collection Input and Output */ \ + bool PFX##_insert(SNAME *_set_, V element); \ + bool PFX##_remove(SNAME *_set_, V element); \ + /* Conditional Input and Output */ \ + bool PFX##_insert_if(SNAME *_set_, V element, bool condition); \ + bool PFX##_remove_if(SNAME *_set_, V element, bool condition); \ + /* Element Access */ \ + bool PFX##_max(SNAME *_set_, V *value); \ + bool PFX##_min(SNAME *_set_, V *value); \ + /* Collection State */ \ + bool PFX##_contains(SNAME *_set_, V element); \ + bool PFX##_empty(SNAME *_set_); \ + size_t PFX##_count(SNAME *_set_); \ + size_t PFX##_capacity(SNAME *_set_); \ + /* Collection Utility */ \ + SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)); \ + bool PFX##_equals(SNAME *_set1_, SNAME *_set2_); \ + cmc_string PFX##_to_string(SNAME *_set_); \ + \ + /* Set Operations */ \ + SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_); \ + SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_); \ + SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_); \ + SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_); \ + bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_); \ + bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_); \ + bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_); \ + bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_); \ + bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + SNAME##_iter *PFX##_iter_new(SNAME *target); \ + void PFX##_iter_free(SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(SNAME##_iter *iter); \ + bool PFX##_iter_end(SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(SNAME##_iter *iter); \ + void PFX##_iter_to_end(SNAME##_iter *iter); \ + bool PFX##_iter_next(SNAME##_iter *iter); \ + bool PFX##_iter_prev(SNAME##_iter *iter); \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + V PFX##_iter_value(SNAME##_iter *iter); \ + size_t PFX##_iter_index(SNAME##_iter *iter); \ + \ + /* Default Value */ \ + static inline V PFX##_impl_default_value(void) \ + { \ + V _empty_value_; \ + \ + memset(&_empty_value_, 0, sizeof(V)); \ + \ + return _empty_value_; \ + } \ + \ /* SOURCE ********************************************************************/ -#define HASHSET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ - \ - /* Implementation Detail Functions */ \ - static bool PFX##_impl_grow(SNAME *_set_); \ - static SNAME##_entry *PFX##_impl_get_entry(SNAME *_set_, V element); \ - static size_t PFX##_impl_calculate_size(size_t required); \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_set_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_set_); \ - \ - FMOD SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), size_t (*hash)(V)) \ - { \ - if (capacity == 0 || load <= 0 || load >= 1) \ - return NULL; \ - \ - /* Prevent integer overflow */ \ - if (capacity >= UINTMAX_MAX * load) \ - return NULL; \ - \ - size_t real_capacity = PFX##_impl_calculate_size(capacity / load); \ - \ - SNAME *_set_ = malloc(sizeof(SNAME)); \ - \ - if (!_set_) \ - return NULL; \ - \ - _set_->buffer = malloc(sizeof(SNAME##_entry) * real_capacity); \ - \ - if (!_set_->buffer) \ - { \ - free(_set_); \ - return NULL; \ - } \ - \ - memset(_set_->buffer, 0, sizeof(SNAME##_entry) * real_capacity); \ - \ - _set_->count = 0; \ - _set_->capacity = real_capacity; \ - _set_->load = load; \ - _set_->cmp = compare; \ - _set_->hash = hash; \ - \ - _set_->it_start = PFX##_impl_it_start; \ - _set_->it_end = PFX##_impl_it_end; \ - \ - return _set_; \ - } \ - \ - FMOD void PFX##_clear(SNAME *_set_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _set_->capacity; i++) \ - { \ - SNAME##_entry *entry = &(_set_->buffer[i]); \ - \ - if (entry->state == CMC_ES_FILLED) \ - { \ - deallocator(entry->value); \ - } \ - } \ - } \ - \ - memset(_set_->buffer, 0, sizeof(SNAME##_entry) * _set_->capacity); \ - \ - _set_->count = 0; \ - } \ - \ - FMOD void PFX##_free(SNAME *_set_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _set_->capacity; i++) \ - { \ - SNAME##_entry *entry = &(_set_->buffer[i]); \ - \ - if (entry->state == CMC_ES_FILLED) \ - { \ - deallocator(entry->value); \ - } \ - } \ - } \ - \ - free(_set_->buffer); \ - free(_set_); \ - } \ - \ - FMOD bool PFX##_insert(SNAME *_set_, V element) \ - { \ - if ((double)_set_->capacity * _set_->load <= (double)_set_->count) \ - { \ - if (!PFX##_impl_grow(_set_)) \ - return false; \ - } \ - \ - size_t hash = _set_->hash(element); \ - size_t original_pos = hash % _set_->capacity; \ - size_t pos = original_pos; \ - \ - SNAME##_entry *target = &(_set_->buffer[pos]); \ - \ - if (PFX##_impl_get_entry(_set_, element) != NULL) \ - return false; \ - \ - if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) \ - { \ - target->value = element; \ - target->dist = 0; \ - target->state = CMC_ES_FILLED; \ - } \ - else \ - { \ - while (true) \ - { \ - pos++; \ - target = &(_set_->buffer[pos % _set_->capacity]); \ - \ - if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) \ - { \ - target->value = element; \ - target->dist = pos - original_pos; \ - target->state = CMC_ES_FILLED; \ - \ - break; \ - } \ - else if (target->dist < pos - original_pos) \ - { \ - V tmp = target->value; \ - size_t tmp_dist = target->dist; \ - \ - target->value = element; \ - target->dist = pos - original_pos; \ - \ - element = tmp; \ - original_pos = pos - tmp_dist; \ - } \ - } \ - } \ - \ - _set_->count++; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_remove(SNAME *_set_, V element) \ - { \ - SNAME##_entry *result = PFX##_impl_get_entry(_set_, element); \ - \ - if (result == NULL) \ - return false; \ - \ - result->value = PFX##_impl_default_value(); \ - result->dist = 0; \ - result->state = CMC_ES_DELETED; \ - \ - _set_->count--; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_insert_if(SNAME *_set_, V element, bool condition) \ - { \ - if (condition) \ - return PFX##_insert(_set_, element); \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_remove_if(SNAME *_set_, V element, bool condition) \ - { \ - if (condition) \ - return PFX##_remove(_set_, element); \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_max(SNAME *_set_, V *value) \ - { \ - if (PFX##_empty(_set_)) \ - return false; \ - \ - SNAME##_iter iter; \ - \ - for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - V result = PFX##_iter_value(&iter); \ - size_t index = PFX##_iter_index(&iter); \ - \ - if (index == 0) \ - *value = result; \ - else if (_set_->cmp(result, *value) > 0) \ - *value = result; \ - } \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_min(SNAME *_set_, V *value) \ - { \ - if (PFX##_empty(_set_)) \ - return false; \ - \ - SNAME##_iter iter; \ - \ - for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - V result = PFX##_iter_value(&iter); \ - size_t index = PFX##_iter_index(&iter); \ - \ - if (index == 0) \ - *value = result; \ - else if (_set_->cmp(result, *value) < 0) \ - *value = result; \ - } \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_contains(SNAME *_set_, V element) \ - { \ - return PFX##_impl_get_entry(_set_, element) != NULL; \ - } \ - \ - FMOD bool PFX##_empty(SNAME *_set_) \ - { \ - return _set_->count == 0; \ - } \ - \ - FMOD size_t PFX##_count(SNAME *_set_) \ - { \ - return _set_->count; \ - } \ - \ - FMOD size_t PFX##_capacity(SNAME *_set_) \ - { \ - return _set_->capacity; \ - } \ - \ - FMOD SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)) \ - { \ - SNAME *result = PFX##_new(_set_->capacity, _set_->load, _set_->cmp, _set_->hash); \ - \ - if (!result) \ - return NULL; \ - \ - if (copy_func) \ - { \ - for (size_t i = 0; i < _set_->capacity; i++) \ - { \ - SNAME##_entry *scan = &(_set_->buffer[i]); \ - \ - if (scan->state != CMC_ES_EMPTY) \ - { \ - SNAME##_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(SNAME##_entry) * _set_->capacity); \ - \ - result->count = _set_->count; \ - \ - return result; \ - } \ - \ - FMOD bool PFX##_equals(SNAME *_set1_, SNAME *_set2_) \ - { \ - if (PFX##_count(_set1_) != PFX##_count(_set2_)) \ - return false; \ - \ - if (PFX##_count(_set1_) == 0) \ - return true; \ - \ - SNAME##_iter iter; \ - PFX##_iter_init(&iter, _set1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - if (PFX##_impl_get_entry(_set2_, PFX##_iter_value(&iter)) == NULL) \ - return false; \ - } \ - \ - return true; \ - } \ - \ - FMOD cmc_string PFX##_to_string(SNAME *_set_) \ - { \ - cmc_string str; \ - SNAME *s_ = _set_; \ - const char *name = #SNAME; \ - \ - snprintf(str.s, cmc_string_len, cmc_string_fmt_hashset, \ - name, s_, s_->buffer, s_->capacity, s_->count, s_->load, s_->cmp, s_->hash); \ - \ - return str; \ - } \ - \ - FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_) \ - { \ - SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ - \ - if (!_set_r_) \ - return NULL; \ - \ - SNAME##_iter iter1, iter2; \ - PFX##_iter_init(&iter1, _set1_); \ - PFX##_iter_init(&iter2, _set2_); \ - \ - for (PFX##_iter_to_start(&iter1); !PFX##_iter_end(&iter1); PFX##_iter_next(&iter1)) \ - { \ - PFX##_insert(_set_r_, PFX##_iter_value(&iter1)); \ - } \ - \ - for (PFX##_iter_to_start(&iter2); !PFX##_iter_end(&iter2); PFX##_iter_next(&iter2)) \ - { \ - PFX##_insert(_set_r_, PFX##_iter_value(&iter2)); \ - } \ - \ - return _set_r_; \ - } \ - \ - FMOD SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_) \ - { \ - SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ - \ - if (!_set_r_) \ - return NULL; \ - \ - SNAME *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; \ - SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \ - \ - SNAME##_iter iter; \ - PFX##_iter_init(&iter, _set_A_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - V value = PFX##_iter_value(&iter); \ - \ - if (PFX##_impl_get_entry(_set_B_, value) != NULL) \ - PFX##_insert(_set_r_, value); \ - } \ - \ - return _set_r_; \ - } \ - \ - FMOD SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_) \ - { \ - SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ - \ - if (!_set_r_) \ - return NULL; \ - \ - SNAME##_iter iter; \ - PFX##_iter_init(&iter, _set1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - V value = PFX##_iter_value(&iter); \ - \ - if (PFX##_impl_get_entry(_set2_, value) == NULL) \ - PFX##_insert(_set_r_, value); \ - } \ - \ - return _set_r_; \ - } \ - \ - FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_) \ - { \ - SNAME##_iter iter1, iter2; \ - \ - SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ - \ - if (!_set_r_) \ - return NULL; \ - \ - PFX##_iter_init(&iter1, _set1_); \ - PFX##_iter_init(&iter2, _set2_); \ - \ - for (PFX##_iter_to_start(&iter1); !PFX##_iter_end(&iter1); PFX##_iter_next(&iter1)) \ - { \ - V value = PFX##_iter_value(&iter1); \ - \ - if (PFX##_impl_get_entry(_set2_, value) == NULL) \ - PFX##_insert(_set_r_, value); \ - } \ - \ - for (PFX##_iter_to_start(&iter2); !PFX##_iter_end(&iter2); PFX##_iter_next(&iter2)) \ - { \ - V value = PFX##_iter_value(&iter2); \ - \ - if (PFX##_impl_get_entry(_set1_, value) == NULL) \ - PFX##_insert(_set_r_, value); \ - } \ - \ - return _set_r_; \ - } \ - \ - /* Is _set1_ a subset of _set2_ ? */ \ - /* A set X is a subset of a set Y when: X <= Y */ \ - /* If X is a subset of Y, then Y is a superset of X */ \ - FMOD bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_) \ - { \ - /* If the cardinality of _set1_ is greater than that of _set2_, then it is safe to */ \ - /* say that _set1_ can't be a subset of _set2_ */ \ - if (PFX##_count(_set1_) > PFX##_count(_set2_)) \ - return false; \ - \ - /* The empty set is a subset of all sets */ \ - if (PFX##_empty(_set1_)) \ - return true; \ - \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _set1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - V value = PFX##_iter_value(&iter); \ - \ - if (!PFX##_contains(_set2_, value)) \ - return false; \ - } \ - \ - return true; \ - } \ - \ - /* Is _set1_ a superset of _set2_ ? */ \ - /* A set X is a superset of a set Y when: X >= Y */ \ - /* If X is a superset of Y, then Y is a subset of X */ \ - FMOD bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_) \ - { \ - return PFX##_is_subset(_set2_, _set1_); \ - } \ - \ - /* Is _set1_ a proper subset of _set2_ ? */ \ - /* A set X is a proper subset of a set Y when: X < Y */ \ - /* If X is a proper subset of Y, then Y is a proper superset of X */ \ - FMOD bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_) \ - { \ - /* If the cardinality of _set1_ is greater than or equal to that of _set2_, then it */ \ - /* is safe to say that _set1_ can't be a proper subset of _set2_ */ \ - if (PFX##_count(_set1_) >= PFX##_count(_set2_)) \ - return false; \ - \ - if (PFX##_empty(_set1_)) \ - { \ - /* The empty set is a proper subset of all non-empty sets */ \ - if (!PFX##_empty(_set2_)) \ - return true; \ - /* The empty set is not a proper subset of itself (this is true for any set) */ \ - else \ - return false; \ - } \ - \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _set1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - V value = PFX##_iter_value(&iter); \ - \ - if (!PFX##_contains(_set2_, value)) \ - return false; \ - } \ - \ - return true; \ - } \ - \ - /* Is _set1_ a proper superset of _set2_ ? */ \ - /* A set X is a proper superset of a set Y when: X > Y */ \ - /* If X is a proper superset of Y, then Y is a proper subset of X */ \ - FMOD bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_) \ - { \ - return PFX##_is_proper_subset(_set2_, _set1_); \ - } \ - \ - /* Is _set1_ a disjointset of _set2_ ? */ \ - /* A set X is a disjointset of a set Y if their intersection is empty, that is, if */ \ - /* there are no elements in common between the two */ \ - FMOD bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_) \ - { \ - /* The intersection of an empty set with any other set will result in an empty set */ \ - if (PFX##_empty(_set1_)) \ - return true; \ - \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _set1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - V value = PFX##_iter_value(&iter); \ - \ - if (PFX##_contains(_set2_, value)) \ - return false; \ - } \ - \ - return true; \ - } \ - \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ - { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - FMOD void PFX##_iter_free(SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ - { \ - memset(iter, 0, sizeof(SNAME##_iter)); \ - \ - iter->target = target; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - \ - if (!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; \ - } \ - } \ - } \ - } \ - \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->first; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - } \ - } \ - \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->last; \ - iter->index = PFX##_count(iter->target) - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - } \ - } \ - \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->index + 1 == PFX##_count(iter->target)) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - SNAME##_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 true; \ - } \ - \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->index == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - SNAME##_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 true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->index + 1 == PFX##_count(iter->target)) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ - return false; \ - \ - for (size_t i = 0; i < steps; i++) \ - PFX##_iter_next(iter); \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *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++) \ - PFX##_iter_prev(iter); \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator was able to be positioned at the given index */ \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ - { \ - if (index >= PFX##_count(iter->target)) \ - return false; \ - \ - if (iter->index > index) \ - return PFX##_iter_rewind(iter, iter->index - index); \ - else if (iter->index < index) \ - return PFX##_iter_advance(iter, index - iter->index); \ - \ - return true; \ - } \ - \ - FMOD V PFX##_iter_value(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return PFX##_impl_default_value(); \ - \ - return iter->target->buffer[iter->cursor].value; \ - } \ - \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - static bool PFX##_impl_grow(SNAME *_set_) \ - { \ - size_t new_size = _set_->capacity + _set_->capacity / 2; \ - \ - SNAME *_new_set_ = PFX##_new(new_size, _set_->load, _set_->cmp, _set_->hash); \ - \ - if (!_new_set_) \ - return false; \ - \ - SNAME##_iter iter; \ - \ - for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - PFX##_insert(_new_set_, PFX##_iter_value(&iter)); \ - } \ - \ - if (_set_->count != _new_set_->count) \ - { \ - PFX##_free(_new_set_, NULL); \ - \ - return false; \ - } \ - \ - SNAME##_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; \ - \ - PFX##_free(_new_set_, NULL); \ - \ - return true; \ - } \ - \ - static SNAME##_entry *PFX##_impl_get_entry(SNAME *_set_, V element) \ - { \ - size_t hash = _set_->hash(element); \ - size_t pos = hash % _set_->capacity; \ - \ - SNAME##_entry *target = &(_set_->buffer[pos]); \ - \ - while (target->state == CMC_ES_FILLED || target->state == CMC_ES_DELETED) \ - { \ - if (_set_->cmp(target->value, element) == 0) \ - return target; \ - \ - pos++; \ - target = &(_set_->buffer[pos % _set_->capacity]); \ - } \ - \ - return NULL; \ - } \ - \ - static size_t PFX##_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 SNAME##_iter PFX##_impl_it_start(SNAME *_set_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _set_); \ - \ - return iter; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_set_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _set_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ +#define CMC_GENERATE_HASHSET_SOURCE(PFX, SNAME, V) \ + \ + /* Implementation Detail Functions */ \ + static bool PFX##_impl_grow(SNAME *_set_); \ + static SNAME##_entry *PFX##_impl_get_entry(SNAME *_set_, V element); \ + static size_t PFX##_impl_calculate_size(size_t required); \ + static SNAME##_iter PFX##_impl_it_start(SNAME *_set_); \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_set_); \ + \ + SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), size_t (*hash)(V)) \ + { \ + if (capacity == 0 || load <= 0 || load >= 1) \ + return NULL; \ + \ + /* Prevent integer overflow */ \ + if (capacity >= UINTMAX_MAX * load) \ + return NULL; \ + \ + size_t real_capacity = PFX##_impl_calculate_size(capacity / load); \ + \ + SNAME *_set_ = malloc(sizeof(SNAME)); \ + \ + if (!_set_) \ + return NULL; \ + \ + _set_->buffer = malloc(sizeof(SNAME##_entry) * real_capacity); \ + \ + if (!_set_->buffer) \ + { \ + free(_set_); \ + return NULL; \ + } \ + \ + memset(_set_->buffer, 0, sizeof(SNAME##_entry) * real_capacity); \ + \ + _set_->count = 0; \ + _set_->capacity = real_capacity; \ + _set_->load = load; \ + _set_->cmp = compare; \ + _set_->hash = hash; \ + \ + _set_->it_start = PFX##_impl_it_start; \ + _set_->it_end = PFX##_impl_it_end; \ + \ + return _set_; \ + } \ + \ + void PFX##_clear(SNAME *_set_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _set_->capacity; i++) \ + { \ + SNAME##_entry *entry = &(_set_->buffer[i]); \ + \ + if (entry->state == CMC_ES_FILLED) \ + { \ + deallocator(entry->value); \ + } \ + } \ + } \ + \ + memset(_set_->buffer, 0, sizeof(SNAME##_entry) * _set_->capacity); \ + \ + _set_->count = 0; \ + } \ + \ + void PFX##_free(SNAME *_set_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _set_->capacity; i++) \ + { \ + SNAME##_entry *entry = &(_set_->buffer[i]); \ + \ + if (entry->state == CMC_ES_FILLED) \ + { \ + deallocator(entry->value); \ + } \ + } \ + } \ + \ + free(_set_->buffer); \ + free(_set_); \ + } \ + \ + bool PFX##_insert(SNAME *_set_, V element) \ + { \ + if ((double)_set_->capacity * _set_->load <= (double)_set_->count) \ + { \ + if (!PFX##_impl_grow(_set_)) \ + return false; \ + } \ + \ + size_t hash = _set_->hash(element); \ + size_t original_pos = hash % _set_->capacity; \ + size_t pos = original_pos; \ + \ + SNAME##_entry *target = &(_set_->buffer[pos]); \ + \ + if (PFX##_impl_get_entry(_set_, element) != NULL) \ + return false; \ + \ + if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) \ + { \ + target->value = element; \ + target->dist = 0; \ + target->state = CMC_ES_FILLED; \ + } \ + else \ + { \ + while (true) \ + { \ + pos++; \ + target = &(_set_->buffer[pos % _set_->capacity]); \ + \ + if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) \ + { \ + target->value = element; \ + target->dist = pos - original_pos; \ + target->state = CMC_ES_FILLED; \ + \ + break; \ + } \ + else if (target->dist < pos - original_pos) \ + { \ + V tmp = target->value; \ + size_t tmp_dist = target->dist; \ + \ + target->value = element; \ + target->dist = pos - original_pos; \ + \ + element = tmp; \ + original_pos = pos - tmp_dist; \ + } \ + } \ + } \ + \ + _set_->count++; \ + \ + return true; \ + } \ + \ + bool PFX##_remove(SNAME *_set_, V element) \ + { \ + SNAME##_entry *result = PFX##_impl_get_entry(_set_, element); \ + \ + if (result == NULL) \ + return false; \ + \ + result->value = PFX##_impl_default_value(); \ + result->dist = 0; \ + result->state = CMC_ES_DELETED; \ + \ + _set_->count--; \ + \ + return true; \ + } \ + \ + bool PFX##_insert_if(SNAME *_set_, V element, bool condition) \ + { \ + if (condition) \ + return PFX##_insert(_set_, element); \ + \ + return false; \ + } \ + \ + bool PFX##_remove_if(SNAME *_set_, V element, bool condition) \ + { \ + if (condition) \ + return PFX##_remove(_set_, element); \ + \ + return false; \ + } \ + \ + bool PFX##_max(SNAME *_set_, V *value) \ + { \ + if (PFX##_empty(_set_)) \ + return false; \ + \ + SNAME##_iter iter; \ + \ + for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + V result = PFX##_iter_value(&iter); \ + size_t index = PFX##_iter_index(&iter); \ + \ + if (index == 0) \ + *value = result; \ + else if (_set_->cmp(result, *value) > 0) \ + *value = result; \ + } \ + \ + return true; \ + } \ + \ + bool PFX##_min(SNAME *_set_, V *value) \ + { \ + if (PFX##_empty(_set_)) \ + return false; \ + \ + SNAME##_iter iter; \ + \ + for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + V result = PFX##_iter_value(&iter); \ + size_t index = PFX##_iter_index(&iter); \ + \ + if (index == 0) \ + *value = result; \ + else if (_set_->cmp(result, *value) < 0) \ + *value = result; \ + } \ + \ + return true; \ + } \ + \ + bool PFX##_contains(SNAME *_set_, V element) \ + { \ + return PFX##_impl_get_entry(_set_, element) != NULL; \ + } \ + \ + bool PFX##_empty(SNAME *_set_) \ + { \ + return _set_->count == 0; \ + } \ + \ + size_t PFX##_count(SNAME *_set_) \ + { \ + return _set_->count; \ + } \ + \ + size_t PFX##_capacity(SNAME *_set_) \ + { \ + return _set_->capacity; \ + } \ + \ + SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)) \ + { \ + SNAME *result = PFX##_new(_set_->capacity, _set_->load, _set_->cmp, _set_->hash); \ + \ + if (!result) \ + return NULL; \ + \ + if (copy_func) \ + { \ + for (size_t i = 0; i < _set_->capacity; i++) \ + { \ + SNAME##_entry *scan = &(_set_->buffer[i]); \ + \ + if (scan->state != CMC_ES_EMPTY) \ + { \ + SNAME##_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(SNAME##_entry) * _set_->capacity); \ + \ + result->count = _set_->count; \ + \ + return result; \ + } \ + \ + bool PFX##_equals(SNAME *_set1_, SNAME *_set2_) \ + { \ + if (PFX##_count(_set1_) != PFX##_count(_set2_)) \ + return false; \ + \ + if (PFX##_count(_set1_) == 0) \ + return true; \ + \ + SNAME##_iter iter; \ + PFX##_iter_init(&iter, _set1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + if (PFX##_impl_get_entry(_set2_, PFX##_iter_value(&iter)) == NULL) \ + return false; \ + } \ + \ + return true; \ + } \ + \ + cmc_string PFX##_to_string(SNAME *_set_) \ + { \ + cmc_string str; \ + SNAME *s_ = _set_; \ + const char *name = #SNAME; \ + \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_hashset, \ + name, s_, s_->buffer, s_->capacity, s_->count, s_->load, s_->cmp, s_->hash); \ + \ + return str; \ + } \ + \ + SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_) \ + { \ + SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ + \ + if (!_set_r_) \ + return NULL; \ + \ + SNAME##_iter iter1, iter2; \ + PFX##_iter_init(&iter1, _set1_); \ + PFX##_iter_init(&iter2, _set2_); \ + \ + for (PFX##_iter_to_start(&iter1); !PFX##_iter_end(&iter1); PFX##_iter_next(&iter1)) \ + { \ + PFX##_insert(_set_r_, PFX##_iter_value(&iter1)); \ + } \ + \ + for (PFX##_iter_to_start(&iter2); !PFX##_iter_end(&iter2); PFX##_iter_next(&iter2)) \ + { \ + PFX##_insert(_set_r_, PFX##_iter_value(&iter2)); \ + } \ + \ + return _set_r_; \ + } \ + \ + SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_) \ + { \ + SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ + \ + if (!_set_r_) \ + return NULL; \ + \ + SNAME *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; \ + SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \ + \ + SNAME##_iter iter; \ + PFX##_iter_init(&iter, _set_A_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + V value = PFX##_iter_value(&iter); \ + \ + if (PFX##_impl_get_entry(_set_B_, value) != NULL) \ + PFX##_insert(_set_r_, value); \ + } \ + \ + return _set_r_; \ + } \ + \ + SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_) \ + { \ + SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ + \ + if (!_set_r_) \ + return NULL; \ + \ + SNAME##_iter iter; \ + PFX##_iter_init(&iter, _set1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + V value = PFX##_iter_value(&iter); \ + \ + if (PFX##_impl_get_entry(_set2_, value) == NULL) \ + PFX##_insert(_set_r_, value); \ + } \ + \ + return _set_r_; \ + } \ + \ + SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_) \ + { \ + SNAME##_iter iter1, iter2; \ + \ + SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ + \ + if (!_set_r_) \ + return NULL; \ + \ + PFX##_iter_init(&iter1, _set1_); \ + PFX##_iter_init(&iter2, _set2_); \ + \ + for (PFX##_iter_to_start(&iter1); !PFX##_iter_end(&iter1); PFX##_iter_next(&iter1)) \ + { \ + V value = PFX##_iter_value(&iter1); \ + \ + if (PFX##_impl_get_entry(_set2_, value) == NULL) \ + PFX##_insert(_set_r_, value); \ + } \ + \ + for (PFX##_iter_to_start(&iter2); !PFX##_iter_end(&iter2); PFX##_iter_next(&iter2)) \ + { \ + V value = PFX##_iter_value(&iter2); \ + \ + if (PFX##_impl_get_entry(_set1_, value) == NULL) \ + PFX##_insert(_set_r_, value); \ + } \ + \ + return _set_r_; \ + } \ + \ + /* Is _set1_ a subset of _set2_ ? */ \ + /* A set X is a subset of a set Y when: X <= Y */ \ + /* If X is a subset of Y, then Y is a superset of X */ \ + bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_) \ + { \ + /* If the cardinality of _set1_ is greater than that of _set2_, then it is safe to */ \ + /* say that _set1_ can't be a subset of _set2_ */ \ + if (PFX##_count(_set1_) > PFX##_count(_set2_)) \ + return false; \ + \ + /* The empty set is a subset of all sets */ \ + if (PFX##_empty(_set1_)) \ + return true; \ + \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _set1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + V value = PFX##_iter_value(&iter); \ + \ + if (!PFX##_contains(_set2_, value)) \ + return false; \ + } \ + \ + return true; \ + } \ + \ + /* Is _set1_ a superset of _set2_ ? */ \ + /* A set X is a superset of a set Y when: X >= Y */ \ + /* If X is a superset of Y, then Y is a subset of X */ \ + bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_) \ + { \ + return PFX##_is_subset(_set2_, _set1_); \ + } \ + \ + /* Is _set1_ a proper subset of _set2_ ? */ \ + /* A set X is a proper subset of a set Y when: X < Y */ \ + /* If X is a proper subset of Y, then Y is a proper superset of X */ \ + bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_) \ + { \ + /* If the cardinality of _set1_ is greater than or equal to that of _set2_, then it */ \ + /* is safe to say that _set1_ can't be a proper subset of _set2_ */ \ + if (PFX##_count(_set1_) >= PFX##_count(_set2_)) \ + return false; \ + \ + if (PFX##_empty(_set1_)) \ + { \ + /* The empty set is a proper subset of all non-empty sets */ \ + if (!PFX##_empty(_set2_)) \ + return true; \ + /* The empty set is not a proper subset of itself (this is true for any set) */ \ + else \ + return false; \ + } \ + \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _set1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + V value = PFX##_iter_value(&iter); \ + \ + if (!PFX##_contains(_set2_, value)) \ + return false; \ + } \ + \ + return true; \ + } \ + \ + /* Is _set1_ a proper superset of _set2_ ? */ \ + /* A set X is a proper superset of a set Y when: X > Y */ \ + /* If X is a proper superset of Y, then Y is a proper subset of X */ \ + bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_) \ + { \ + return PFX##_is_proper_subset(_set2_, _set1_); \ + } \ + \ + /* Is _set1_ a disjointset of _set2_ ? */ \ + /* A set X is a disjointset of a set Y if their intersection is empty, that is, if */ \ + /* there are no elements in common between the two */ \ + bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_) \ + { \ + /* The intersection of an empty set with any other set will result in an empty set */ \ + if (PFX##_empty(_set1_)) \ + return true; \ + \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _set1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + V value = PFX##_iter_value(&iter); \ + \ + if (PFX##_contains(_set2_, value)) \ + return false; \ + } \ + \ + return true; \ + } \ + \ + SNAME##_iter *PFX##_iter_new(SNAME *target) \ + { \ + SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + void PFX##_iter_free(SNAME##_iter *iter) \ + { \ + free(iter); \ + } \ + \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + { \ + memset(iter, 0, sizeof(SNAME##_iter)); \ + \ + iter->target = target; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + \ + if (!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; \ + } \ + } \ + } \ + } \ + \ + bool PFX##_iter_start(SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + bool PFX##_iter_end(SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + void PFX##_iter_to_start(SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->first; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ + } \ + \ + void PFX##_iter_to_end(SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->last; \ + iter->index = PFX##_count(iter->target) - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + } \ + } \ + \ + bool PFX##_iter_next(SNAME##_iter *iter) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->index + 1 == PFX##_count(iter->target)) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + SNAME##_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 true; \ + } \ + \ + bool PFX##_iter_prev(SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->index == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + SNAME##_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 true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->index + 1 == PFX##_count(iter->target)) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ + return false; \ + \ + for (size_t i = 0; i < steps; i++) \ + PFX##_iter_next(iter); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool PFX##_iter_rewind(SNAME##_iter *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++) \ + PFX##_iter_prev(iter); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator was able to be positioned at the given index */ \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + { \ + if (index >= PFX##_count(iter->target)) \ + return false; \ + \ + if (iter->index > index) \ + return PFX##_iter_rewind(iter, iter->index - index); \ + else if (iter->index < index) \ + return PFX##_iter_advance(iter, index - iter->index); \ + \ + return true; \ + } \ + \ + V PFX##_iter_value(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return PFX##_impl_default_value(); \ + \ + return iter->target->buffer[iter->cursor].value; \ + } \ + \ + size_t PFX##_iter_index(SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + static bool PFX##_impl_grow(SNAME *_set_) \ + { \ + size_t new_size = _set_->capacity + _set_->capacity / 2; \ + \ + SNAME *_new_set_ = PFX##_new(new_size, _set_->load, _set_->cmp, _set_->hash); \ + \ + if (!_new_set_) \ + return false; \ + \ + SNAME##_iter iter; \ + \ + for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + PFX##_insert(_new_set_, PFX##_iter_value(&iter)); \ + } \ + \ + if (_set_->count != _new_set_->count) \ + { \ + PFX##_free(_new_set_, NULL); \ + \ + return false; \ + } \ + \ + SNAME##_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; \ + \ + PFX##_free(_new_set_, NULL); \ + \ + return true; \ + } \ + \ + static SNAME##_entry *PFX##_impl_get_entry(SNAME *_set_, V element) \ + { \ + size_t hash = _set_->hash(element); \ + size_t pos = hash % _set_->capacity; \ + \ + SNAME##_entry *target = &(_set_->buffer[pos]); \ + \ + while (target->state == CMC_ES_FILLED || target->state == CMC_ES_DELETED) \ + { \ + if (_set_->cmp(target->value, element) == 0) \ + return target; \ + \ + pos++; \ + target = &(_set_->buffer[pos % _set_->capacity]); \ + } \ + \ + return NULL; \ + } \ + \ + static size_t PFX##_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 SNAME##_iter PFX##_impl_it_start(SNAME *_set_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _set_); \ + \ + return iter; \ + } \ + \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_set_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _set_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_HASHSET_H */ diff --git a/src/cmc/heap.h b/src/cmc/heap.h index 5859929..41ab263 100644 --- a/src/cmc/heap.h +++ b/src/cmc/heap.h @@ -42,120 +42,120 @@ typedef enum cmc_heap_order_e cmc_min_heap = -1 } cmc_heap_order; -#define HEAP_GENERATE(PFX, SNAME, FMOD, V) \ - HEAP_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - HEAP_GENERATE_SOURCE(PFX, SNAME, FMOD, V) +#define CMC_GENERATE_HEAP(PFX, SNAME, V) \ + CMC_GENERATE_HEAP_HEADER(PFX, SNAME, V) \ + CMC_GENERATE_HEAP_SOURCE(PFX, SNAME, V) -#define HEAP_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \ - HEAP_GENERATE_HEADER(PFX, SNAME, FMOD, V) +#define CMC_WRAPGEN_HEAP_HEADER(PFX, SNAME, K, V) \ + CMC_GENERATE_HEAP_HEADER(PFX, SNAME, V) -#define HEAP_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \ - HEAP_GENERATE_SOURCE(PFX, SNAME, FMOD, V) +#define CMC_WRAPGEN_HEAP_SOURCE(PFX, SNAME, K, V) \ + CMC_GENERATE_HEAP_SOURCE(PFX, SNAME, V) /* HEADER ********************************************************************/ -#define HEAP_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - \ - /* Heap Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Dynamic array of elements */ \ - V *buffer; \ - \ - /* Current array capacity */ \ - size_t capacity; \ - \ - /* Current amount of elements in the heap */ \ - size_t count; \ - \ - /* Heap order (MaxHeap or MinHeap) */ \ - enum cmc_heap_order_e HO; \ - \ - /* Element comparison function */ \ - int (*cmp)(V, V); \ - \ - /* Function that returns an iterator to the start of the heap */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the heap */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Heap Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target heap */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - FMOD SNAME *PFX##_new(size_t capacity, cmc_heap_order HO, int (*compare)(V, V)); \ - FMOD void PFX##_clear(SNAME *_heap_, void (*deallocator)(V)); \ - FMOD void PFX##_free(SNAME *_heap_, void (*deallocator)(V)); \ - /* Collection Input and Output */ \ - FMOD bool PFX##_insert(SNAME *_heap_, V element); \ - FMOD bool PFX##_remove(SNAME *_heap_, V *result); \ - /* Conditional Input and Output */ \ - FMOD bool PFX##_insert_if(SNAME *_heap_, V element, bool condition); \ - FMOD bool PFX##_remove_if(SNAME *_heap_, V *result, bool condition); \ - /* Element Access */ \ - FMOD V PFX##_peek(SNAME *_heap_); \ - FMOD V *PFX##_peek_ref(SNAME *_heap_); \ - /* Collection State */ \ - FMOD bool PFX##_contains(SNAME *_heap_, V element); \ - FMOD bool PFX##_empty(SNAME *_heap_); \ - FMOD bool PFX##_full(SNAME *_heap_); \ - FMOD size_t PFX##_count(SNAME *_heap_); \ - FMOD size_t PFX##_capacity(SNAME *_heap_); \ - /* Collection Utility */ \ - FMOD SNAME *PFX##_copy_of(SNAME *_heap_, V (*copy_func)(V)); \ - FMOD bool PFX##_equals(SNAME *_heap1_, SNAME *_heap2_); \ - FMOD cmc_string PFX##_to_string(SNAME *_heap_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ - FMOD void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - FMOD V PFX##_iter_value(SNAME##_iter *iter); \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ - /* Default Value */ \ - static inline V PFX##_impl_default_value(void) \ - { \ - V _empty_value_; \ - \ - memset(&_empty_value_, 0, sizeof(V)); \ - \ - return _empty_value_; \ - } \ - \ +#define CMC_GENERATE_HEAP_HEADER(PFX, SNAME, V) \ + \ + /* Heap Structure */ \ + typedef struct SNAME##_s \ + { \ + /* Dynamic array of elements */ \ + V *buffer; \ + \ + /* Current array capacity */ \ + size_t capacity; \ + \ + /* Current amount of elements in the heap */ \ + size_t count; \ + \ + /* Heap order (MaxHeap or MinHeap) */ \ + enum cmc_heap_order_e HO; \ + \ + /* Element comparison function */ \ + int (*cmp)(V, V); \ + \ + /* Function that returns an iterator to the start of the heap */ \ + struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + \ + /* Function that returns an iterator to the end of the heap */ \ + struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + \ + } SNAME, *SNAME##_ptr; \ + \ + /* Heap Iterator */ \ + typedef struct SNAME##_iter_s \ + { \ + /* Target heap */ \ + struct SNAME##_s *target; \ + \ + /* Cursor's position (index) */ \ + size_t cursor; \ + \ + /* If the iterator has reached the start of the iteration */ \ + bool start; \ + \ + /* If the iterator has reached the end of the iteration */ \ + bool end; \ + \ + } SNAME##_iter, *SNAME##_iter_ptr; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + SNAME *PFX##_new(size_t capacity, cmc_heap_order HO, int (*compare)(V, V)); \ + void PFX##_clear(SNAME *_heap_, void (*deallocator)(V)); \ + void PFX##_free(SNAME *_heap_, void (*deallocator)(V)); \ + /* Collection Input and Output */ \ + bool PFX##_insert(SNAME *_heap_, V element); \ + bool PFX##_remove(SNAME *_heap_, V *result); \ + /* Conditional Input and Output */ \ + bool PFX##_insert_if(SNAME *_heap_, V element, bool condition); \ + bool PFX##_remove_if(SNAME *_heap_, V *result, bool condition); \ + /* Element Access */ \ + V PFX##_peek(SNAME *_heap_); \ + V *PFX##_peek_ref(SNAME *_heap_); \ + /* Collection State */ \ + bool PFX##_contains(SNAME *_heap_, V element); \ + bool PFX##_empty(SNAME *_heap_); \ + bool PFX##_full(SNAME *_heap_); \ + size_t PFX##_count(SNAME *_heap_); \ + size_t PFX##_capacity(SNAME *_heap_); \ + /* Collection Utility */ \ + SNAME *PFX##_copy_of(SNAME *_heap_, V (*copy_func)(V)); \ + bool PFX##_equals(SNAME *_heap1_, SNAME *_heap2_); \ + cmc_string PFX##_to_string(SNAME *_heap_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + SNAME##_iter *PFX##_iter_new(SNAME *target); \ + void PFX##_iter_free(SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(SNAME##_iter *iter); \ + bool PFX##_iter_end(SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(SNAME##_iter *iter); \ + void PFX##_iter_to_end(SNAME##_iter *iter); \ + bool PFX##_iter_next(SNAME##_iter *iter); \ + bool PFX##_iter_prev(SNAME##_iter *iter); \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + V PFX##_iter_value(SNAME##_iter *iter); \ + size_t PFX##_iter_index(SNAME##_iter *iter); \ + \ + /* Default Value */ \ + static inline V PFX##_impl_default_value(void) \ + { \ + V _empty_value_; \ + \ + memset(&_empty_value_, 0, sizeof(V)); \ + \ + return _empty_value_; \ + } \ + \ /* SOURCE ********************************************************************/ -#define HEAP_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ +#define CMC_GENERATE_HEAP_SOURCE(PFX, SNAME, V) \ \ /* Implementation Detail Functions */ \ static bool PFX##_impl_grow(SNAME *_heap_); \ @@ -164,7 +164,7 @@ typedef enum cmc_heap_order_e static SNAME##_iter PFX##_impl_it_start(SNAME *_heap_); \ static SNAME##_iter PFX##_impl_it_end(SNAME *_heap_); \ \ - FMOD SNAME *PFX##_new(size_t capacity, cmc_heap_order HO, int (*compare)(V, V)) \ + SNAME *PFX##_new(size_t capacity, cmc_heap_order HO, int (*compare)(V, V)) \ { \ if (capacity < 1) \ return NULL; \ @@ -198,7 +198,7 @@ typedef enum cmc_heap_order_e return _heap_; \ } \ \ - FMOD void PFX##_clear(SNAME *_heap_, void (*deallocator)(V)) \ + void PFX##_clear(SNAME *_heap_, void (*deallocator)(V)) \ { \ if (deallocator) \ { \ @@ -213,7 +213,7 @@ typedef enum cmc_heap_order_e _heap_->count = 0; \ } \ \ - FMOD void PFX##_free(SNAME *_heap_, void (*deallocator)(V)) \ + void PFX##_free(SNAME *_heap_, void (*deallocator)(V)) \ { \ if (deallocator) \ { \ @@ -227,7 +227,7 @@ typedef enum cmc_heap_order_e free(_heap_); \ } \ \ - FMOD bool PFX##_insert(SNAME *_heap_, V element) \ + bool PFX##_insert(SNAME *_heap_, V element) \ { \ if (PFX##_full(_heap_)) \ { \ @@ -249,7 +249,7 @@ typedef enum cmc_heap_order_e return true; \ } \ \ - FMOD bool PFX##_remove(SNAME *_heap_, V *result) \ + bool PFX##_remove(SNAME *_heap_, V *result) \ { \ if (PFX##_empty(_heap_)) \ return false; \ @@ -266,7 +266,7 @@ typedef enum cmc_heap_order_e return true; \ } \ \ - FMOD bool PFX##_insert_if(SNAME *_heap_, V element, bool condition) \ + bool PFX##_insert_if(SNAME *_heap_, V element, bool condition) \ { \ if (condition) \ return PFX##_insert(_heap_, element); \ @@ -274,7 +274,7 @@ typedef enum cmc_heap_order_e return false; \ } \ \ - FMOD bool PFX##_remove_if(SNAME *_heap_, V *result, bool condition) \ + bool PFX##_remove_if(SNAME *_heap_, V *result, bool condition) \ { \ if (condition) \ return PFX##_remove(_heap_, result); \ @@ -282,7 +282,7 @@ typedef enum cmc_heap_order_e return false; \ } \ \ - FMOD V PFX##_peek(SNAME *_heap_) \ + V PFX##_peek(SNAME *_heap_) \ { \ if (PFX##_empty(_heap_)) \ return PFX##_impl_default_value(); \ @@ -290,7 +290,7 @@ typedef enum cmc_heap_order_e return _heap_->buffer[0]; \ } \ \ - FMOD V *PFX##_peek_ref(SNAME *_heap_) \ + V *PFX##_peek_ref(SNAME *_heap_) \ { \ if (PFX##_empty(_heap_)) \ return NULL; \ @@ -298,7 +298,7 @@ typedef enum cmc_heap_order_e return &(_heap_->buffer[0]); \ } \ \ - FMOD bool PFX##_contains(SNAME *_heap_, V element) \ + bool PFX##_contains(SNAME *_heap_, V element) \ { \ for (size_t i = 0; i < _heap_->count; i++) \ { \ @@ -309,27 +309,27 @@ typedef enum cmc_heap_order_e return false; \ } \ \ - FMOD bool PFX##_empty(SNAME *_heap_) \ + bool PFX##_empty(SNAME *_heap_) \ { \ return _heap_->count == 0; \ } \ \ - FMOD bool PFX##_full(SNAME *_heap_) \ + bool PFX##_full(SNAME *_heap_) \ { \ return _heap_->count >= _heap_->capacity; \ } \ \ - FMOD size_t PFX##_count(SNAME *_heap_) \ + size_t PFX##_count(SNAME *_heap_) \ { \ return _heap_->count; \ } \ \ - FMOD size_t PFX##_capacity(SNAME *_heap_) \ + size_t PFX##_capacity(SNAME *_heap_) \ { \ return _heap_->capacity; \ } \ \ - FMOD SNAME *PFX##_copy_of(SNAME *_heap_, V (*copy_func)(V)) \ + SNAME *PFX##_copy_of(SNAME *_heap_, V (*copy_func)(V)) \ { \ SNAME *result = PFX##_new(_heap_->capacity, _heap_->HO, _heap_->cmp); \ \ @@ -349,7 +349,7 @@ typedef enum cmc_heap_order_e return result; \ } \ \ - FMOD bool PFX##_equals(SNAME *_heap1_, SNAME *_heap2_) \ + bool PFX##_equals(SNAME *_heap1_, SNAME *_heap2_) \ { \ if (PFX##_count(_heap1_) != PFX##_count(_heap2_)) \ return false; \ @@ -363,7 +363,7 @@ typedef enum cmc_heap_order_e return true; \ } \ \ - FMOD cmc_string PFX##_to_string(SNAME *_heap_) \ + cmc_string PFX##_to_string(SNAME *_heap_) \ { \ cmc_string str; \ SNAME *h_ = _heap_; \ @@ -376,7 +376,7 @@ typedef enum cmc_heap_order_e return str; \ } \ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ + SNAME##_iter *PFX##_iter_new(SNAME *target) \ { \ SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ \ @@ -388,12 +388,12 @@ typedef enum cmc_heap_order_e return iter; \ } \ \ - FMOD void PFX##_iter_free(SNAME##_iter *iter) \ + void PFX##_iter_free(SNAME##_iter *iter) \ { \ free(iter); \ } \ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ { \ iter->target = target; \ iter->cursor = 0; \ @@ -401,17 +401,17 @@ typedef enum cmc_heap_order_e iter->end = PFX##_empty(target); \ } \ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ + bool PFX##_iter_start(SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->start; \ } \ \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ + bool PFX##_iter_end(SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->end; \ } \ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ + void PFX##_iter_to_start(SNAME##_iter *iter) \ { \ if (!PFX##_empty(iter->target)) \ { \ @@ -421,7 +421,7 @@ typedef enum cmc_heap_order_e } \ } \ \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ + void PFX##_iter_to_end(SNAME##_iter *iter) \ { \ if (!PFX##_empty(iter->target)) \ { \ @@ -431,7 +431,7 @@ typedef enum cmc_heap_order_e } \ } \ \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ + bool PFX##_iter_next(SNAME##_iter *iter) \ { \ if (iter->end) \ return false; \ @@ -449,7 +449,7 @@ typedef enum cmc_heap_order_e return true; \ } \ \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ + bool PFX##_iter_prev(SNAME##_iter *iter) \ { \ if (iter->start) \ return false; \ @@ -468,7 +468,7 @@ typedef enum cmc_heap_order_e } \ \ /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ { \ if (iter->start) \ return false; \ @@ -493,7 +493,7 @@ typedef enum cmc_heap_order_e } \ \ /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ { \ if (iter->start) \ return false; \ @@ -515,7 +515,7 @@ typedef enum cmc_heap_order_e } \ \ /* Returns true only if the iterator was able to be positioned at the given index */ \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ { \ if (index >= PFX##_count(iter->target)) \ return false; \ @@ -528,7 +528,7 @@ typedef enum cmc_heap_order_e return true; \ } \ \ - FMOD V PFX##_iter_value(SNAME##_iter *iter) \ + V PFX##_iter_value(SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ return PFX##_impl_default_value(); \ @@ -536,7 +536,7 @@ typedef enum cmc_heap_order_e return iter->target->buffer[iter->cursor]; \ } \ \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ + size_t PFX##_iter_index(SNAME##_iter *iter) \ { \ return iter->cursor; \ } \ diff --git a/src/cmc/linkedlist.h b/src/cmc/linkedlist.h index b671f61..adc026a 100644 --- a/src/cmc/linkedlist.h +++ b/src/cmc/linkedlist.h @@ -34,897 +34,897 @@ #include #include "../utl/cmc_string.h" -#define LINKEDLIST_GENERATE(PFX, SNAME, FMOD, V) \ - LINKEDLIST_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - LINKEDLIST_GENERATE_SOURCE(PFX, SNAME, FMOD, V) +#define CMC_GENERATE_LINKEDLIST(PFX, SNAME, V) \ + CMC_GENERATE_LINKEDLIST_HEADER(PFX, SNAME, V) \ + CMC_GENERATE_LINKEDLIST_SOURCE(PFX, SNAME, V) -#define LINKEDLIST_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \ - LINKEDLIST_GENERATE_HEADER(PFX, SNAME, FMOD, V) +#define CMC_WRAPGEN_LINKEDLIST_HEADER(PFX, SNAME, K, V) \ + CMC_GENERATE_LINKEDLIST_HEADER(PFX, SNAME, V) -#define LINKEDLIST_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \ - LINKEDLIST_GENERATE_SOURCE(PFX, SNAME, FMOD, V) +#define CMC_WRAPGEN_LINKEDLIST_SOURCE(PFX, SNAME, K, V) \ + CMC_GENERATE_LINKEDLIST_SOURCE(PFX, SNAME, V) /* HEADER ********************************************************************/ -#define LINKEDLIST_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - \ - /* Linked List Structure */ \ - typedef struct SNAME##_s \ - { \ - /* First node in the list */ \ - struct SNAME##_node_s *head; \ - \ - /* Last node in the list */ \ - struct SNAME##_node_s *tail; \ - \ - /* Current amount of elements in the list */ \ - size_t count; \ - \ - /* Function that returns an iterator to the start of the list */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the list */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Doubly-linked list node */ \ - typedef struct SNAME##_node_s \ - { \ - /* Node's data */ \ - V data; \ - \ - /* Pointer to the next node on the linked list */ \ - struct SNAME##_node_s *next; \ - \ - /* Pointer to the previous node on the linked list */ \ - struct SNAME##_node_s *prev; \ - \ - } SNAME##_node, *SNAME##_node_ptr; \ - \ - /* Linked List Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target Linked List */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's current node */ \ - struct SNAME##_node_s *cursor; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - FMOD SNAME *PFX##_new(void); \ - FMOD void PFX##_clear(SNAME *_list_, void (*deallocator)(V)); \ - FMOD void PFX##_free(SNAME *_list_, void (*deallocator)(V)); \ - /* Collection Input and Output */ \ - FMOD bool PFX##_push_front(SNAME *_list_, V element); \ - FMOD bool PFX##_push(SNAME *_list_, V element, size_t index); \ - FMOD bool PFX##_push_back(SNAME *_list_, V element); \ - FMOD bool PFX##_pop_front(SNAME *_list_); \ - FMOD bool PFX##_pop(SNAME *_list_, size_t index); \ - FMOD bool PFX##_pop_back(SNAME *_list_); \ - /* Conditional Input and Output */ \ - FMOD bool PFX##_push_if(SNAME *_list_, V element, size_t index, bool condition); \ - FMOD bool PFX##_pop_if(SNAME *_list_, size_t index, bool condition); \ - /* Element Access */ \ - FMOD V PFX##_front(SNAME *_list_); \ - FMOD V PFX##_get(SNAME *_list_, size_t index); \ - FMOD V *PFX##_get_ref(SNAME *_list_, size_t index); \ - FMOD V PFX##_back(SNAME *_list_); \ - /* Collection State */ \ - FMOD bool PFX##_contains(SNAME *_list_, V element, int (*comparator)(V, V)); \ - FMOD bool PFX##_empty(SNAME *_list_); \ - FMOD size_t PFX##_count(SNAME *_list_); \ - /* Collection Utility */ \ - FMOD SNAME *PFX##_copy_of(SNAME *_list_, V (*copy_func)(V)); \ - FMOD bool PFX##_equals(SNAME *_list1_, SNAME *_list2_, int (*comparator)(V, V)); \ - FMOD cmc_string PFX##_to_string(SNAME *_list_); \ - \ - /* Node Related Functions */ \ - /* Node Allocation and Deallocation */ \ - FMOD SNAME##_node *PFX##_new_node(V element); \ - FMOD void PFX##_free_node(SNAME##_node *_node_); \ - /* Node Access Relative to a Linked List */ \ - FMOD SNAME##_node *PFX##_head(SNAME *_list_); \ - FMOD SNAME##_node *PFX##_get_node(SNAME *_list_, size_t index); \ - FMOD SNAME##_node *PFX##_tail(SNAME *_list_); \ - /* Input and Output Relative to a Node */ \ - FMOD bool PFX##_insert_after(SNAME *_owner_, SNAME##_node *_node_, V element); \ - FMOD bool PFX##_insert_before(SNAME *_owner_, SNAME##_node *_node_, V element); \ - FMOD bool PFX##_remove_after(SNAME *_owner_, SNAME##_node *_node_); \ - FMOD bool PFX##_remove_current(SNAME *_owner_, SNAME##_node *_node_); \ - FMOD bool PFX##_remove_before(SNAME *_owner_, SNAME##_node *_node_); \ - /* Node Access Relative to a Linked List Node */ \ - FMOD SNAME##_node *PFX##_next_node(SNAME##_node *_node_); \ - FMOD SNAME##_node *PFX##_prev_node(SNAME##_node *_node_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ - FMOD void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - FMOD V PFX##_iter_value(SNAME##_iter *iter); \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ - FMOD SNAME##_node *PFX##_iter_node(SNAME##_iter *iter); \ - \ - /* Default Value */ \ - static inline V PFX##_impl_default_value(void) \ - { \ - V _empty_value_; \ - \ - memset(&_empty_value_, 0, sizeof(V)); \ - \ - return _empty_value_; \ - } \ - \ +#define CMC_GENERATE_LINKEDLIST_HEADER(PFX, SNAME, V) \ + \ + /* Linked List Structure */ \ + typedef struct SNAME##_s \ + { \ + /* First node in the list */ \ + struct SNAME##_node_s *head; \ + \ + /* Last node in the list */ \ + struct SNAME##_node_s *tail; \ + \ + /* Current amount of elements in the list */ \ + size_t count; \ + \ + /* Function that returns an iterator to the start of the list */ \ + struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + \ + /* Function that returns an iterator to the end of the list */ \ + struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + \ + } SNAME, *SNAME##_ptr; \ + \ + /* Doubly-linked list node */ \ + typedef struct SNAME##_node_s \ + { \ + /* Node's data */ \ + V data; \ + \ + /* Pointer to the next node on the linked list */ \ + struct SNAME##_node_s *next; \ + \ + /* Pointer to the previous node on the linked list */ \ + struct SNAME##_node_s *prev; \ + \ + } SNAME##_node, *SNAME##_node_ptr; \ + \ + /* Linked List Iterator */ \ + typedef struct SNAME##_iter_s \ + { \ + /* Target Linked List */ \ + struct SNAME##_s *target; \ + \ + /* Cursor's current node */ \ + struct SNAME##_node_s *cursor; \ + \ + /* Keeps track of relative index to the iteration of elements */ \ + size_t index; \ + \ + /* If the iterator has reached the start of the iteration */ \ + bool start; \ + \ + /* If the iterator has reached the end of the iteration */ \ + bool end; \ + \ + } SNAME##_iter, *SNAME##_iter_ptr; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + SNAME *PFX##_new(void); \ + void PFX##_clear(SNAME *_list_, void (*deallocator)(V)); \ + void PFX##_free(SNAME *_list_, void (*deallocator)(V)); \ + /* Collection Input and Output */ \ + bool PFX##_push_front(SNAME *_list_, V element); \ + bool PFX##_push(SNAME *_list_, V element, size_t index); \ + bool PFX##_push_back(SNAME *_list_, V element); \ + bool PFX##_pop_front(SNAME *_list_); \ + bool PFX##_pop(SNAME *_list_, size_t index); \ + bool PFX##_pop_back(SNAME *_list_); \ + /* Conditional Input and Output */ \ + bool PFX##_push_if(SNAME *_list_, V element, size_t index, bool condition); \ + bool PFX##_pop_if(SNAME *_list_, size_t index, bool condition); \ + /* Element Access */ \ + V PFX##_front(SNAME *_list_); \ + V PFX##_get(SNAME *_list_, size_t index); \ + V *PFX##_get_ref(SNAME *_list_, size_t index); \ + V PFX##_back(SNAME *_list_); \ + /* Collection State */ \ + bool PFX##_contains(SNAME *_list_, V element, int (*comparator)(V, V)); \ + bool PFX##_empty(SNAME *_list_); \ + size_t PFX##_count(SNAME *_list_); \ + /* Collection Utility */ \ + SNAME *PFX##_copy_of(SNAME *_list_, V (*copy_func)(V)); \ + bool PFX##_equals(SNAME *_list1_, SNAME *_list2_, int (*comparator)(V, V)); \ + cmc_string PFX##_to_string(SNAME *_list_); \ + \ + /* Node Related Functions */ \ + /* Node Allocation and Deallocation */ \ + SNAME##_node *PFX##_new_node(V element); \ + void PFX##_free_node(SNAME##_node *_node_); \ + /* Node Access Relative to a Linked List */ \ + SNAME##_node *PFX##_head(SNAME *_list_); \ + SNAME##_node *PFX##_get_node(SNAME *_list_, size_t index); \ + SNAME##_node *PFX##_tail(SNAME *_list_); \ + /* Input and Output Relative to a Node */ \ + bool PFX##_insert_after(SNAME *_owner_, SNAME##_node *_node_, V element); \ + bool PFX##_insert_before(SNAME *_owner_, SNAME##_node *_node_, V element); \ + bool PFX##_remove_after(SNAME *_owner_, SNAME##_node *_node_); \ + bool PFX##_remove_current(SNAME *_owner_, SNAME##_node *_node_); \ + bool PFX##_remove_before(SNAME *_owner_, SNAME##_node *_node_); \ + /* Node Access Relative to a Linked List Node */ \ + SNAME##_node *PFX##_next_node(SNAME##_node *_node_); \ + SNAME##_node *PFX##_prev_node(SNAME##_node *_node_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + SNAME##_iter *PFX##_iter_new(SNAME *target); \ + void PFX##_iter_free(SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(SNAME##_iter *iter); \ + bool PFX##_iter_end(SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(SNAME##_iter *iter); \ + void PFX##_iter_to_end(SNAME##_iter *iter); \ + bool PFX##_iter_next(SNAME##_iter *iter); \ + bool PFX##_iter_prev(SNAME##_iter *iter); \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + V PFX##_iter_value(SNAME##_iter *iter); \ + V *PFX##_iter_rvalue(SNAME##_iter *iter); \ + size_t PFX##_iter_index(SNAME##_iter *iter); \ + SNAME##_node *PFX##_iter_node(SNAME##_iter *iter); \ + \ + /* Default Value */ \ + static inline V PFX##_impl_default_value(void) \ + { \ + V _empty_value_; \ + \ + memset(&_empty_value_, 0, sizeof(V)); \ + \ + return _empty_value_; \ + } \ + \ /* SOURCE ********************************************************************/ -#define LINKEDLIST_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ - \ - /* Implementation Detail Functions */ \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_list_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_list_); \ - \ - FMOD SNAME *PFX##_new(void) \ - { \ - SNAME *_list_ = malloc(sizeof(SNAME)); \ - \ - if (!_list_) \ - return NULL; \ - \ - _list_->count = 0; \ - _list_->head = NULL; \ - _list_->tail = NULL; \ - \ - _list_->it_start = PFX##_impl_it_start; \ - _list_->it_end = PFX##_impl_it_end; \ - \ - return _list_; \ - } \ - \ - FMOD void PFX##_clear(SNAME *_list_, void (*deallocator)(V)) \ - { \ - SNAME##_node *scan = _list_->head; \ - \ - while (_list_->head != NULL) \ - { \ - _list_->head = _list_->head->next; \ - \ - if (deallocator) \ - { \ - deallocator(scan->data); \ - } \ - \ - free(scan); \ - \ - scan = _list_->head; \ - } \ - \ - _list_->count = 0; \ - _list_->head = NULL; \ - _list_->tail = NULL; \ - } \ - \ - FMOD void PFX##_free(SNAME *_list_, void (*deallocator)(V)) \ - { \ - PFX##_clear(_list_, deallocator); \ - \ - free(_list_); \ - } \ - \ - FMOD bool PFX##_push_front(SNAME *_list_, V element) \ - { \ - SNAME##_node *_node_ = PFX##_new_node(element); \ - \ - if (!_node_) \ - return false; \ - \ - if (PFX##_empty(_list_)) \ - { \ - _list_->head = _node_; \ - _list_->tail = _node_; \ - } \ - else \ - { \ - _node_->next = _list_->head; \ - _list_->head->prev = _node_; \ - _list_->head = _node_; \ - } \ - \ - _list_->count++; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_push(SNAME *_list_, V element, size_t index) \ - { \ - if (index > _list_->count) \ - return false; \ - \ - if (index == 0) \ - { \ - return PFX##_push_front(_list_, element); \ - } \ - else if (index == _list_->count) \ - { \ - return PFX##_push_back(_list_, element); \ - } \ - \ - SNAME##_node *_node_ = PFX##_new_node(element); \ - \ - if (!_node_) \ - return false; \ - \ - SNAME##_node *scan = PFX##_get_node(_list_, index - 1); \ - \ - _node_->next = scan->next; \ - _node_->prev = scan; \ - _node_->next->prev = _node_; \ - _node_->prev->next = _node_; \ - \ - _list_->count++; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_push_back(SNAME *_list_, V element) \ - { \ - SNAME##_node *_node_ = PFX##_new_node(element); \ - \ - if (!_node_) \ - return false; \ - \ - if (PFX##_empty(_list_)) \ - { \ - _list_->head = _node_; \ - _list_->tail = _node_; \ - } \ - else \ - { \ - _node_->prev = _list_->tail; \ - _list_->tail->next = _node_; \ - _list_->tail = _node_; \ - } \ - \ - _list_->count++; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_pop_front(SNAME *_list_) \ - { \ - if (PFX##_empty(_list_)) \ - return false; \ - \ - SNAME##_node *_node_ = _list_->head; \ - _list_->head = _list_->head->next; \ - \ - free(_node_); \ - \ - if (_list_->head == NULL) \ - _list_->tail = NULL; \ - else \ - _list_->head->prev = NULL; \ - \ - _list_->count--; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_pop(SNAME *_list_, size_t index) \ - { \ - if (PFX##_empty(_list_)) \ - return false; \ - \ - if (index >= _list_->count) \ - return false; \ - \ - if (index == 0) \ - { \ - return PFX##_pop_front(_list_); \ - } \ - else if (index == _list_->count - 1) \ - { \ - return PFX##_pop_back(_list_); \ - } \ - \ - SNAME##_node *_node_ = PFX##_get_node(_list_, index); \ - \ - if (!_node_) \ - return false; \ - \ - _node_->next->prev = _node_->prev; \ - _node_->prev->next = _node_->next; \ - \ - free(_node_); \ - \ - _list_->count--; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_pop_back(SNAME *_list_) \ - { \ - if (PFX##_empty(_list_)) \ - return false; \ - \ - SNAME##_node *_node_ = _list_->tail; \ - _list_->tail = _list_->tail->prev; \ - \ - free(_node_); \ - \ - if (_list_->tail == NULL) \ - _list_->head = NULL; \ - else \ - _list_->tail->next = NULL; \ - \ - _list_->count--; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_push_if(SNAME *_list_, V element, size_t index, bool condition) \ - { \ - if (condition) \ - return PFX##_push(_list_, element, index); \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_pop_if(SNAME *_list_, size_t index, bool condition) \ - { \ - if (condition) \ - return PFX##_pop(_list_, index); \ - \ - return false; \ - } \ - \ - FMOD V PFX##_front(SNAME *_list_) \ - { \ - if (PFX##_empty(_list_)) \ - return PFX##_impl_default_value(); \ - \ - return _list_->head->data; \ - } \ - \ - FMOD V PFX##_get(SNAME *_list_, size_t index) \ - { \ - if (index >= _list_->count || PFX##_empty(_list_)) \ - return PFX##_impl_default_value(); \ - \ - SNAME##_node *scan = PFX##_get_node(_list_, index); \ - \ - if (scan == NULL) \ - return PFX##_impl_default_value(); \ - \ - return scan->data; \ - } \ - \ - FMOD V *PFX##_get_ref(SNAME *_list_, size_t index) \ - { \ - if (index >= _list_->count) \ - return NULL; \ - \ - if (PFX##_empty(_list_)) \ - return NULL; \ - \ - SNAME##_node *scan = PFX##_get_node(_list_, index); \ - \ - if (scan == NULL) \ - return NULL; \ - \ - return &(scan->data); \ - } \ - \ - FMOD V PFX##_back(SNAME *_list_) \ - { \ - if (PFX##_empty(_list_)) \ - return PFX##_impl_default_value(); \ - \ - return _list_->tail->data; \ - } \ - \ - FMOD bool PFX##_contains(SNAME *_list_, V element, int (*comparator)(V, V)) \ - { \ - SNAME##_node *scan = _list_->head; \ - \ - while (scan != NULL) \ - { \ - if (comparator(scan->data, element) == 0) \ - return true; \ - \ - scan = scan->next; \ - } \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_empty(SNAME *_list_) \ - { \ - return _list_->count == 0; \ - } \ - \ - FMOD size_t PFX##_count(SNAME *_list_) \ - { \ - return _list_->count; \ - } \ - \ - FMOD SNAME *PFX##_copy_of(SNAME *_list_, V (*copy_func)(V)) \ - { \ - SNAME *result = PFX##_new(); \ - \ - if (!result) \ - return NULL; \ - \ - SNAME##_node *scan = _list_->head; \ - \ - while (scan != NULL) \ - { \ - /* This allocation should never fail since it might not be */ \ - /* possible to recover from it. That is why it isn't checked */ \ - SNAME##_node *new_node; \ - \ - if (copy_func) \ - new_node = PFX##_new_node(copy_func(scan->data)); \ - else \ - new_node = PFX##_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; \ - } \ - \ - FMOD bool PFX##_equals(SNAME *_list1_, SNAME *_list2_, int (*comparator)(V, V)) \ - { \ - if (PFX##_count(_list1_) != PFX##_count(_list2_)) \ - return false; \ - \ - SNAME##_node *scan1 = _list1_->head; \ - SNAME##_node *scan2 = _list2_->head; \ - \ - while (scan1 != NULL && scan2 != NULL) \ - { \ - if (comparator(scan1->data, scan2->data) != 0) \ - return false; \ - \ - scan1 = scan1->next; \ - scan2 = scan2->next; \ - } \ - \ - return true; \ - } \ - \ - FMOD cmc_string PFX##_to_string(SNAME *_list_) \ - { \ - cmc_string str; \ - SNAME *l_ = _list_; \ - const char *name = #SNAME; \ - \ - snprintf(str.s, cmc_string_len, cmc_string_fmt_linkedlist, \ - name, l_, l_->count, l_->head, l_->tail); \ - \ - return str; \ - } \ - \ - FMOD SNAME##_node *PFX##_new_node(V element) \ - { \ - SNAME##_node *_node_ = malloc(sizeof(SNAME##_node)); \ - \ - if (!_node_) \ - return NULL; \ - \ - _node_->data = element; \ - _node_->next = NULL; \ - _node_->prev = NULL; \ - \ - return _node_; \ - } \ - \ - FMOD void PFX##_free_node(SNAME##_node *_node_) \ - { \ - free(_node_); \ - } \ - \ - FMOD SNAME##_node *PFX##_head(SNAME *_list_) \ - { \ - return _list_->head; \ - } \ - \ - FMOD SNAME##_node *PFX##_get_node(SNAME *_list_, size_t index) \ - { \ - if (index >= _list_->count) \ - return NULL; \ - \ - if (PFX##_empty(_list_)) \ - return NULL; \ - \ - SNAME##_node *_node_ = NULL; \ - \ - if (index <= _list_->count / 2) \ - { \ - _node_ = _list_->head; \ - for (size_t i = 0; i < index; i++) \ - { \ - _node_ = _node_->next; \ - } \ - } \ - else \ - { \ - _node_ = _list_->tail; \ - for (size_t i = _list_->count - 1; i > index; i--) \ - { \ - _node_ = _node_->prev; \ - } \ - } \ - \ - return _node_; \ - } \ - \ - FMOD SNAME##_node *PFX##_tail(SNAME *_list_) \ - { \ - return _list_->tail; \ - } \ - \ - FMOD bool PFX##_insert_after(SNAME *_owner_, SNAME##_node *_node_, V element) \ - { \ - SNAME##_node *new_node = PFX##_new_node(element); \ - \ - if (!new_node) \ - return false; \ - \ - new_node->next = _node_->next; \ - \ - if (_node_->next != NULL) \ - _node_->next->prev = new_node; \ - else \ - _owner_->tail = new_node; \ - \ - new_node->prev = _node_; \ - _node_->next = new_node; \ - \ - _owner_->count++; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_insert_before(SNAME *_owner_, SNAME##_node *_node_, V element) \ - { \ - SNAME##_node *new_node = PFX##_new_node(element); \ - \ - if (!new_node) \ - return false; \ - \ - new_node->prev = _node_->prev; \ - \ - if (_node_->prev != NULL) \ - _node_->prev->next = new_node; \ - else \ - _owner_->head = new_node; \ - \ - new_node->next = _node_; \ - _node_->prev = new_node; \ - \ - _owner_->count++; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_remove_after(SNAME *_owner_, SNAME##_node *_node_) \ - { \ - if (_node_->next == NULL) \ - return false; \ - \ - SNAME##_node *tmp = _node_->next; \ - \ - if (tmp->next != NULL) \ - { \ - _node_->next = _node_->next->next; \ - _node_->next->prev = _node_; \ - } \ - else \ - _owner_->tail = _node_; \ - \ - free(tmp); \ - \ - _owner_->count--; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_remove_current(SNAME *_owner_, SNAME##_node *_node_) \ - { \ - if (_node_->prev != NULL) \ - _node_->prev->next = _node_->next; \ - else \ - _owner_->head = _node_->next; \ - \ - if (_node_->next != NULL) \ - _node_->next->prev = _node_->prev; \ - else \ - _owner_->tail = _node_->prev; \ - \ - free(_node_); \ - \ - _owner_->count--; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_remove_before(SNAME *_owner_, SNAME##_node *_node_) \ - { \ - if (_node_->prev == NULL) \ - return false; \ - \ - SNAME##_node *tmp = _node_->prev; \ - \ - if (tmp->prev != NULL) \ - { \ - _node_->prev = _node_->prev->prev; \ - _node_->prev->next = _node_; \ - } \ - else \ - _owner_->head = _node_; \ - \ - free(tmp); \ - \ - _owner_->count--; \ - \ - return true; \ - } \ - \ - FMOD SNAME##_node *PFX##_next_node(SNAME##_node *_node_) \ - { \ - return _node_->next; \ - } \ - \ - FMOD SNAME##_node *PFX##_prev_node(SNAME##_node *_node_) \ - { \ - return _node_->prev; \ - } \ - \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ - { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - FMOD void PFX##_iter_free(SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ - { \ - iter->target = target; \ - iter->cursor = target->head; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - } \ - \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->target->head; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - } \ - } \ - \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->target->tail; \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - } \ - } \ - \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->cursor->next == NULL) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - iter->cursor = iter->cursor->next; \ - iter->index++; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->cursor->prev == NULL) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - iter->cursor = iter->cursor->prev; \ - iter->index--; \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->cursor->next == NULL) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ - return false; \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - iter->index += steps; \ - \ - for (size_t i = 0; i < steps; i++) \ - iter->cursor = iter->cursor->next; \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->cursor->prev == NULL) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index < steps) \ - return false; \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - iter->index -= steps; \ - \ - for (size_t i = 0; i < steps; i++) \ - iter->cursor = iter->cursor->prev; \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator was able to be positioned at the given */ \ - /* index */ \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ - { \ - if (index >= PFX##_count(iter->target)) \ - return false; \ - \ - if (iter->index > index) \ - return PFX##_iter_rewind(iter, iter->index - index); \ - else if (iter->index < index) \ - return PFX##_iter_advance(iter, index - iter->index); \ - \ - return true; \ - } \ - \ - FMOD V PFX##_iter_value(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return PFX##_impl_default_value(); \ - \ - return iter->cursor->data; \ - } \ - \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->cursor->data); \ - } \ - \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - FMOD SNAME##_node *PFX##_iter_node(SNAME##_iter *iter) \ - { \ - return iter->cursor; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_list_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _list_); \ - PFX##_iter_to_start(&iter); \ - \ - return iter; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_list_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _list_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ +#define CMC_GENERATE_LINKEDLIST_SOURCE(PFX, SNAME, V) \ + \ + /* Implementation Detail Functions */ \ + static SNAME##_iter PFX##_impl_it_start(SNAME *_list_); \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_list_); \ + \ + SNAME *PFX##_new(void) \ + { \ + SNAME *_list_ = malloc(sizeof(SNAME)); \ + \ + if (!_list_) \ + return NULL; \ + \ + _list_->count = 0; \ + _list_->head = NULL; \ + _list_->tail = NULL; \ + \ + _list_->it_start = PFX##_impl_it_start; \ + _list_->it_end = PFX##_impl_it_end; \ + \ + return _list_; \ + } \ + \ + void PFX##_clear(SNAME *_list_, void (*deallocator)(V)) \ + { \ + SNAME##_node *scan = _list_->head; \ + \ + while (_list_->head != NULL) \ + { \ + _list_->head = _list_->head->next; \ + \ + if (deallocator) \ + { \ + deallocator(scan->data); \ + } \ + \ + free(scan); \ + \ + scan = _list_->head; \ + } \ + \ + _list_->count = 0; \ + _list_->head = NULL; \ + _list_->tail = NULL; \ + } \ + \ + void PFX##_free(SNAME *_list_, void (*deallocator)(V)) \ + { \ + PFX##_clear(_list_, deallocator); \ + \ + free(_list_); \ + } \ + \ + bool PFX##_push_front(SNAME *_list_, V element) \ + { \ + SNAME##_node *_node_ = PFX##_new_node(element); \ + \ + if (!_node_) \ + return false; \ + \ + if (PFX##_empty(_list_)) \ + { \ + _list_->head = _node_; \ + _list_->tail = _node_; \ + } \ + else \ + { \ + _node_->next = _list_->head; \ + _list_->head->prev = _node_; \ + _list_->head = _node_; \ + } \ + \ + _list_->count++; \ + \ + return true; \ + } \ + \ + bool PFX##_push(SNAME *_list_, V element, size_t index) \ + { \ + if (index > _list_->count) \ + return false; \ + \ + if (index == 0) \ + { \ + return PFX##_push_front(_list_, element); \ + } \ + else if (index == _list_->count) \ + { \ + return PFX##_push_back(_list_, element); \ + } \ + \ + SNAME##_node *_node_ = PFX##_new_node(element); \ + \ + if (!_node_) \ + return false; \ + \ + SNAME##_node *scan = PFX##_get_node(_list_, index - 1); \ + \ + _node_->next = scan->next; \ + _node_->prev = scan; \ + _node_->next->prev = _node_; \ + _node_->prev->next = _node_; \ + \ + _list_->count++; \ + \ + return true; \ + } \ + \ + bool PFX##_push_back(SNAME *_list_, V element) \ + { \ + SNAME##_node *_node_ = PFX##_new_node(element); \ + \ + if (!_node_) \ + return false; \ + \ + if (PFX##_empty(_list_)) \ + { \ + _list_->head = _node_; \ + _list_->tail = _node_; \ + } \ + else \ + { \ + _node_->prev = _list_->tail; \ + _list_->tail->next = _node_; \ + _list_->tail = _node_; \ + } \ + \ + _list_->count++; \ + \ + return true; \ + } \ + \ + bool PFX##_pop_front(SNAME *_list_) \ + { \ + if (PFX##_empty(_list_)) \ + return false; \ + \ + SNAME##_node *_node_ = _list_->head; \ + _list_->head = _list_->head->next; \ + \ + free(_node_); \ + \ + if (_list_->head == NULL) \ + _list_->tail = NULL; \ + else \ + _list_->head->prev = NULL; \ + \ + _list_->count--; \ + \ + return true; \ + } \ + \ + bool PFX##_pop(SNAME *_list_, size_t index) \ + { \ + if (PFX##_empty(_list_)) \ + return false; \ + \ + if (index >= _list_->count) \ + return false; \ + \ + if (index == 0) \ + { \ + return PFX##_pop_front(_list_); \ + } \ + else if (index == _list_->count - 1) \ + { \ + return PFX##_pop_back(_list_); \ + } \ + \ + SNAME##_node *_node_ = PFX##_get_node(_list_, index); \ + \ + if (!_node_) \ + return false; \ + \ + _node_->next->prev = _node_->prev; \ + _node_->prev->next = _node_->next; \ + \ + free(_node_); \ + \ + _list_->count--; \ + \ + return true; \ + } \ + \ + bool PFX##_pop_back(SNAME *_list_) \ + { \ + if (PFX##_empty(_list_)) \ + return false; \ + \ + SNAME##_node *_node_ = _list_->tail; \ + _list_->tail = _list_->tail->prev; \ + \ + free(_node_); \ + \ + if (_list_->tail == NULL) \ + _list_->head = NULL; \ + else \ + _list_->tail->next = NULL; \ + \ + _list_->count--; \ + \ + return true; \ + } \ + \ + bool PFX##_push_if(SNAME *_list_, V element, size_t index, bool condition) \ + { \ + if (condition) \ + return PFX##_push(_list_, element, index); \ + \ + return false; \ + } \ + \ + bool PFX##_pop_if(SNAME *_list_, size_t index, bool condition) \ + { \ + if (condition) \ + return PFX##_pop(_list_, index); \ + \ + return false; \ + } \ + \ + V PFX##_front(SNAME *_list_) \ + { \ + if (PFX##_empty(_list_)) \ + return PFX##_impl_default_value(); \ + \ + return _list_->head->data; \ + } \ + \ + V PFX##_get(SNAME *_list_, size_t index) \ + { \ + if (index >= _list_->count || PFX##_empty(_list_)) \ + return PFX##_impl_default_value(); \ + \ + SNAME##_node *scan = PFX##_get_node(_list_, index); \ + \ + if (scan == NULL) \ + return PFX##_impl_default_value(); \ + \ + return scan->data; \ + } \ + \ + V *PFX##_get_ref(SNAME *_list_, size_t index) \ + { \ + if (index >= _list_->count) \ + return NULL; \ + \ + if (PFX##_empty(_list_)) \ + return NULL; \ + \ + SNAME##_node *scan = PFX##_get_node(_list_, index); \ + \ + if (scan == NULL) \ + return NULL; \ + \ + return &(scan->data); \ + } \ + \ + V PFX##_back(SNAME *_list_) \ + { \ + if (PFX##_empty(_list_)) \ + return PFX##_impl_default_value(); \ + \ + return _list_->tail->data; \ + } \ + \ + bool PFX##_contains(SNAME *_list_, V element, int (*comparator)(V, V)) \ + { \ + SNAME##_node *scan = _list_->head; \ + \ + while (scan != NULL) \ + { \ + if (comparator(scan->data, element) == 0) \ + return true; \ + \ + scan = scan->next; \ + } \ + \ + return false; \ + } \ + \ + bool PFX##_empty(SNAME *_list_) \ + { \ + return _list_->count == 0; \ + } \ + \ + size_t PFX##_count(SNAME *_list_) \ + { \ + return _list_->count; \ + } \ + \ + SNAME *PFX##_copy_of(SNAME *_list_, V (*copy_func)(V)) \ + { \ + SNAME *result = PFX##_new(); \ + \ + if (!result) \ + return NULL; \ + \ + SNAME##_node *scan = _list_->head; \ + \ + while (scan != NULL) \ + { \ + /* This allocation should never fail since it might not be */ \ + /* possible to recover from it. That is why it isn't checked */ \ + SNAME##_node *new_node; \ + \ + if (copy_func) \ + new_node = PFX##_new_node(copy_func(scan->data)); \ + else \ + new_node = PFX##_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 PFX##_equals(SNAME *_list1_, SNAME *_list2_, int (*comparator)(V, V)) \ + { \ + if (PFX##_count(_list1_) != PFX##_count(_list2_)) \ + return false; \ + \ + SNAME##_node *scan1 = _list1_->head; \ + SNAME##_node *scan2 = _list2_->head; \ + \ + while (scan1 != NULL && scan2 != NULL) \ + { \ + if (comparator(scan1->data, scan2->data) != 0) \ + return false; \ + \ + scan1 = scan1->next; \ + scan2 = scan2->next; \ + } \ + \ + return true; \ + } \ + \ + cmc_string PFX##_to_string(SNAME *_list_) \ + { \ + cmc_string str; \ + SNAME *l_ = _list_; \ + const char *name = #SNAME; \ + \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_linkedlist, \ + name, l_, l_->count, l_->head, l_->tail); \ + \ + return str; \ + } \ + \ + SNAME##_node *PFX##_new_node(V element) \ + { \ + SNAME##_node *_node_ = malloc(sizeof(SNAME##_node)); \ + \ + if (!_node_) \ + return NULL; \ + \ + _node_->data = element; \ + _node_->next = NULL; \ + _node_->prev = NULL; \ + \ + return _node_; \ + } \ + \ + void PFX##_free_node(SNAME##_node *_node_) \ + { \ + free(_node_); \ + } \ + \ + SNAME##_node *PFX##_head(SNAME *_list_) \ + { \ + return _list_->head; \ + } \ + \ + SNAME##_node *PFX##_get_node(SNAME *_list_, size_t index) \ + { \ + if (index >= _list_->count) \ + return NULL; \ + \ + if (PFX##_empty(_list_)) \ + return NULL; \ + \ + SNAME##_node *_node_ = NULL; \ + \ + if (index <= _list_->count / 2) \ + { \ + _node_ = _list_->head; \ + for (size_t i = 0; i < index; i++) \ + { \ + _node_ = _node_->next; \ + } \ + } \ + else \ + { \ + _node_ = _list_->tail; \ + for (size_t i = _list_->count - 1; i > index; i--) \ + { \ + _node_ = _node_->prev; \ + } \ + } \ + \ + return _node_; \ + } \ + \ + SNAME##_node *PFX##_tail(SNAME *_list_) \ + { \ + return _list_->tail; \ + } \ + \ + bool PFX##_insert_after(SNAME *_owner_, SNAME##_node *_node_, V element) \ + { \ + SNAME##_node *new_node = PFX##_new_node(element); \ + \ + if (!new_node) \ + return false; \ + \ + new_node->next = _node_->next; \ + \ + if (_node_->next != NULL) \ + _node_->next->prev = new_node; \ + else \ + _owner_->tail = new_node; \ + \ + new_node->prev = _node_; \ + _node_->next = new_node; \ + \ + _owner_->count++; \ + \ + return true; \ + } \ + \ + bool PFX##_insert_before(SNAME *_owner_, SNAME##_node *_node_, V element) \ + { \ + SNAME##_node *new_node = PFX##_new_node(element); \ + \ + if (!new_node) \ + return false; \ + \ + new_node->prev = _node_->prev; \ + \ + if (_node_->prev != NULL) \ + _node_->prev->next = new_node; \ + else \ + _owner_->head = new_node; \ + \ + new_node->next = _node_; \ + _node_->prev = new_node; \ + \ + _owner_->count++; \ + \ + return true; \ + } \ + \ + bool PFX##_remove_after(SNAME *_owner_, SNAME##_node *_node_) \ + { \ + if (_node_->next == NULL) \ + return false; \ + \ + SNAME##_node *tmp = _node_->next; \ + \ + if (tmp->next != NULL) \ + { \ + _node_->next = _node_->next->next; \ + _node_->next->prev = _node_; \ + } \ + else \ + _owner_->tail = _node_; \ + \ + free(tmp); \ + \ + _owner_->count--; \ + \ + return true; \ + } \ + \ + bool PFX##_remove_current(SNAME *_owner_, SNAME##_node *_node_) \ + { \ + if (_node_->prev != NULL) \ + _node_->prev->next = _node_->next; \ + else \ + _owner_->head = _node_->next; \ + \ + if (_node_->next != NULL) \ + _node_->next->prev = _node_->prev; \ + else \ + _owner_->tail = _node_->prev; \ + \ + free(_node_); \ + \ + _owner_->count--; \ + \ + return true; \ + } \ + \ + bool PFX##_remove_before(SNAME *_owner_, SNAME##_node *_node_) \ + { \ + if (_node_->prev == NULL) \ + return false; \ + \ + SNAME##_node *tmp = _node_->prev; \ + \ + if (tmp->prev != NULL) \ + { \ + _node_->prev = _node_->prev->prev; \ + _node_->prev->next = _node_; \ + } \ + else \ + _owner_->head = _node_; \ + \ + free(tmp); \ + \ + _owner_->count--; \ + \ + return true; \ + } \ + \ + SNAME##_node *PFX##_next_node(SNAME##_node *_node_) \ + { \ + return _node_->next; \ + } \ + \ + SNAME##_node *PFX##_prev_node(SNAME##_node *_node_) \ + { \ + return _node_->prev; \ + } \ + \ + SNAME##_iter *PFX##_iter_new(SNAME *target) \ + { \ + SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + void PFX##_iter_free(SNAME##_iter *iter) \ + { \ + free(iter); \ + } \ + \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + { \ + iter->target = target; \ + iter->cursor = target->head; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + } \ + \ + bool PFX##_iter_start(SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + bool PFX##_iter_end(SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + void PFX##_iter_to_start(SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->target->head; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ + } \ + \ + void PFX##_iter_to_end(SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->target->tail; \ + iter->index = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + } \ + } \ + \ + bool PFX##_iter_next(SNAME##_iter *iter) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->cursor->next == NULL) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + iter->cursor = iter->cursor->next; \ + iter->index++; \ + \ + return true; \ + } \ + \ + bool PFX##_iter_prev(SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor->prev == NULL) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->cursor = iter->cursor->prev; \ + iter->index--; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->cursor->next == NULL) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ + return false; \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + iter->index += steps; \ + \ + for (size_t i = 0; i < steps; i++) \ + iter->cursor = iter->cursor->next; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor->prev == NULL) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index < steps) \ + return false; \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->index -= steps; \ + \ + for (size_t i = 0; i < steps; i++) \ + iter->cursor = iter->cursor->prev; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator was able to be positioned at the given */ \ + /* index */ \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + { \ + if (index >= PFX##_count(iter->target)) \ + return false; \ + \ + if (iter->index > index) \ + return PFX##_iter_rewind(iter, iter->index - index); \ + else if (iter->index < index) \ + return PFX##_iter_advance(iter, index - iter->index); \ + \ + return true; \ + } \ + \ + V PFX##_iter_value(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return PFX##_impl_default_value(); \ + \ + return iter->cursor->data; \ + } \ + \ + V *PFX##_iter_rvalue(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return NULL; \ + \ + return &(iter->cursor->data); \ + } \ + \ + size_t PFX##_iter_index(SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + SNAME##_node *PFX##_iter_node(SNAME##_iter *iter) \ + { \ + return iter->cursor; \ + } \ + \ + static SNAME##_iter PFX##_impl_it_start(SNAME *_list_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _list_); \ + PFX##_iter_to_start(&iter); \ + \ + return iter; \ + } \ + \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_list_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _list_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_LINKEDLIST_H */ diff --git a/src/cmc/list.h b/src/cmc/list.h index 2d5ba5b..a976f19 100644 --- a/src/cmc/list.h +++ b/src/cmc/list.h @@ -49,137 +49,137 @@ #include #include "../utl/cmc_string.h" -#define LIST_GENERATE(PFX, SNAME, FMOD, V) \ - LIST_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - LIST_GENERATE_SOURCE(PFX, SNAME, FMOD, V) +#define CMC_GENERATE_LIST(PFX, SNAME, V) \ + CMC_GENERATE_LIST_HEADER(PFX, SNAME, V) \ + CMC_GENERATE_LIST_SOURCE(PFX, SNAME, V) -#define LIST_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \ - LIST_GENERATE_HEADER(PFX, SNAME, FMOD, V) +#define CMC_WRAPGEN_LIST_HEADER(PFX, SNAME, K, V) \ + CMC_GENERATE_LIST_HEADER(PFX, SNAME, V) -#define LIST_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \ - LIST_GENERATE_SOURCE(PFX, SNAME, FMOD, V) +#define CMC_WRAPGEN_LIST_SOURCE(PFX, SNAME, K, V) \ + CMC_GENERATE_LIST_SOURCE(PFX, SNAME, V) /* HEADER ********************************************************************/ -#define LIST_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - \ - /* List Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Dynamic array of elements */ \ - V *buffer; \ - \ - /* Current array capacity */ \ - size_t capacity; \ - \ - /* Current amount of elements */ \ - size_t count; \ - \ - /* Function that returns an iterator to the start of the list */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the list */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* List Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target list */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - FMOD SNAME *PFX##_new(size_t capacity); \ - FMOD SNAME *PFX##_new_from(V *elements, size_t size); \ - FMOD void PFX##_clear(SNAME *_list_, void (*deallocator)(V)); \ - FMOD void PFX##_free(SNAME *_list_, void (*deallocator)(V)); \ - /* Collection Input and Output */ \ - FMOD bool PFX##_push_front(SNAME *_list_, V element); \ - FMOD bool PFX##_push(SNAME *_list_, V element, size_t index); \ - FMOD bool PFX##_push_back(SNAME *_list_, V element); \ - FMOD bool PFX##_pop_front(SNAME *_list_); \ - FMOD bool PFX##_pop(SNAME *_list_, size_t index); \ - FMOD bool PFX##_pop_back(SNAME *_list_); \ - /* Conditional Input and Output */ \ - FMOD bool PFX##_push_if(SNAME *_list_, V element, size_t index, bool condition); \ - FMOD bool PFX##_pop_if(SNAME *_list_, size_t index, bool condition); \ - /* Collection Range Input and Output */ \ - FMOD bool PFX##_prepend(SNAME *_list_, V *elements, size_t size); \ - FMOD bool PFX##_insert(SNAME *_list_, V *elements, size_t size, size_t index); \ - FMOD bool PFX##_append(SNAME *_list_, V *elements, size_t size); \ - FMOD bool PFX##_remove(SNAME *_list_, size_t from, size_t to); \ - FMOD SNAME *PFX##_extract(SNAME *_list_, size_t from, size_t to); \ - /* Element Access */ \ - FMOD V PFX##_front(SNAME *_list_); \ - FMOD V PFX##_get(SNAME *_list_, size_t index); \ - FMOD V *PFX##_get_ref(SNAME *_list_, size_t index); \ - FMOD V PFX##_back(SNAME *_list_); \ - FMOD size_t PFX##_indexof(SNAME *_list_, V element, int (*comparator)(V, V), bool from_start); \ - /* Collection State */ \ - FMOD bool PFX##_contains(SNAME *_list_, V element, int (*comparator)(V, V)); \ - FMOD bool PFX##_empty(SNAME *_list_); \ - FMOD bool PFX##_full(SNAME *_list_); \ - FMOD size_t PFX##_count(SNAME *_list_); \ - FMOD bool PFX##_fits(SNAME *_list_, size_t size); \ - FMOD size_t PFX##_capacity(SNAME *_list_); \ - /* Collection Utility */ \ - FMOD SNAME *PFX##_copy_of(SNAME *_list_, V (*copy_func)(V)); \ - FMOD bool PFX##_equals(SNAME *_list1_, SNAME *_list2_, int (*comparator)(V, V)); \ - FMOD cmc_string PFX##_to_string(SNAME *_list_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ - FMOD void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - FMOD V PFX##_iter_value(SNAME##_iter *iter); \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ - /* Default Value */ \ - static inline V PFX##_impl_default_value(void) \ - { \ - V _empty_value_; \ - \ - memset(&_empty_value_, 0, sizeof(V)); \ - \ - return _empty_value_; \ - } \ - \ +#define CMC_GENERATE_LIST_HEADER(PFX, SNAME, V) \ + \ + /* List Structure */ \ + typedef struct SNAME##_s \ + { \ + /* Dynamic array of elements */ \ + V *buffer; \ + \ + /* Current array capacity */ \ + size_t capacity; \ + \ + /* Current amount of elements */ \ + size_t count; \ + \ + /* Function that returns an iterator to the start of the list */ \ + struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + \ + /* Function that returns an iterator to the end of the list */ \ + struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + \ + } SNAME, *SNAME##_ptr; \ + \ + /* List Iterator */ \ + typedef struct SNAME##_iter_s \ + { \ + /* Target list */ \ + struct SNAME##_s *target; \ + \ + /* Cursor's position (index) */ \ + size_t cursor; \ + \ + /* If the iterator has reached the start of the iteration */ \ + bool start; \ + \ + /* If the iterator has reached the end of the iteration */ \ + bool end; \ + \ + } SNAME##_iter, *SNAME##_iter_ptr; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + SNAME *PFX##_new(size_t capacity); \ + SNAME *PFX##_new_from(V *elements, size_t size); \ + void PFX##_clear(SNAME *_list_, void (*deallocator)(V)); \ + void PFX##_free(SNAME *_list_, void (*deallocator)(V)); \ + /* Collection Input and Output */ \ + bool PFX##_push_front(SNAME *_list_, V element); \ + bool PFX##_push(SNAME *_list_, V element, size_t index); \ + bool PFX##_push_back(SNAME *_list_, V element); \ + bool PFX##_pop_front(SNAME *_list_); \ + bool PFX##_pop(SNAME *_list_, size_t index); \ + bool PFX##_pop_back(SNAME *_list_); \ + /* Conditional Input and Output */ \ + bool PFX##_push_if(SNAME *_list_, V element, size_t index, bool condition); \ + bool PFX##_pop_if(SNAME *_list_, size_t index, bool condition); \ + /* Collection Range Input and Output */ \ + bool PFX##_prepend(SNAME *_list_, V *elements, size_t size); \ + bool PFX##_insert(SNAME *_list_, V *elements, size_t size, size_t index); \ + bool PFX##_append(SNAME *_list_, V *elements, size_t size); \ + bool PFX##_remove(SNAME *_list_, size_t from, size_t to); \ + SNAME *PFX##_extract(SNAME *_list_, size_t from, size_t to); \ + /* Element Access */ \ + V PFX##_front(SNAME *_list_); \ + V PFX##_get(SNAME *_list_, size_t index); \ + V *PFX##_get_ref(SNAME *_list_, size_t index); \ + V PFX##_back(SNAME *_list_); \ + size_t PFX##_indexof(SNAME *_list_, V element, int (*comparator)(V, V), bool from_start); \ + /* Collection State */ \ + bool PFX##_contains(SNAME *_list_, V element, int (*comparator)(V, V)); \ + bool PFX##_empty(SNAME *_list_); \ + bool PFX##_full(SNAME *_list_); \ + size_t PFX##_count(SNAME *_list_); \ + bool PFX##_fits(SNAME *_list_, size_t size); \ + size_t PFX##_capacity(SNAME *_list_); \ + /* Collection Utility */ \ + SNAME *PFX##_copy_of(SNAME *_list_, V (*copy_func)(V)); \ + bool PFX##_equals(SNAME *_list1_, SNAME *_list2_, int (*comparator)(V, V)); \ + cmc_string PFX##_to_string(SNAME *_list_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + SNAME##_iter *PFX##_iter_new(SNAME *target); \ + void PFX##_iter_free(SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(SNAME##_iter *iter); \ + bool PFX##_iter_end(SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(SNAME##_iter *iter); \ + void PFX##_iter_to_end(SNAME##_iter *iter); \ + bool PFX##_iter_next(SNAME##_iter *iter); \ + bool PFX##_iter_prev(SNAME##_iter *iter); \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + V PFX##_iter_value(SNAME##_iter *iter); \ + V *PFX##_iter_rvalue(SNAME##_iter *iter); \ + size_t PFX##_iter_index(SNAME##_iter *iter); \ + \ + /* Default Value */ \ + static inline V PFX##_impl_default_value(void) \ + { \ + V _empty_value_; \ + \ + memset(&_empty_value_, 0, sizeof(V)); \ + \ + return _empty_value_; \ + } \ + \ /* SOURCE ********************************************************************/ -#define LIST_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ +#define CMC_GENERATE_LIST_SOURCE(PFX, SNAME, V) \ \ /* Implementation Detail Functions */ \ static bool PFX##_impl_grow(SNAME *_list_, size_t required); \ static SNAME##_iter PFX##_impl_it_start(SNAME *_list_); \ static SNAME##_iter PFX##_impl_it_end(SNAME *_list_); \ \ - FMOD SNAME *PFX##_new(size_t capacity) \ + SNAME *PFX##_new(size_t capacity) \ { \ if (capacity < 1) \ return NULL; \ @@ -208,7 +208,7 @@ return _list_; \ } \ \ - FMOD SNAME *PFX##_new_from(V *elements, size_t size) \ + SNAME *PFX##_new_from(V *elements, size_t size) \ { \ if (size == 0) \ return NULL; \ @@ -225,7 +225,7 @@ return _list_; \ } \ \ - FMOD void PFX##_clear(SNAME *_list_, void (*deallocator)(V)) \ + void PFX##_clear(SNAME *_list_, void (*deallocator)(V)) \ { \ if (deallocator) \ { \ @@ -238,7 +238,7 @@ _list_->count = 0; \ } \ \ - FMOD void PFX##_free(SNAME *_list_, void (*deallocator)(V)) \ + void PFX##_free(SNAME *_list_, void (*deallocator)(V)) \ { \ if (deallocator) \ { \ @@ -250,7 +250,7 @@ free(_list_); \ } \ \ - FMOD bool PFX##_push_front(SNAME *_list_, V element) \ + bool PFX##_push_front(SNAME *_list_, V element) \ { \ if (PFX##_full(_list_)) \ { \ @@ -270,7 +270,7 @@ return true; \ } \ \ - FMOD bool PFX##_push(SNAME *_list_, V element, size_t index) \ + bool PFX##_push(SNAME *_list_, V element, size_t index) \ { \ if (index > _list_->count) \ return false; \ @@ -299,7 +299,7 @@ return true; \ } \ \ - FMOD bool PFX##_push_back(SNAME *_list_, V element) \ + bool PFX##_push_back(SNAME *_list_, V element) \ { \ if (PFX##_full(_list_)) \ { \ @@ -312,7 +312,7 @@ return true; \ } \ \ - FMOD bool PFX##_pop_front(SNAME *_list_) \ + bool PFX##_pop_front(SNAME *_list_) \ { \ if (PFX##_empty(_list_)) \ return false; \ @@ -324,7 +324,7 @@ return true; \ } \ \ - FMOD bool PFX##_pop(SNAME *_list_, size_t index) \ + bool PFX##_pop(SNAME *_list_, size_t index) \ { \ if (PFX##_empty(_list_)) \ return false; \ @@ -348,7 +348,7 @@ return true; \ } \ \ - FMOD bool PFX##_pop_back(SNAME *_list_) \ + bool PFX##_pop_back(SNAME *_list_) \ { \ if (PFX##_empty(_list_)) \ return false; \ @@ -358,7 +358,7 @@ return true; \ } \ \ - FMOD bool PFX##_push_if(SNAME *_list_, V element, size_t index, bool condition) \ + bool PFX##_push_if(SNAME *_list_, V element, size_t index, bool condition) \ { \ if (condition) \ return PFX##_push(_list_, element, index); \ @@ -366,7 +366,7 @@ return false; \ } \ \ - FMOD bool PFX##_pop_if(SNAME *_list_, size_t index, bool condition) \ + bool PFX##_pop_if(SNAME *_list_, size_t index, bool condition) \ { \ if (condition) \ return PFX##_pop(_list_, index); \ @@ -374,7 +374,7 @@ return false; \ } \ \ - FMOD bool PFX##_prepend(SNAME *_list_, V *elements, size_t size) \ + bool PFX##_prepend(SNAME *_list_, V *elements, size_t size) \ { \ if (size == 0) \ return false; \ @@ -394,7 +394,7 @@ return true; \ } \ \ - FMOD bool PFX##_insert(SNAME *_list_, V *elements, size_t size, size_t index) \ + bool PFX##_insert(SNAME *_list_, V *elements, size_t size, size_t index) \ { \ if (size == 0 || index > _list_->count) \ return false; \ @@ -421,7 +421,7 @@ return true; \ } \ \ - FMOD bool PFX##_append(SNAME *_list_, V *elements, size_t size) \ + bool PFX##_append(SNAME *_list_, V *elements, size_t size) \ { \ if (size == 0) \ return false; \ @@ -439,7 +439,7 @@ return true; \ } \ \ - FMOD bool PFX##_remove(SNAME *_list_, size_t from, size_t to) \ + bool PFX##_remove(SNAME *_list_, size_t from, size_t to) \ { \ if (from > to || to >= _list_->count) \ return false; \ @@ -455,7 +455,7 @@ return true; \ } \ \ - FMOD SNAME *PFX##_extract(SNAME *_list_, size_t from, size_t to) \ + SNAME *PFX##_extract(SNAME *_list_, size_t from, size_t to) \ { \ if (from > to || to >= _list_->count) \ return false; \ @@ -476,7 +476,7 @@ return result; \ } \ \ - FMOD V PFX##_front(SNAME *_list_) \ + V PFX##_front(SNAME *_list_) \ { \ if (PFX##_empty(_list_)) \ return PFX##_impl_default_value(); \ @@ -484,7 +484,7 @@ return _list_->buffer[0]; \ } \ \ - FMOD V PFX##_get(SNAME *_list_, size_t index) \ + V PFX##_get(SNAME *_list_, size_t index) \ { \ if (index >= _list_->count || PFX##_empty(_list_)) \ return PFX##_impl_default_value(); \ @@ -492,7 +492,7 @@ return _list_->buffer[index]; \ } \ \ - FMOD V *PFX##_get_ref(SNAME *_list_, size_t index) \ + V *PFX##_get_ref(SNAME *_list_, size_t index) \ { \ if (index >= _list_->count) \ return NULL; \ @@ -503,7 +503,7 @@ return &(_list_->buffer[index]); \ } \ \ - FMOD V PFX##_back(SNAME *_list_) \ + V PFX##_back(SNAME *_list_) \ { \ if (PFX##_empty(_list_)) \ return PFX##_impl_default_value(); \ @@ -511,7 +511,7 @@ return _list_->buffer[_list_->count - 1]; \ } \ \ - FMOD size_t PFX##_indexof(SNAME *_list_, V element, int (*comparator)(V, V), bool from_start) \ + size_t PFX##_indexof(SNAME *_list_, V element, int (*comparator)(V, V), bool from_start) \ { \ if (from_start) \ { \ @@ -533,7 +533,7 @@ return _list_->count; \ } \ \ - FMOD bool PFX##_contains(SNAME *_list_, V element, int (*comparator)(V, V)) \ + bool PFX##_contains(SNAME *_list_, V element, int (*comparator)(V, V)) \ { \ for (size_t i = 0; i < _list_->count; i++) \ { \ @@ -544,32 +544,32 @@ return false; \ } \ \ - FMOD bool PFX##_empty(SNAME *_list_) \ + bool PFX##_empty(SNAME *_list_) \ { \ return _list_->count == 0; \ } \ \ - FMOD bool PFX##_full(SNAME *_list_) \ + bool PFX##_full(SNAME *_list_) \ { \ return _list_->count >= _list_->capacity; \ } \ \ - FMOD size_t PFX##_count(SNAME *_list_) \ + size_t PFX##_count(SNAME *_list_) \ { \ return _list_->count; \ } \ \ - FMOD bool PFX##_fits(SNAME *_list_, size_t size) \ + bool PFX##_fits(SNAME *_list_, size_t size) \ { \ return _list_->count + size <= _list_->capacity; \ } \ \ - FMOD size_t PFX##_capacity(SNAME *_list_) \ + size_t PFX##_capacity(SNAME *_list_) \ { \ return _list_->capacity; \ } \ \ - FMOD SNAME *PFX##_copy_of(SNAME *_list_, V (*copy_func)(V)) \ + SNAME *PFX##_copy_of(SNAME *_list_, V (*copy_func)(V)) \ { \ SNAME *result = PFX##_new(_list_->capacity); \ \ @@ -589,7 +589,7 @@ return result; \ } \ \ - FMOD bool PFX##_equals(SNAME *_list1_, SNAME *_list2_, int (*comparator)(V, V)) \ + bool PFX##_equals(SNAME *_list1_, SNAME *_list2_, int (*comparator)(V, V)) \ { \ if (PFX##_count(_list1_) != PFX##_count(_list2_)) \ return false; \ @@ -603,7 +603,7 @@ return false; \ } \ \ - FMOD cmc_string PFX##_to_string(SNAME *_list_) \ + cmc_string PFX##_to_string(SNAME *_list_) \ { \ cmc_string str; \ SNAME *l_ = _list_; \ @@ -615,7 +615,7 @@ return str; \ } \ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ + SNAME##_iter *PFX##_iter_new(SNAME *target) \ { \ SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ \ @@ -627,12 +627,12 @@ return iter; \ } \ \ - FMOD void PFX##_iter_free(SNAME##_iter *iter) \ + void PFX##_iter_free(SNAME##_iter *iter) \ { \ free(iter); \ } \ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ { \ iter->target = target; \ iter->cursor = 0; \ @@ -640,17 +640,17 @@ iter->end = PFX##_empty(target); \ } \ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ + bool PFX##_iter_start(SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->start; \ } \ \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ + bool PFX##_iter_end(SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->end; \ } \ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ + void PFX##_iter_to_start(SNAME##_iter *iter) \ { \ if (!PFX##_empty(iter->target)) \ { \ @@ -660,7 +660,7 @@ } \ } \ \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ + void PFX##_iter_to_end(SNAME##_iter *iter) \ { \ if (!PFX##_empty(iter->target)) \ { \ @@ -670,7 +670,7 @@ } \ } \ \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ + bool PFX##_iter_next(SNAME##_iter *iter) \ { \ if (iter->end) \ return false; \ @@ -688,7 +688,7 @@ return true; \ } \ \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ + bool PFX##_iter_prev(SNAME##_iter *iter) \ { \ if (iter->start) \ return false; \ @@ -707,7 +707,7 @@ } \ \ /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ { \ if (iter->end) \ return false; \ @@ -729,7 +729,7 @@ } \ \ /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ { \ if (iter->start) \ return false; \ @@ -751,7 +751,7 @@ } \ \ /* Returns true only if the iterator was able to be positioned at the given index */ \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ { \ if (index >= PFX##_count(iter->target)) \ return false; \ @@ -764,7 +764,7 @@ return true; \ } \ \ - FMOD V PFX##_iter_value(SNAME##_iter *iter) \ + V PFX##_iter_value(SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ return PFX##_impl_default_value(); \ @@ -772,7 +772,7 @@ return iter->target->buffer[iter->cursor]; \ } \ \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \ + V *PFX##_iter_rvalue(SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ return NULL; \ @@ -780,7 +780,7 @@ return &(iter->target->buffer[iter->cursor]); \ } \ \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ + size_t PFX##_iter_index(SNAME##_iter *iter) \ { \ return iter->cursor; \ } \ diff --git a/src/cmc/queue.h b/src/cmc/queue.h index 079eb85..65a9c57 100644 --- a/src/cmc/queue.h +++ b/src/cmc/queue.h @@ -49,130 +49,130 @@ #include #include "../utl/cmc_string.h" -#define QUEUE_GENERATE(PFX, SNAME, FMOD, V) \ - QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) +#define CMC_GENERATE_QUEUE(PFX, SNAME, V) \ + CMC_GENERATE_QUEUE_HEADER(PFX, SNAME, V) \ + CMC_GENERATE_QUEUE_SOURCE(PFX, SNAME, V) -#define QUEUE_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \ - QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) +#define CMC_WRAPGEN_QUEUE_HEADER(PFX, SNAME, K, V) \ + CMC_GENERATE_QUEUE_HEADER(PFX, SNAME, V) -#define QUEUE_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \ - QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) +#define CMC_WRAPGEN_QUEUE_SOURCE(PFX, SNAME, K, V) \ + CMC_GENERATE_QUEUE_SOURCE(PFX, SNAME, V) /* HEADER ********************************************************************/ -#define QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - \ - /* Queue Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Dynamic circular array of elements */ \ - V *buffer; \ - \ - /* Current circular array capacity */ \ - size_t capacity; \ - \ - /* Current amount of elements */ \ - size_t count; \ - \ - /* Index representing the front of the queue */ \ - size_t front; \ - \ - /* Index representing the back of the queue */ \ - size_t back; \ - \ - /* Function that returns an iterator to the start of the queue */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the queue */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Queue Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target queue */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - FMOD SNAME *PFX##_new(size_t capacity); \ - FMOD void PFX##_clear(SNAME *_queue_, void (*deallocator)(V)); \ - FMOD void PFX##_free(SNAME *_queue_, void (*deallocator)(V)); \ - /* Collection Input and Output */ \ - FMOD bool PFX##_enqueue(SNAME *_queue_, V element); \ - FMOD bool PFX##_dequeue(SNAME *_queue_); \ - /* Conditional Input and Output */ \ - FMOD bool PFX##_enqueue_if(SNAME *_queue_, V element, bool condition); \ - FMOD bool PFX##_dequeue_if(SNAME *_queue_, bool condition); \ - /* Element Access */ \ - FMOD V PFX##_peek(SNAME *_queue_); \ - /* Collection State */ \ - FMOD bool PFX##_contains(SNAME *_queue_, V element, int (*comparator)(V, V)); \ - FMOD bool PFX##_empty(SNAME *_queue_); \ - FMOD bool PFX##_full(SNAME *_queue_); \ - FMOD size_t PFX##_count(SNAME *_queue_); \ - FMOD size_t PFX##_capacity(SNAME *_queue_); \ - /* Collection Utility */ \ - FMOD SNAME *PFX##_copy_of(SNAME *_queue_, V (*copy_func)(V)); \ - FMOD bool PFX##_equals(SNAME *_queue1_, SNAME *_queue2_, int (*comparator)(V, V)); \ - FMOD cmc_string PFX##_to_string(SNAME *_queue_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ - FMOD void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - FMOD V PFX##_iter_value(SNAME##_iter *iter); \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ - /* Default Value */ \ - static inline V PFX##_impl_default_value(void) \ - { \ - V _empty_value_; \ - \ - memset(&_empty_value_, 0, sizeof(V)); \ - \ - return _empty_value_; \ - } \ - \ +#define CMC_GENERATE_QUEUE_HEADER(PFX, SNAME, V) \ + \ + /* Queue Structure */ \ + typedef struct SNAME##_s \ + { \ + /* Dynamic circular array of elements */ \ + V *buffer; \ + \ + /* Current circular array capacity */ \ + size_t capacity; \ + \ + /* Current amount of elements */ \ + size_t count; \ + \ + /* Index representing the front of the queue */ \ + size_t front; \ + \ + /* Index representing the back of the queue */ \ + size_t back; \ + \ + /* Function that returns an iterator to the start of the queue */ \ + struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + \ + /* Function that returns an iterator to the end of the queue */ \ + struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + \ + } SNAME, *SNAME##_ptr; \ + \ + /* Queue Iterator */ \ + typedef struct SNAME##_iter_s \ + { \ + /* Target queue */ \ + struct SNAME##_s *target; \ + \ + /* Cursor's position (index) */ \ + size_t cursor; \ + \ + /* Keeps track of relative index to the iteration of elements */ \ + size_t index; \ + \ + /* If the iterator has reached the start of the iteration */ \ + bool start; \ + \ + /* If the iterator has reached the end of the iteration */ \ + bool end; \ + \ + } SNAME##_iter, *SNAME##_iter_ptr; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + SNAME *PFX##_new(size_t capacity); \ + void PFX##_clear(SNAME *_queue_, void (*deallocator)(V)); \ + void PFX##_free(SNAME *_queue_, void (*deallocator)(V)); \ + /* Collection Input and Output */ \ + bool PFX##_enqueue(SNAME *_queue_, V element); \ + bool PFX##_dequeue(SNAME *_queue_); \ + /* Conditional Input and Output */ \ + bool PFX##_enqueue_if(SNAME *_queue_, V element, bool condition); \ + bool PFX##_dequeue_if(SNAME *_queue_, bool condition); \ + /* Element Access */ \ + V PFX##_peek(SNAME *_queue_); \ + /* Collection State */ \ + bool PFX##_contains(SNAME *_queue_, V element, int (*comparator)(V, V)); \ + bool PFX##_empty(SNAME *_queue_); \ + bool PFX##_full(SNAME *_queue_); \ + size_t PFX##_count(SNAME *_queue_); \ + size_t PFX##_capacity(SNAME *_queue_); \ + /* Collection Utility */ \ + SNAME *PFX##_copy_of(SNAME *_queue_, V (*copy_func)(V)); \ + bool PFX##_equals(SNAME *_queue1_, SNAME *_queue2_, int (*comparator)(V, V)); \ + cmc_string PFX##_to_string(SNAME *_queue_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + SNAME##_iter *PFX##_iter_new(SNAME *target); \ + void PFX##_iter_free(SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(SNAME##_iter *iter); \ + bool PFX##_iter_end(SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(SNAME##_iter *iter); \ + void PFX##_iter_to_end(SNAME##_iter *iter); \ + bool PFX##_iter_next(SNAME##_iter *iter); \ + bool PFX##_iter_prev(SNAME##_iter *iter); \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + V PFX##_iter_value(SNAME##_iter *iter); \ + V *PFX##_iter_rvalue(SNAME##_iter *iter); \ + size_t PFX##_iter_index(SNAME##_iter *iter); \ + \ + /* Default Value */ \ + static inline V PFX##_impl_default_value(void) \ + { \ + V _empty_value_; \ + \ + memset(&_empty_value_, 0, sizeof(V)); \ + \ + return _empty_value_; \ + } \ + \ /* SOURCE ********************************************************************/ -#define QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ +#define CMC_GENERATE_QUEUE_SOURCE(PFX, SNAME, V) \ \ /* Implementation Detail Functions */ \ static bool PFX##_impl_grow(SNAME *_queue_); \ static SNAME##_iter PFX##_impl_it_start(SNAME *_queue_); \ static SNAME##_iter PFX##_impl_it_end(SNAME *_queue_); \ \ - FMOD SNAME *PFX##_new(size_t capacity) \ + SNAME *PFX##_new(size_t capacity) \ { \ if (capacity < 1) \ return NULL; \ @@ -203,7 +203,7 @@ return _queue_; \ } \ \ - FMOD void PFX##_clear(SNAME *_queue_, void (*deallocator)(V)) \ + void PFX##_clear(SNAME *_queue_, void (*deallocator)(V)) \ { \ if (deallocator) \ { \ @@ -220,7 +220,7 @@ _queue_->back = 0; \ } \ \ - FMOD void PFX##_free(SNAME *_queue_, void (*deallocator)(V)) \ + void PFX##_free(SNAME *_queue_, void (*deallocator)(V)) \ { \ if (deallocator) \ { \ @@ -234,7 +234,7 @@ free(_queue_); \ } \ \ - FMOD bool PFX##_enqueue(SNAME *_queue_, V element) \ + bool PFX##_enqueue(SNAME *_queue_, V element) \ { \ if (PFX##_full(_queue_)) \ { \ @@ -250,7 +250,7 @@ return true; \ } \ \ - FMOD bool PFX##_dequeue(SNAME *_queue_) \ + bool PFX##_dequeue(SNAME *_queue_) \ { \ if (PFX##_empty(_queue_)) \ return false; \ @@ -263,7 +263,7 @@ return true; \ } \ \ - FMOD bool PFX##_enqueue_if(SNAME *_queue_, V element, bool condition) \ + bool PFX##_enqueue_if(SNAME *_queue_, V element, bool condition) \ { \ if (condition) \ return PFX##_enqueue(_queue_, element); \ @@ -271,7 +271,7 @@ return false; \ } \ \ - FMOD bool PFX##_dequeue_if(SNAME *_queue_, bool condition) \ + bool PFX##_dequeue_if(SNAME *_queue_, bool condition) \ { \ if (condition) \ return PFX##_dequeue(_queue_); \ @@ -279,7 +279,7 @@ return false; \ } \ \ - FMOD V PFX##_peek(SNAME *_queue_) \ + V PFX##_peek(SNAME *_queue_) \ { \ if (PFX##_empty(_queue_)) \ return PFX##_impl_default_value(); \ @@ -287,7 +287,7 @@ return _queue_->buffer[_queue_->front]; \ } \ \ - FMOD bool PFX##_contains(SNAME *_queue_, V element, int (*comparator)(V, V)) \ + bool PFX##_contains(SNAME *_queue_, V element, int (*comparator)(V, V)) \ { \ for (size_t i = _queue_->front, j = 0; j < _queue_->count; i = (i + 1) % _queue_->count, j++) \ { \ @@ -298,27 +298,27 @@ return false; \ } \ \ - FMOD bool PFX##_empty(SNAME *_queue_) \ + bool PFX##_empty(SNAME *_queue_) \ { \ return _queue_->count == 0; \ } \ \ - FMOD bool PFX##_full(SNAME *_queue_) \ + bool PFX##_full(SNAME *_queue_) \ { \ return _queue_->count >= _queue_->capacity; \ } \ \ - FMOD size_t PFX##_count(SNAME *_queue_) \ + size_t PFX##_count(SNAME *_queue_) \ { \ return _queue_->count; \ } \ \ - FMOD size_t PFX##_capacity(SNAME *_queue_) \ + size_t PFX##_capacity(SNAME *_queue_) \ { \ return _queue_->capacity; \ } \ \ - FMOD SNAME *PFX##_copy_of(SNAME *_queue_, V (*copy_func)(V)) \ + SNAME *PFX##_copy_of(SNAME *_queue_, V (*copy_func)(V)) \ { \ SNAME *result = PFX##_new(_queue_->capacity); \ \ @@ -345,7 +345,7 @@ return result; \ } \ \ - FMOD bool PFX##_equals(SNAME *_queue1_, SNAME *_queue2_, int (*comparator)(V, V)) \ + bool PFX##_equals(SNAME *_queue1_, SNAME *_queue2_, int (*comparator)(V, V)) \ { \ if (PFX##_count(_queue1_) != PFX##_count(_queue2_)) \ return false; \ @@ -363,7 +363,7 @@ return true; \ } \ \ - FMOD cmc_string PFX##_to_string(SNAME *_queue_) \ + cmc_string PFX##_to_string(SNAME *_queue_) \ { \ cmc_string str; \ SNAME *q_ = _queue_; \ @@ -375,7 +375,7 @@ return str; \ } \ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ + SNAME##_iter *PFX##_iter_new(SNAME *target) \ { \ SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ \ @@ -387,12 +387,12 @@ return iter; \ } \ \ - FMOD void PFX##_iter_free(SNAME##_iter *iter) \ + void PFX##_iter_free(SNAME##_iter *iter) \ { \ free(iter); \ } \ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ { \ iter->target = target; \ iter->cursor = target->front; \ @@ -401,17 +401,17 @@ iter->end = PFX##_empty(target); \ } \ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ + bool PFX##_iter_start(SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->start; \ } \ \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ + bool PFX##_iter_end(SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->end; \ } \ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ + void PFX##_iter_to_start(SNAME##_iter *iter) \ { \ iter->cursor = iter->target->front; \ iter->index = 0; \ @@ -419,7 +419,7 @@ iter->end = PFX##_empty(iter->target); \ } \ \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ + void PFX##_iter_to_end(SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ iter->cursor = 0; \ @@ -431,7 +431,7 @@ iter->end = true; \ } \ \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ + bool PFX##_iter_next(SNAME##_iter *iter) \ { \ if (iter->end) \ return false; \ @@ -450,7 +450,7 @@ return true; \ } \ \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ + bool PFX##_iter_prev(SNAME##_iter *iter) \ { \ if (iter->start) \ return false; \ @@ -470,7 +470,7 @@ } \ \ /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ { \ if (iter->end) \ return false; \ @@ -493,7 +493,7 @@ } \ \ /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ { \ if (iter->start) \ return false; \ @@ -521,7 +521,7 @@ } \ \ /* Returns true only if the iterator was able to be positioned at the given index */ \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ { \ if (index >= PFX##_count(iter->target)) \ return false; \ @@ -534,7 +534,7 @@ return true; \ } \ \ - FMOD V PFX##_iter_value(SNAME##_iter *iter) \ + V PFX##_iter_value(SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ return PFX##_impl_default_value(); \ @@ -542,7 +542,7 @@ return iter->target->buffer[iter->cursor]; \ } \ \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \ + V *PFX##_iter_rvalue(SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ return NULL; \ @@ -550,7 +550,7 @@ return &(iter->target->buffer[iter->cursor]); \ } \ \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ + size_t PFX##_iter_index(SNAME##_iter *iter) \ { \ return iter->index; \ } \ diff --git a/src/cmc/stack.h b/src/cmc/stack.h index 4b3290a..11c3862 100644 --- a/src/cmc/stack.h +++ b/src/cmc/stack.h @@ -34,505 +34,505 @@ #include #include "../utl/cmc_string.h" -#define STACK_GENERATE(PFX, SNAME, FMOD, V) \ - STACK_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, V) +#define CMC_GENERATE_STACK(PFX, SNAME, V) \ + CMC_GENERATE_STACK_HEADER(PFX, SNAME, V) \ + CMC_GENERATE_STACK_SOURCE(PFX, SNAME, V) -#define STACK_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \ - STACK_GENERATE_HEADER(PFX, SNAME, FMOD, V) +#define CMC_WRAPGEN_STACK_HEADER(PFX, SNAME, K, V) \ + CMC_GENERATE_STACK_HEADER(PFX, SNAME, V) -#define STACK_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \ - STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, V) +#define CMC_WRAPGEN_STACK_SOURCE(PFX, SNAME, K, V) \ + CMC_GENERATE_STACK_SOURCE(PFX, SNAME, V) /* HEADER ********************************************************************/ -#define STACK_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - \ - /* Stack Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Dynamic array of elements */ \ - V *buffer; \ - \ - /* Current array capacity */ \ - size_t capacity; \ - \ - /* Current amount of elements */ \ - size_t count; \ - \ - /* Function that returns an iterator to the start of the stack */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the stack */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Stack Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target stack */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - FMOD SNAME *PFX##_new(size_t capacity); \ - FMOD void PFX##_clear(SNAME *_stack_, void (*deallocator)(V)); \ - FMOD void PFX##_free(SNAME *_stack_, void (*deallocator)(V)); \ - /* Collection Input and Output */ \ - FMOD bool PFX##_push(SNAME *_stack_, V element); \ - FMOD bool PFX##_pop(SNAME *_stack_); \ - /* Conditional Input and Output */ \ - FMOD bool PFX##_push_if(SNAME *_stack_, V element, bool condition); \ - FMOD bool PFX##_pop_if(SNAME *_stack_, bool condition); \ - /* Element Access */ \ - FMOD V PFX##_top(SNAME *_stack_); \ - /* Collection State */ \ - FMOD bool PFX##_contains(SNAME *_stack_, V element, int (*comparator)(V, V)); \ - FMOD bool PFX##_empty(SNAME *_stack_); \ - FMOD bool PFX##_full(SNAME *_stack_); \ - FMOD size_t PFX##_count(SNAME *_stack_); \ - FMOD size_t PFX##_capacity(SNAME *_stack_); \ - /* Collection Utility */ \ - FMOD SNAME *PFX##_copy_of(SNAME *_stack_, V (*copy_func)(V)); \ - FMOD bool PFX##_equals(SNAME *_stack1_, SNAME *_stack2_, int (*comparator)(V, V)); \ - FMOD cmc_string PFX##_to_string(SNAME *_stack_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ - FMOD void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - FMOD V PFX##_iter_value(SNAME##_iter *iter); \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ - /* Default Value */ \ - static inline V PFX##_impl_default_value(void) \ - { \ - V _empty_value_; \ - \ - memset(&_empty_value_, 0, sizeof(V)); \ - \ - return _empty_value_; \ - } \ - \ +#define CMC_GENERATE_STACK_HEADER(PFX, SNAME, V) \ + \ + /* Stack Structure */ \ + typedef struct SNAME##_s \ + { \ + /* Dynamic array of elements */ \ + V *buffer; \ + \ + /* Current array capacity */ \ + size_t capacity; \ + \ + /* Current amount of elements */ \ + size_t count; \ + \ + /* Function that returns an iterator to the start of the stack */ \ + struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + \ + /* Function that returns an iterator to the end of the stack */ \ + struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + \ + } SNAME, *SNAME##_ptr; \ + \ + /* Stack Iterator */ \ + typedef struct SNAME##_iter_s \ + { \ + /* Target stack */ \ + struct SNAME##_s *target; \ + \ + /* Cursor's position (index) */ \ + size_t cursor; \ + \ + /* If the iterator has reached the start of the iteration */ \ + bool start; \ + \ + /* If the iterator has reached the end of the iteration */ \ + bool end; \ + \ + } SNAME##_iter, *SNAME##_iter_ptr; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + SNAME *PFX##_new(size_t capacity); \ + void PFX##_clear(SNAME *_stack_, void (*deallocator)(V)); \ + void PFX##_free(SNAME *_stack_, void (*deallocator)(V)); \ + /* Collection Input and Output */ \ + bool PFX##_push(SNAME *_stack_, V element); \ + bool PFX##_pop(SNAME *_stack_); \ + /* Conditional Input and Output */ \ + bool PFX##_push_if(SNAME *_stack_, V element, bool condition); \ + bool PFX##_pop_if(SNAME *_stack_, bool condition); \ + /* Element Access */ \ + V PFX##_top(SNAME *_stack_); \ + /* Collection State */ \ + bool PFX##_contains(SNAME *_stack_, V element, int (*comparator)(V, V)); \ + bool PFX##_empty(SNAME *_stack_); \ + bool PFX##_full(SNAME *_stack_); \ + size_t PFX##_count(SNAME *_stack_); \ + size_t PFX##_capacity(SNAME *_stack_); \ + /* Collection Utility */ \ + SNAME *PFX##_copy_of(SNAME *_stack_, V (*copy_func)(V)); \ + bool PFX##_equals(SNAME *_stack1_, SNAME *_stack2_, int (*comparator)(V, V)); \ + cmc_string PFX##_to_string(SNAME *_stack_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + SNAME##_iter *PFX##_iter_new(SNAME *target); \ + void PFX##_iter_free(SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(SNAME##_iter *iter); \ + bool PFX##_iter_end(SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(SNAME##_iter *iter); \ + void PFX##_iter_to_end(SNAME##_iter *iter); \ + bool PFX##_iter_next(SNAME##_iter *iter); \ + bool PFX##_iter_prev(SNAME##_iter *iter); \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + V PFX##_iter_value(SNAME##_iter *iter); \ + V *PFX##_iter_rvalue(SNAME##_iter *iter); \ + size_t PFX##_iter_index(SNAME##_iter *iter); \ + \ + /* Default Value */ \ + static inline V PFX##_impl_default_value(void) \ + { \ + V _empty_value_; \ + \ + memset(&_empty_value_, 0, sizeof(V)); \ + \ + return _empty_value_; \ + } \ + \ /* SOURCE ********************************************************************/ -#define STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ - \ - /* Implementation Detail Functions */ \ - static bool PFX##_impl_grow(SNAME *_stack_); \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_stack_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_stack_); \ - \ - FMOD SNAME *PFX##_new(size_t capacity) \ - { \ - if (capacity < 1) \ - return NULL; \ - \ - SNAME *_stack_ = malloc(sizeof(SNAME)); \ - \ - if (!_stack_) \ - return NULL; \ - \ - _stack_->buffer = malloc(sizeof(V) * capacity); \ - \ - if (!_stack_->buffer) \ - { \ - free(_stack_); \ - return NULL; \ - } \ - \ - memset(_stack_->buffer, 0, sizeof(V) * capacity); \ - \ - _stack_->capacity = capacity; \ - _stack_->count = 0; \ - \ - _stack_->it_start = PFX##_impl_it_start; \ - _stack_->it_end = PFX##_impl_it_end; \ - \ - return _stack_; \ - } \ - \ - FMOD void PFX##_clear(SNAME *_stack_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _stack_->count; i++) \ - deallocator(_stack_->buffer[i]); \ - } \ - \ - memset(_stack_->buffer, 0, sizeof(V) * _stack_->capacity); \ - \ - _stack_->count = 0; \ - } \ - \ - FMOD void PFX##_free(SNAME *_stack_, void (*deallocator)(V)) \ - { \ - free(_stack_->buffer); \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _stack_->count; i++) \ - deallocator(_stack_->buffer[i]); \ - } \ - \ - free(_stack_); \ - } \ - \ - FMOD bool PFX##_push(SNAME *_stack_, V element) \ - { \ - if (PFX##_full(_stack_)) \ - { \ - if (!PFX##_impl_grow(_stack_)) \ - return false; \ - } \ - \ - _stack_->buffer[_stack_->count++] = element; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_pop(SNAME *_stack_) \ - { \ - if (PFX##_empty(_stack_)) \ - return false; \ - \ - _stack_->buffer[--_stack_->count] = PFX##_impl_default_value(); \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_push_if(SNAME *_stack_, V element, bool condition) \ - { \ - if (condition) \ - return PFX##_push(_stack_, element); \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_pop_if(SNAME *_stack_, bool condition) \ - { \ - if (condition) \ - return PFX##_pop(_stack_); \ - \ - return false; \ - } \ - \ - FMOD V PFX##_top(SNAME *_stack_) \ - { \ - if (PFX##_empty(_stack_)) \ - return PFX##_impl_default_value(); \ - \ - return _stack_->buffer[_stack_->count - 1]; \ - } \ - \ - FMOD bool PFX##_contains(SNAME *_stack_, V element, int (*comparator)(V, V)) \ - { \ - for (size_t i = 0; i < _stack_->count; i++) \ - { \ - if (comparator(_stack_->buffer[i], element) == 0) \ - return true; \ - } \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_empty(SNAME *_stack_) \ - { \ - return _stack_->count == 0; \ - } \ - \ - FMOD bool PFX##_full(SNAME *_stack_) \ - { \ - return _stack_->count >= _stack_->capacity; \ - } \ - \ - FMOD size_t PFX##_count(SNAME *_stack_) \ - { \ - return _stack_->count; \ - } \ - \ - FMOD size_t PFX##_capacity(SNAME *_stack_) \ - { \ - return _stack_->capacity; \ - } \ - \ - FMOD SNAME *PFX##_copy_of(SNAME *_stack_, V (*copy_func)(V)) \ - { \ - SNAME *result = PFX##_new(_stack_->capacity); \ - \ - if (!result) \ - return NULL; \ - \ - 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(V) * _stack_->count); \ - \ - result->count = _stack_->count; \ - \ - return result; \ - } \ - \ - FMOD bool PFX##_equals(SNAME *_stack1_, SNAME *_stack2_, int (*comparator)(V, V)) \ - { \ - if (PFX##_count(_stack1_) != PFX##_count(_stack2_)) \ - return false; \ - \ - for (size_t i = 0; i < PFX##_count(_stack1_); i++) \ - { \ - if (comparator(_stack1_->buffer[i], _stack2_->buffer[i]) != 0) \ - return false; \ - } \ - \ - return true; \ - } \ - \ - FMOD cmc_string PFX##_to_string(SNAME *_stack_) \ - { \ - cmc_string str; \ - SNAME *s_ = _stack_; \ - const char *name = #SNAME; \ - \ - snprintf(str.s, cmc_string_len, cmc_string_fmt_stack, \ - name, s_, s_->buffer, s_->capacity, s_->count); \ - \ - return str; \ - } \ - \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ - { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - FMOD void PFX##_iter_free(SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ - { \ - iter->target = target; \ - iter->cursor = PFX##_empty(target) ? 0 : iter->target->count - 1; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - } \ - \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->target->count - 1; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - } \ - } \ - \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = 0; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - } \ - } \ - \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->cursor == 0) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - iter->cursor--; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->cursor + 1 == PFX##_count(iter->target)) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - iter->cursor++; \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->cursor == 0) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->cursor < steps) \ - return false; \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - iter->cursor -= steps; \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->cursor + 1 == PFX##_count(iter->target)) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->cursor + steps >= PFX##_count(iter->target)) \ - return false; \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - iter->cursor += steps; \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator was able to be positioned at the given */ \ - /* index */ \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ - { \ - if (index >= PFX##_count(iter->target)) \ - return false; \ - \ - if (iter->cursor > index) \ - return PFX##_iter_rewind(iter, iter->cursor - index); \ - else if (iter->cursor < index) \ - return PFX##_iter_advance(iter, index - iter->cursor); \ - \ - return true; \ - } \ - \ - FMOD V PFX##_iter_value(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return PFX##_impl_default_value(); \ - \ - return iter->target->buffer[iter->cursor]; \ - } \ - \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->target->buffer[iter->cursor]); \ - } \ - \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return 0; \ - \ - return iter->target->count - 1 - iter->cursor; \ - } \ - \ - static bool PFX##_impl_grow(SNAME *_stack_) \ - { \ - size_t new_capacity = _stack_->capacity * 2; \ - \ - V *new_buffer = realloc(_stack_->buffer, sizeof(V) * new_capacity); \ - \ - if (!new_buffer) \ - return false; \ - \ - _stack_->buffer = new_buffer; \ - _stack_->capacity = new_capacity; \ - \ - return true; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_stack_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _stack_); \ - PFX##_iter_to_start(&iter); \ - \ - return iter; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_stack_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _stack_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ +#define CMC_GENERATE_STACK_SOURCE(PFX, SNAME, V) \ + \ + /* Implementation Detail Functions */ \ + static bool PFX##_impl_grow(SNAME *_stack_); \ + static SNAME##_iter PFX##_impl_it_start(SNAME *_stack_); \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_stack_); \ + \ + SNAME *PFX##_new(size_t capacity) \ + { \ + if (capacity < 1) \ + return NULL; \ + \ + SNAME *_stack_ = malloc(sizeof(SNAME)); \ + \ + if (!_stack_) \ + return NULL; \ + \ + _stack_->buffer = malloc(sizeof(V) * capacity); \ + \ + if (!_stack_->buffer) \ + { \ + free(_stack_); \ + return NULL; \ + } \ + \ + memset(_stack_->buffer, 0, sizeof(V) * capacity); \ + \ + _stack_->capacity = capacity; \ + _stack_->count = 0; \ + \ + _stack_->it_start = PFX##_impl_it_start; \ + _stack_->it_end = PFX##_impl_it_end; \ + \ + return _stack_; \ + } \ + \ + void PFX##_clear(SNAME *_stack_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _stack_->count; i++) \ + deallocator(_stack_->buffer[i]); \ + } \ + \ + memset(_stack_->buffer, 0, sizeof(V) * _stack_->capacity); \ + \ + _stack_->count = 0; \ + } \ + \ + void PFX##_free(SNAME *_stack_, void (*deallocator)(V)) \ + { \ + free(_stack_->buffer); \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _stack_->count; i++) \ + deallocator(_stack_->buffer[i]); \ + } \ + \ + free(_stack_); \ + } \ + \ + bool PFX##_push(SNAME *_stack_, V element) \ + { \ + if (PFX##_full(_stack_)) \ + { \ + if (!PFX##_impl_grow(_stack_)) \ + return false; \ + } \ + \ + _stack_->buffer[_stack_->count++] = element; \ + \ + return true; \ + } \ + \ + bool PFX##_pop(SNAME *_stack_) \ + { \ + if (PFX##_empty(_stack_)) \ + return false; \ + \ + _stack_->buffer[--_stack_->count] = PFX##_impl_default_value(); \ + \ + return true; \ + } \ + \ + bool PFX##_push_if(SNAME *_stack_, V element, bool condition) \ + { \ + if (condition) \ + return PFX##_push(_stack_, element); \ + \ + return false; \ + } \ + \ + bool PFX##_pop_if(SNAME *_stack_, bool condition) \ + { \ + if (condition) \ + return PFX##_pop(_stack_); \ + \ + return false; \ + } \ + \ + V PFX##_top(SNAME *_stack_) \ + { \ + if (PFX##_empty(_stack_)) \ + return PFX##_impl_default_value(); \ + \ + return _stack_->buffer[_stack_->count - 1]; \ + } \ + \ + bool PFX##_contains(SNAME *_stack_, V element, int (*comparator)(V, V)) \ + { \ + for (size_t i = 0; i < _stack_->count; i++) \ + { \ + if (comparator(_stack_->buffer[i], element) == 0) \ + return true; \ + } \ + \ + return false; \ + } \ + \ + bool PFX##_empty(SNAME *_stack_) \ + { \ + return _stack_->count == 0; \ + } \ + \ + bool PFX##_full(SNAME *_stack_) \ + { \ + return _stack_->count >= _stack_->capacity; \ + } \ + \ + size_t PFX##_count(SNAME *_stack_) \ + { \ + return _stack_->count; \ + } \ + \ + size_t PFX##_capacity(SNAME *_stack_) \ + { \ + return _stack_->capacity; \ + } \ + \ + SNAME *PFX##_copy_of(SNAME *_stack_, V (*copy_func)(V)) \ + { \ + SNAME *result = PFX##_new(_stack_->capacity); \ + \ + if (!result) \ + return NULL; \ + \ + 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(V) * _stack_->count); \ + \ + result->count = _stack_->count; \ + \ + return result; \ + } \ + \ + bool PFX##_equals(SNAME *_stack1_, SNAME *_stack2_, int (*comparator)(V, V)) \ + { \ + if (PFX##_count(_stack1_) != PFX##_count(_stack2_)) \ + return false; \ + \ + for (size_t i = 0; i < PFX##_count(_stack1_); i++) \ + { \ + if (comparator(_stack1_->buffer[i], _stack2_->buffer[i]) != 0) \ + return false; \ + } \ + \ + return true; \ + } \ + \ + cmc_string PFX##_to_string(SNAME *_stack_) \ + { \ + cmc_string str; \ + SNAME *s_ = _stack_; \ + const char *name = #SNAME; \ + \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_stack, \ + name, s_, s_->buffer, s_->capacity, s_->count); \ + \ + return str; \ + } \ + \ + SNAME##_iter *PFX##_iter_new(SNAME *target) \ + { \ + SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + void PFX##_iter_free(SNAME##_iter *iter) \ + { \ + free(iter); \ + } \ + \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + { \ + iter->target = target; \ + iter->cursor = PFX##_empty(target) ? 0 : iter->target->count - 1; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + } \ + \ + bool PFX##_iter_start(SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + bool PFX##_iter_end(SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + void PFX##_iter_to_start(SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->target->count - 1; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ + } \ + \ + void PFX##_iter_to_end(SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = 0; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + } \ + } \ + \ + bool PFX##_iter_next(SNAME##_iter *iter) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->cursor == 0) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + iter->cursor--; \ + \ + return true; \ + } \ + \ + bool PFX##_iter_prev(SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor + 1 == PFX##_count(iter->target)) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->cursor++; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->cursor == 0) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->cursor < steps) \ + return false; \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + iter->cursor -= steps; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor + 1 == PFX##_count(iter->target)) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->cursor + steps >= PFX##_count(iter->target)) \ + return false; \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->cursor += steps; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator was able to be positioned at the given */ \ + /* index */ \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + { \ + if (index >= PFX##_count(iter->target)) \ + return false; \ + \ + if (iter->cursor > index) \ + return PFX##_iter_rewind(iter, iter->cursor - index); \ + else if (iter->cursor < index) \ + return PFX##_iter_advance(iter, index - iter->cursor); \ + \ + return true; \ + } \ + \ + V PFX##_iter_value(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return PFX##_impl_default_value(); \ + \ + return iter->target->buffer[iter->cursor]; \ + } \ + \ + V *PFX##_iter_rvalue(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return NULL; \ + \ + return &(iter->target->buffer[iter->cursor]); \ + } \ + \ + size_t PFX##_iter_index(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return 0; \ + \ + return iter->target->count - 1 - iter->cursor; \ + } \ + \ + static bool PFX##_impl_grow(SNAME *_stack_) \ + { \ + size_t new_capacity = _stack_->capacity * 2; \ + \ + V *new_buffer = realloc(_stack_->buffer, sizeof(V) * new_capacity); \ + \ + if (!new_buffer) \ + return false; \ + \ + _stack_->buffer = new_buffer; \ + _stack_->capacity = new_capacity; \ + \ + return true; \ + } \ + \ + static SNAME##_iter PFX##_impl_it_start(SNAME *_stack_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _stack_); \ + PFX##_iter_to_start(&iter); \ + \ + return iter; \ + } \ + \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_stack_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _stack_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_STACK_H */ diff --git a/src/cmc/treemap.h b/src/cmc/treemap.h index b1f063e..8d9f83b 100644 --- a/src/cmc/treemap.h +++ b/src/cmc/treemap.h @@ -25,159 +25,159 @@ #include #include "../utl/cmc_string.h" -#define TREEMAP_GENERATE(PFX, SNAME, FMOD, K, V) \ - TREEMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \ - TREEMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) +#define CMC_GENERATE_TREEMAP(PFX, SNAME, K, V) \ + CMC_GENERATE_TREEMAP_HEADER(PFX, SNAME, K, V) \ + CMC_GENERATE_TREEMAP_SOURCE(PFX, SNAME, K, V) -#define TREEMAP_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \ - TREEMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) +#define CMC_WRAPGEN_TREEMAP_HEADER(PFX, SNAME, K, V) \ + CMC_GENERATE_TREEMAP_HEADER(PFX, SNAME, K, V) -#define TREEMAP_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \ - TREEMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) +#define CMC_WRAPGEN_TREEMAP_SOURCE(PFX, SNAME, K, V) \ + CMC_GENERATE_TREEMAP_SOURCE(PFX, SNAME, K, V) /* HEADER ********************************************************************/ -#define TREEMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \ - \ - /* Treemap Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Root node */ \ - struct SNAME##_node_s *root; \ - \ - /* Current amount of keys */ \ - size_t count; \ - \ - /* Key comparison function */ \ - int (*cmp)(K, K); \ - \ - /* Function that returns an iterator to the start of the treemap */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the treemap */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Treemap Node */ \ - typedef struct SNAME##_node_s \ - { \ - /* Node Key */ \ - K key; \ - \ - /* Node Value */ \ - V value; \ - \ - /* Node height used by the AVL tree to keep it strictly balanced */ \ - unsigned char height; \ - \ - /* Right child node or subtree */ \ - struct SNAME##_node_s *right; \ - \ - /* Left child node or subtree */ \ - struct SNAME##_node_s *left; \ - \ - /* Parent node */ \ - struct SNAME##_node_s *parent; \ - \ - } SNAME##_node, *SNAME##_node_ptr; \ - \ - /* Treemap Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target treemap */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's current node */ \ - struct SNAME##_node_s *cursor; \ - \ - /* The first node in the iteration */ \ - struct SNAME##_node_s *first; \ - \ - /* The last node in the iteration */ \ - struct SNAME##_node_s *last; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - FMOD SNAME *PFX##_new(int (*compare)(K, K)); \ - FMOD void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)); \ - FMOD void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)); \ - /* Collection Input and Output */ \ - FMOD bool PFX##_insert(SNAME *_map_, K key, V value); \ - FMOD bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value); \ - FMOD bool PFX##_remove(SNAME *_map_, K key, V *out_value); \ - /* Conditional Input and Output */ \ - FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition); \ - FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *out_value, bool condition); \ - /* Element Access */ \ - FMOD bool PFX##_max(SNAME *_map_, K *key, V *value); \ - FMOD bool PFX##_min(SNAME *_map_, K *key, V *value); \ - FMOD V PFX##_get(SNAME *_map_, K key); \ - FMOD V *PFX##_get_ref(SNAME *_map_, K key); \ - /* Collection State */ \ - FMOD bool PFX##_contains(SNAME *_map_, K key); \ - FMOD bool PFX##_empty(SNAME *_map_); \ - FMOD size_t PFX##_count(SNAME *_map_); \ - /* Collection Utility */ \ - FMOD SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)); \ - FMOD bool PFX##_equals(SNAME *_map1_, SNAME *_map2_, int (*value_comparator)(V, V)); \ - FMOD cmc_string PFX##_to_string(SNAME *_map_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ - FMOD void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - FMOD K PFX##_iter_key(SNAME##_iter *iter); \ - FMOD V PFX##_iter_value(SNAME##_iter *iter); \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ - /* Default Key */ \ - static inline K PFX##_impl_default_key(void) \ - { \ - K _empty_key_; \ - \ - memset(&_empty_key_, 0, sizeof(K)); \ - \ - return _empty_key_; \ - } \ - \ - /* Default Value */ \ - static inline V PFX##_impl_default_value(void) \ - { \ - V _empty_value_; \ - \ - memset(&_empty_value_, 0, sizeof(V)); \ - \ - return _empty_value_; \ - } \ - \ +#define CMC_GENERATE_TREEMAP_HEADER(PFX, SNAME, K, V) \ + \ + /* Treemap Structure */ \ + typedef struct SNAME##_s \ + { \ + /* Root node */ \ + struct SNAME##_node_s *root; \ + \ + /* Current amount of keys */ \ + size_t count; \ + \ + /* Key comparison function */ \ + int (*cmp)(K, K); \ + \ + /* Function that returns an iterator to the start of the treemap */ \ + struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + \ + /* Function that returns an iterator to the end of the treemap */ \ + struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + \ + } SNAME, *SNAME##_ptr; \ + \ + /* Treemap Node */ \ + typedef struct SNAME##_node_s \ + { \ + /* Node Key */ \ + K key; \ + \ + /* Node Value */ \ + V value; \ + \ + /* Node height used by the AVL tree to keep it strictly balanced */ \ + unsigned char height; \ + \ + /* Right child node or subtree */ \ + struct SNAME##_node_s *right; \ + \ + /* Left child node or subtree */ \ + struct SNAME##_node_s *left; \ + \ + /* Parent node */ \ + struct SNAME##_node_s *parent; \ + \ + } SNAME##_node, *SNAME##_node_ptr; \ + \ + /* Treemap Iterator */ \ + typedef struct SNAME##_iter_s \ + { \ + /* Target treemap */ \ + struct SNAME##_s *target; \ + \ + /* Cursor's current node */ \ + struct SNAME##_node_s *cursor; \ + \ + /* The first node in the iteration */ \ + struct SNAME##_node_s *first; \ + \ + /* The last node in the iteration */ \ + struct SNAME##_node_s *last; \ + \ + /* Keeps track of relative index to the iteration of elements */ \ + size_t index; \ + \ + /* If the iterator has reached the start of the iteration */ \ + bool start; \ + \ + /* If the iterator has reached the end of the iteration */ \ + bool end; \ + \ + } SNAME##_iter, *SNAME##_iter_ptr; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + SNAME *PFX##_new(int (*compare)(K, K)); \ + void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)); \ + void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)); \ + /* Collection Input and Output */ \ + bool PFX##_insert(SNAME *_map_, K key, V value); \ + bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value); \ + bool PFX##_remove(SNAME *_map_, K key, V *out_value); \ + /* Conditional Input and Output */ \ + bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition); \ + bool PFX##_remove_if(SNAME *_map_, K key, V *out_value, bool condition); \ + /* Element Access */ \ + bool PFX##_max(SNAME *_map_, K *key, V *value); \ + bool PFX##_min(SNAME *_map_, K *key, V *value); \ + V PFX##_get(SNAME *_map_, K key); \ + V *PFX##_get_ref(SNAME *_map_, K key); \ + /* Collection State */ \ + bool PFX##_contains(SNAME *_map_, K key); \ + bool PFX##_empty(SNAME *_map_); \ + size_t PFX##_count(SNAME *_map_); \ + /* Collection Utility */ \ + SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)); \ + bool PFX##_equals(SNAME *_map1_, SNAME *_map2_, int (*value_comparator)(V, V)); \ + cmc_string PFX##_to_string(SNAME *_map_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + SNAME##_iter *PFX##_iter_new(SNAME *target); \ + void PFX##_iter_free(SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(SNAME##_iter *iter); \ + bool PFX##_iter_end(SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(SNAME##_iter *iter); \ + void PFX##_iter_to_end(SNAME##_iter *iter); \ + bool PFX##_iter_next(SNAME##_iter *iter); \ + bool PFX##_iter_prev(SNAME##_iter *iter); \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + K PFX##_iter_key(SNAME##_iter *iter); \ + V PFX##_iter_value(SNAME##_iter *iter); \ + V *PFX##_iter_rvalue(SNAME##_iter *iter); \ + size_t PFX##_iter_index(SNAME##_iter *iter); \ + \ + /* Default Key */ \ + static inline K PFX##_impl_default_key(void) \ + { \ + K _empty_key_; \ + \ + memset(&_empty_key_, 0, sizeof(K)); \ + \ + return _empty_key_; \ + } \ + \ + /* Default Value */ \ + static inline V PFX##_impl_default_value(void) \ + { \ + V _empty_value_; \ + \ + memset(&_empty_value_, 0, sizeof(V)); \ + \ + return _empty_value_; \ + } \ + \ /* SOURCE ********************************************************************/ -#define TREEMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) \ +#define CMC_GENERATE_TREEMAP_SOURCE(PFX, SNAME, K, V) \ \ /* Implementation Detail Functions */ \ static SNAME##_node *PFX##_impl_new_node(K key, V value); \ @@ -190,7 +190,7 @@ static SNAME##_iter PFX##_impl_it_start(SNAME *_map_); \ static SNAME##_iter PFX##_impl_it_end(SNAME *_map_); \ \ - FMOD SNAME *PFX##_new(int (*compare)(K, K)) \ + SNAME *PFX##_new(int (*compare)(K, K)) \ { \ SNAME *_map_ = malloc(sizeof(SNAME)); \ \ @@ -207,7 +207,7 @@ return _map_; \ } \ \ - FMOD void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)) \ + void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)) \ { \ SNAME##_node *scan = _map_->root; \ SNAME##_node *up = NULL; \ @@ -268,14 +268,14 @@ _map_->root = NULL; \ } \ \ - FMOD void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)) \ + void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)) \ { \ PFX##_clear(_map_, deallocator); \ \ free(_map_); \ } \ \ - FMOD bool PFX##_insert(SNAME *_map_, K key, V value) \ + bool PFX##_insert(SNAME *_map_, K key, V value) \ { \ if (PFX##_empty(_map_)) \ { \ @@ -332,7 +332,7 @@ return true; \ } \ \ - FMOD bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value) \ + bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value) \ { \ SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ \ @@ -347,7 +347,7 @@ return true; \ } \ \ - FMOD bool PFX##_remove(SNAME *_map_, K key, V *out_value) \ + bool PFX##_remove(SNAME *_map_, K key, V *out_value) \ { \ SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ \ @@ -473,7 +473,7 @@ return true; \ } \ \ - FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition) \ + bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition) \ { \ if (condition) \ return PFX##_insert(_map_, key, value); \ @@ -481,7 +481,7 @@ return false; \ } \ \ - FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *out_value, bool condition) \ + bool PFX##_remove_if(SNAME *_map_, K key, V *out_value, bool condition) \ { \ if (condition) \ return PFX##_remove(_map_, key, out_value); \ @@ -489,7 +489,7 @@ return false; \ } \ \ - FMOD bool PFX##_max(SNAME *_map_, K *key, V *value) \ + bool PFX##_max(SNAME *_map_, K *key, V *value) \ { \ if (PFX##_empty(_map_)) \ return false; \ @@ -505,7 +505,7 @@ return true; \ } \ \ - FMOD bool PFX##_min(SNAME *_map_, K *key, V *value) \ + bool PFX##_min(SNAME *_map_, K *key, V *value) \ { \ if (PFX##_empty(_map_)) \ return false; \ @@ -521,7 +521,7 @@ return true; \ } \ \ - FMOD V PFX##_get(SNAME *_map_, K key) \ + V PFX##_get(SNAME *_map_, K key) \ { \ SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ \ @@ -531,7 +531,7 @@ return node->value; \ } \ \ - FMOD V *PFX##_get_ref(SNAME *_map_, K key) \ + V *PFX##_get_ref(SNAME *_map_, K key) \ { \ SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ \ @@ -541,7 +541,7 @@ return &(node->value); \ } \ \ - FMOD bool PFX##_contains(SNAME *_map_, K key) \ + bool PFX##_contains(SNAME *_map_, K key) \ { \ SNAME##_node *scan = _map_->root; \ \ @@ -558,17 +558,17 @@ return false; \ } \ \ - FMOD bool PFX##_empty(SNAME *_map_) \ + bool PFX##_empty(SNAME *_map_) \ { \ return _map_->count == 0; \ } \ \ - FMOD size_t PFX##_count(SNAME *_map_) \ + size_t PFX##_count(SNAME *_map_) \ { \ return _map_->count; \ } \ \ - FMOD SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)) \ + SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)) \ { \ SNAME *result = PFX##_new(_map_->cmp); \ \ @@ -597,7 +597,7 @@ return result; \ } \ \ - FMOD bool PFX##_equals(SNAME *_map1_, SNAME *_map2_, int (*value_comparator)(V, V)) \ + bool PFX##_equals(SNAME *_map1_, SNAME *_map2_, int (*value_comparator)(V, V)) \ { \ if (PFX##_count(_map1_) != PFX##_count(_map2_)) \ return false; \ @@ -622,7 +622,7 @@ return true; \ } \ \ - FMOD cmc_string PFX##_to_string(SNAME *_map_) \ + cmc_string PFX##_to_string(SNAME *_map_) \ { \ cmc_string str; \ SNAME *m_ = _map_; \ @@ -634,7 +634,7 @@ return str; \ } \ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ + SNAME##_iter *PFX##_iter_new(SNAME *target) \ { \ SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ \ @@ -646,12 +646,12 @@ return iter; \ } \ \ - FMOD void PFX##_iter_free(SNAME##_iter *iter) \ + void PFX##_iter_free(SNAME##_iter *iter) \ { \ free(iter); \ } \ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ { \ memset(iter, 0, sizeof(SNAME##_iter)); \ \ @@ -674,17 +674,17 @@ } \ } \ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ + bool PFX##_iter_start(SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->start; \ } \ \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ + bool PFX##_iter_end(SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->end; \ } \ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ + void PFX##_iter_to_start(SNAME##_iter *iter) \ { \ if (!PFX##_empty(iter->target)) \ { \ @@ -695,7 +695,7 @@ } \ } \ \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ + void PFX##_iter_to_end(SNAME##_iter *iter) \ { \ if (!PFX##_empty(iter->target)) \ { \ @@ -706,7 +706,7 @@ } \ } \ \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ + bool PFX##_iter_next(SNAME##_iter *iter) \ { \ if (iter->end) \ return false; \ @@ -746,7 +746,7 @@ } \ } \ \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ + bool PFX##_iter_prev(SNAME##_iter *iter) \ { \ if (iter->start) \ return false; \ @@ -787,7 +787,7 @@ } \ \ /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ { \ if (iter->end) \ return false; \ @@ -810,7 +810,7 @@ } \ \ /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ { \ if (iter->start) \ return false; \ @@ -833,7 +833,7 @@ } \ \ /* Returns true only if the iterator was able to be positioned at the given index */ \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ { \ if (index >= PFX##_count(iter->target)) \ return false; \ @@ -846,7 +846,7 @@ return true; \ } \ \ - FMOD K PFX##_iter_key(SNAME##_iter *iter) \ + K PFX##_iter_key(SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ return PFX##_impl_default_key(); \ @@ -854,7 +854,7 @@ return iter->cursor->key; \ } \ \ - FMOD V PFX##_iter_value(SNAME##_iter *iter) \ + V PFX##_iter_value(SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ return PFX##_impl_default_value(); \ @@ -862,7 +862,7 @@ return iter->cursor->value; \ } \ \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \ + V *PFX##_iter_rvalue(SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ return NULL; \ @@ -870,7 +870,7 @@ return &(iter->cursor->value); \ } \ \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ + size_t PFX##_iter_index(SNAME##_iter *iter) \ { \ return iter->index; \ } \ diff --git a/src/cmc/treeset.h b/src/cmc/treeset.h index 7cb5f95..b97b583 100644 --- a/src/cmc/treeset.h +++ b/src/cmc/treeset.h @@ -25,18 +25,18 @@ #include #include "../utl/cmc_string.h" -#define TREESET_GENERATE(PFX, SNAME, FMOD, V) \ - TREESET_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - TREESET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) +#define CMC_GENERATE_TREESET(PFX, SNAME, V) \ + CMC_GENERATE_TREESET_HEADER(PFX, SNAME, V) \ + CMC_GENERATE_TREESET_SOURCE(PFX, SNAME, V) -#define TREESET_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \ - TREESET_GENERATE_HEADER(PFX, SNAME, FMOD, V) +#define CMC_WRAPGEN_TREESET_HEADER(PFX, SNAME, K, V) \ + CMC_GENERATE_TREESET_HEADER(PFX, SNAME, V) -#define TREESET_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \ - TREESET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) +#define CMC_WRAPGEN_TREESET_SOURCE(PFX, SNAME, K, V) \ + CMC_GENERATE_TREESET_SOURCE(PFX, SNAME, V) /* HEADER ********************************************************************/ -#define TREESET_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ +#define CMC_GENERATE_TREESET_HEADER(PFX, SNAME, V) \ \ /* Treeset Structure */ \ typedef struct SNAME##_s \ @@ -106,58 +106,58 @@ \ /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ - FMOD SNAME *PFX##_new(int (*compare)(V, V)); \ - FMOD void PFX##_clear(SNAME *_set_, void (*deallocator)(V)); \ - FMOD void PFX##_free(SNAME *_set_, void (*deallocator)(V)); \ + SNAME *PFX##_new(int (*compare)(V, V)); \ + void PFX##_clear(SNAME *_set_, void (*deallocator)(V)); \ + void PFX##_free(SNAME *_set_, void (*deallocator)(V)); \ /* Collection Input and Output */ \ - FMOD bool PFX##_insert(SNAME *_set_, V element); \ - FMOD bool PFX##_remove(SNAME *_set_, V element); \ + bool PFX##_insert(SNAME *_set_, V element); \ + bool PFX##_remove(SNAME *_set_, V element); \ /* Conditional Input and Output */ \ - FMOD bool PFX##_insert_if(SNAME *_set_, V element, bool condition); \ - FMOD bool PFX##_remove_if(SNAME *_set_, V element, bool condition); \ + bool PFX##_insert_if(SNAME *_set_, V element, bool condition); \ + bool PFX##_remove_if(SNAME *_set_, V element, bool condition); \ /* Element Access */ \ - FMOD bool PFX##_max(SNAME *_set_, V *value); \ - FMOD bool PFX##_min(SNAME *_set_, V *value); \ + bool PFX##_max(SNAME *_set_, V *value); \ + bool PFX##_min(SNAME *_set_, V *value); \ /* Collection State */ \ - FMOD bool PFX##_contains(SNAME *_set_, V element); \ - FMOD bool PFX##_empty(SNAME *_set_); \ - FMOD size_t PFX##_count(SNAME *_set_); \ + bool PFX##_contains(SNAME *_set_, V element); \ + bool PFX##_empty(SNAME *_set_); \ + size_t PFX##_count(SNAME *_set_); \ /* Collection Utility */ \ - FMOD SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)); \ - FMOD bool PFX##_equals(SNAME *_set1_, SNAME *_set2_); \ - FMOD cmc_string PFX##_to_string(SNAME *_set_); \ + SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)); \ + bool PFX##_equals(SNAME *_set1_, SNAME *_set2_); \ + cmc_string PFX##_to_string(SNAME *_set_); \ \ /* Set Operations */ \ - FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_); \ - FMOD SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_); \ - FMOD SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_); \ - FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_); \ - FMOD bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_); \ - FMOD bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_); \ - FMOD bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_); \ - FMOD bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_); \ - FMOD bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_); \ + SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_); \ + SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_); \ + SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_); \ + SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_); \ + bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_); \ + bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_); \ + bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_); \ + bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_); \ + bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_); \ \ /* Iterator Functions */ \ /* Iterator Allocation and Deallocation */ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ - FMOD void PFX##_iter_free(SNAME##_iter *iter); \ + SNAME##_iter *PFX##_iter_new(SNAME *target); \ + void PFX##_iter_free(SNAME##_iter *iter); \ /* Iterator Initialization */ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ /* Iterator State */ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ + bool PFX##_iter_start(SNAME##_iter *iter); \ + bool PFX##_iter_end(SNAME##_iter *iter); \ /* Iterator Movement */ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ + void PFX##_iter_to_start(SNAME##_iter *iter); \ + void PFX##_iter_to_end(SNAME##_iter *iter); \ + bool PFX##_iter_next(SNAME##_iter *iter); \ + bool PFX##_iter_prev(SNAME##_iter *iter); \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ /* Iterator Access */ \ - FMOD V PFX##_iter_value(SNAME##_iter *iter); \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ + V PFX##_iter_value(SNAME##_iter *iter); \ + size_t PFX##_iter_index(SNAME##_iter *iter); \ \ /* Default Value */ \ static inline V PFX##_impl_default_value(void) \ @@ -170,7 +170,7 @@ } \ \ /* SOURCE ********************************************************************/ -#define TREESET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ +#define CMC_GENERATE_TREESET_SOURCE(PFX, SNAME, V) \ \ /* Implementation Detail Functions */ \ static SNAME##_node *PFX##_impl_new_node(V element); \ @@ -183,7 +183,7 @@ static SNAME##_iter PFX##_impl_it_start(SNAME *_set_); \ static SNAME##_iter PFX##_impl_it_end(SNAME *_set_); \ \ - FMOD SNAME *PFX##_new(int (*compare)(V, V)) \ + SNAME *PFX##_new(int (*compare)(V, V)) \ { \ SNAME *_set_ = malloc(sizeof(SNAME)); \ \ @@ -200,7 +200,7 @@ return _set_; \ } \ \ - FMOD void PFX##_clear(SNAME *_set_, void (*deallocator)(V)) \ + void PFX##_clear(SNAME *_set_, void (*deallocator)(V)) \ { \ SNAME##_node *scan = _set_->root; \ SNAME##_node *up = NULL; \ @@ -261,14 +261,14 @@ _set_->root = NULL; \ } \ \ - FMOD void PFX##_free(SNAME *_set_, void (*deallocator)(V)) \ + void PFX##_free(SNAME *_set_, void (*deallocator)(V)) \ { \ PFX##_clear(_set_, deallocator); \ \ free(_set_); \ } \ \ - FMOD bool PFX##_insert(SNAME *_set_, V element) \ + bool PFX##_insert(SNAME *_set_, V element) \ { \ if (PFX##_empty(_set_)) \ { \ @@ -325,7 +325,7 @@ return true; \ } \ \ - FMOD bool PFX##_remove(SNAME *_set_, V element) \ + bool PFX##_remove(SNAME *_set_, V element) \ { \ SNAME##_node *node = PFX##_impl_get_node(_set_, element); \ \ @@ -446,7 +446,7 @@ return true; \ } \ \ - FMOD bool PFX##_insert_if(SNAME *_set_, V element, bool condition) \ + bool PFX##_insert_if(SNAME *_set_, V element, bool condition) \ { \ if (condition) \ return PFX##_insert(_set_, element); \ @@ -454,7 +454,7 @@ return false; \ } \ \ - FMOD bool PFX##_remove_if(SNAME *_set_, V element, bool condition) \ + bool PFX##_remove_if(SNAME *_set_, V element, bool condition) \ { \ if (condition) \ return PFX##_remove(_set_, element); \ @@ -462,7 +462,7 @@ return false; \ } \ \ - FMOD bool PFX##_max(SNAME *_set_, V *value) \ + bool PFX##_max(SNAME *_set_, V *value) \ { \ if (PFX##_empty(_set_)) \ return false; \ @@ -477,7 +477,7 @@ return true; \ } \ \ - FMOD bool PFX##_min(SNAME *_set_, V *value) \ + bool PFX##_min(SNAME *_set_, V *value) \ { \ if (PFX##_empty(_set_)) \ return false; \ @@ -492,7 +492,7 @@ return true; \ } \ \ - FMOD bool PFX##_contains(SNAME *_set_, V element) \ + bool PFX##_contains(SNAME *_set_, V element) \ { \ SNAME##_node *scan = _set_->root; \ \ @@ -509,17 +509,17 @@ return false; \ } \ \ - FMOD bool PFX##_empty(SNAME *_set_) \ + bool PFX##_empty(SNAME *_set_) \ { \ return _set_->count == 0; \ } \ \ - FMOD size_t PFX##_count(SNAME *_set_) \ + size_t PFX##_count(SNAME *_set_) \ { \ return _set_->count; \ } \ \ - FMOD SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)) \ + SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)) \ { \ SNAME *result = PFX##_new(_set_->cmp); \ \ @@ -543,7 +543,7 @@ return result; \ } \ \ - FMOD bool PFX##_equals(SNAME *_set1_, SNAME *_set2_) \ + bool PFX##_equals(SNAME *_set1_, SNAME *_set2_) \ { \ if (PFX##_count(_set1_) != PFX##_count(_set2_)) \ return false; \ @@ -560,7 +560,7 @@ return true; \ } \ \ - FMOD cmc_string PFX##_to_string(SNAME *_set_) \ + cmc_string PFX##_to_string(SNAME *_set_) \ { \ cmc_string str; \ SNAME *s_ = _set_; \ @@ -572,7 +572,7 @@ return str; \ } \ \ - FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_) \ + SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_) \ { \ SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ \ @@ -596,7 +596,7 @@ return _set_r_; \ } \ \ - FMOD SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_) \ + SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_) \ { \ SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ \ @@ -620,7 +620,7 @@ return _set_r_; \ } \ \ - FMOD SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_) \ + SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_) \ { \ SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ \ @@ -641,7 +641,7 @@ return _set_r_; \ } \ \ - FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_) \ + SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_) \ { \ SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ \ @@ -674,7 +674,7 @@ /* Is _set1_ a subset of _set2_ ? */ \ /* A set X is a subset of a set Y when: X <= Y */ \ /* If X is a subset of Y, then Y is a superset of X */ \ - FMOD bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_) \ + bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_) \ { \ /* If the cardinality of _set1_ is greater than that of _set2_, then it is safe */ \ /* to say that _set1_ can't be a subset of _set2_ */ \ @@ -703,7 +703,7 @@ /* Is _set1_ a superset of _set2_ ? */ \ /* A set X is a superset of a set Y when: X >= Y */ \ /* If X is a superset of Y, then Y is a subset of X */ \ - FMOD bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_) \ + bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_) \ { \ return PFX##_is_subset(_set2_, _set1_); \ } \ @@ -711,7 +711,7 @@ /* Is _set1_ a proper subset of _set2_ ? */ \ /* A set X is a proper subset of a set Y when: X < Y */ \ /* If X is a proper subset of Y, then Y is a proper superset of X */ \ - FMOD bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_) \ + bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_) \ { \ /* If the cardinality of _set1_ is greater than or equal to that of _set2_, then */ \ /* it is safe to say that _set1_ can't be a proper subset of _set2_ */ \ @@ -746,7 +746,7 @@ /* Is _set1_ a proper superset of _set2_ ? */ \ /* A set X is a proper superset of a set Y when: X > Y */ \ /* If X is a proper superset of Y, then Y is a proper subset of X */ \ - FMOD bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_) \ + bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_) \ { \ return PFX##_is_proper_subset(_set2_, _set1_); \ } \ @@ -754,7 +754,7 @@ /* Is _set1_ a disjointset of _set2_ ? */ \ /* A set X is a disjointset of a set Y if their intersection is empty, that is, if */ \ /* there are no elements in common between the two */ \ - FMOD bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_) \ + bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_) \ { \ /* The intersection of an empty set with any other set will result in an empty */ \ /* set */ \ @@ -776,7 +776,7 @@ return true; \ } \ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ + SNAME##_iter *PFX##_iter_new(SNAME *target) \ { \ SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ \ @@ -788,12 +788,12 @@ return iter; \ } \ \ - FMOD void PFX##_iter_free(SNAME##_iter *iter) \ + void PFX##_iter_free(SNAME##_iter *iter) \ { \ free(iter); \ } \ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ { \ memset(iter, 0, sizeof(SNAME##_iter)); \ \ @@ -816,17 +816,17 @@ } \ } \ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ + bool PFX##_iter_start(SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->start; \ } \ \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ + bool PFX##_iter_end(SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->end; \ } \ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ + void PFX##_iter_to_start(SNAME##_iter *iter) \ { \ if (!PFX##_empty(iter->target)) \ { \ @@ -837,7 +837,7 @@ } \ } \ \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ + void PFX##_iter_to_end(SNAME##_iter *iter) \ { \ if (!PFX##_empty(iter->target)) \ { \ @@ -848,7 +848,7 @@ } \ } \ \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ + bool PFX##_iter_next(SNAME##_iter *iter) \ { \ if (iter->end) \ return false; \ @@ -888,7 +888,7 @@ } \ } \ \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ + bool PFX##_iter_prev(SNAME##_iter *iter) \ { \ if (iter->start) \ return false; \ @@ -930,7 +930,7 @@ } \ \ /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ { \ if (iter->end) \ return false; \ @@ -953,7 +953,7 @@ } \ \ /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ { \ if (iter->start) \ return false; \ @@ -976,7 +976,7 @@ } \ \ /* Returns true only if the iterator was able to be positioned at the given index */ \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ { \ if (index >= PFX##_count(iter->target)) \ return false; \ @@ -989,7 +989,7 @@ return true; \ } \ \ - FMOD V PFX##_iter_value(SNAME##_iter *iter) \ + V PFX##_iter_value(SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ return PFX##_impl_default_value(); \ @@ -997,7 +997,7 @@ return iter->cursor->value; \ } \ \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ + size_t PFX##_iter_index(SNAME##_iter *iter) \ { \ return iter->index; \ } \ diff --git a/src/ext/intervalheap.h b/src/ext/intervalheap.h index 1d3f678..e12d528 100644 --- a/src/ext/intervalheap.h +++ b/src/ext/intervalheap.h @@ -27,134 +27,134 @@ #include #include "../utl/cmc_string.h" -#define INTERVALHEAP_GENERATE(PFX, SNAME, FMOD, V) \ - INTERVALHEAP_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - INTERVALHEAP_GENERATE_SOURCE(PFX, SNAME, FMOD, V) +#define CMC_GENERATE_INTERVALHEAP(PFX, SNAME, V) \ + CMC_GENERATE_INTERVALHEAP_HEADER(PFX, SNAME, V) \ + CMC_GENERATE_INTERVALHEAP_SOURCE(PFX, SNAME, V) -#define INTERVALHEAP_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \ - INTERVALHEAP_GENERATE_HEADER(PFX, SNAME, FMOD, V) +#define CMC_WRAPGEN_INTERVALHEAP_HEADER(PFX, SNAME, K, V) \ + CMC_GENERATE_INTERVALHEAP_HEADER(PFX, SNAME, V) -#define INTERVALHEAP_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \ - INTERVALHEAP_GENERATE_SOURCE(PFX, SNAME, FMOD, V) +#define CMC_WRAPGEN_INTERVALHEAP_SOURCE(PFX, SNAME, K, V) \ + CMC_GENERATE_INTERVALHEAP_SOURCE(PFX, SNAME, V) /* HEADER ********************************************************************/ -#define INTERVALHEAP_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - \ - /* Heap Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Dynamic array of nodes */ \ - struct SNAME##_node_s *buffer; \ - \ - /* Current array capacity (how many nodes can be stored) */ \ - size_t capacity; \ - \ - /* Current amount of nodes in the dynamic array */ \ - size_t size; \ - \ - /* Current amount of elements in the heap */ \ - size_t count; \ - \ - /* Element comparison function */ \ - int (*cmp)(V, V); \ - \ - /* Function that returns an iterator to the start of the heap */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the heap */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Heap Node */ \ - typedef struct SNAME##_node_s \ - { \ - /* 0 - Value belonging to the MinHeap */ \ - /* 1 - Value belonging to the MaxHeap */ \ - V data[2]; \ - \ - } SNAME##_node, *SNAME##_node_ptr; \ - \ - /* Heap Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target heap */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - FMOD SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)); \ - FMOD void PFX##_clear(SNAME *_heap_, void (*deallocator)(V)); \ - FMOD void PFX##_free(SNAME *_heap_, void (*deallocator)(V)); \ - /* Collection Input and Output */ \ - FMOD bool PFX##_insert(SNAME *_heap_, V element); \ - FMOD bool PFX##_remove_max(SNAME *_heap_, V *result); \ - FMOD bool PFX##_remove_min(SNAME *_heap_, V *result); \ - /* Conditional Input and Output */ \ - FMOD bool PFX##_insert_if(SNAME *_heap_, V element, bool condition); \ - FMOD bool PFX##_remove_max_if(SNAME *_heap_, V *result, bool condition); \ - FMOD bool PFX##_remove_min_if(SNAME *_heap_, V *result, bool condition); \ - /* Collection Update */ \ - FMOD bool PFX##_update_max(SNAME *_heap_, V element); \ - FMOD bool PFX##_update_min(SNAME *_heap_, V element); \ - /* Element Access */ \ - FMOD bool PFX##_max(SNAME *_heap_, V *value); \ - FMOD bool PFX##_min(SNAME *_heap_, V *value); \ - /* Collection State */ \ - FMOD bool PFX##_contains(SNAME *_heap_, V element); \ - FMOD bool PFX##_empty(SNAME *_heap_); \ - FMOD bool PFX##_full(SNAME *_heap_); \ - FMOD size_t PFX##_count(SNAME *_heap_); \ - FMOD size_t PFX##_capacity(SNAME *_heap_); \ - /* Collection Utility */ \ - FMOD SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)); \ - FMOD bool PFX##_equals(SNAME *_heap1_, SNAME *_heap2_); \ - FMOD cmc_string PFX##_to_string(SNAME *_heap_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ - FMOD void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - FMOD V PFX##_iter_value(SNAME##_iter *iter); \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ - /* Default Value */ \ - static inline V PFX##_impl_default_value(void) \ - { \ - V _empty_value_; \ - \ - memset(&_empty_value_, 0, sizeof(V)); \ - \ - return _empty_value_; \ - } \ - \ +#define CMC_GENERATE_INTERVALHEAP_HEADER(PFX, SNAME, V) \ + \ + /* Heap Structure */ \ + typedef struct SNAME##_s \ + { \ + /* Dynamic array of nodes */ \ + struct SNAME##_node_s *buffer; \ + \ + /* Current array capacity (how many nodes can be stored) */ \ + size_t capacity; \ + \ + /* Current amount of nodes in the dynamic array */ \ + size_t size; \ + \ + /* Current amount of elements in the heap */ \ + size_t count; \ + \ + /* Element comparison function */ \ + int (*cmp)(V, V); \ + \ + /* Function that returns an iterator to the start of the heap */ \ + struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + \ + /* Function that returns an iterator to the end of the heap */ \ + struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + \ + } SNAME, *SNAME##_ptr; \ + \ + /* Heap Node */ \ + typedef struct SNAME##_node_s \ + { \ + /* 0 - Value belonging to the MinHeap */ \ + /* 1 - Value belonging to the MaxHeap */ \ + V data[2]; \ + \ + } SNAME##_node, *SNAME##_node_ptr; \ + \ + /* Heap Iterator */ \ + typedef struct SNAME##_iter_s \ + { \ + /* Target heap */ \ + struct SNAME##_s *target; \ + \ + /* Cursor's position (index) */ \ + size_t cursor; \ + \ + /* If the iterator has reached the start of the iteration */ \ + bool start; \ + \ + /* If the iterator has reached the end of the iteration */ \ + bool end; \ + \ + } SNAME##_iter, *SNAME##_iter_ptr; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)); \ + void PFX##_clear(SNAME *_heap_, void (*deallocator)(V)); \ + void PFX##_free(SNAME *_heap_, void (*deallocator)(V)); \ + /* Collection Input and Output */ \ + bool PFX##_insert(SNAME *_heap_, V element); \ + bool PFX##_remove_max(SNAME *_heap_, V *result); \ + bool PFX##_remove_min(SNAME *_heap_, V *result); \ + /* Conditional Input and Output */ \ + bool PFX##_insert_if(SNAME *_heap_, V element, bool condition); \ + bool PFX##_remove_max_if(SNAME *_heap_, V *result, bool condition); \ + bool PFX##_remove_min_if(SNAME *_heap_, V *result, bool condition); \ + /* Collection Update */ \ + bool PFX##_update_max(SNAME *_heap_, V element); \ + bool PFX##_update_min(SNAME *_heap_, V element); \ + /* Element Access */ \ + bool PFX##_max(SNAME *_heap_, V *value); \ + bool PFX##_min(SNAME *_heap_, V *value); \ + /* Collection State */ \ + bool PFX##_contains(SNAME *_heap_, V element); \ + bool PFX##_empty(SNAME *_heap_); \ + bool PFX##_full(SNAME *_heap_); \ + size_t PFX##_count(SNAME *_heap_); \ + size_t PFX##_capacity(SNAME *_heap_); \ + /* Collection Utility */ \ + SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)); \ + bool PFX##_equals(SNAME *_heap1_, SNAME *_heap2_); \ + cmc_string PFX##_to_string(SNAME *_heap_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + SNAME##_iter *PFX##_iter_new(SNAME *target); \ + void PFX##_iter_free(SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(SNAME##_iter *iter); \ + bool PFX##_iter_end(SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(SNAME##_iter *iter); \ + void PFX##_iter_to_end(SNAME##_iter *iter); \ + bool PFX##_iter_next(SNAME##_iter *iter); \ + bool PFX##_iter_prev(SNAME##_iter *iter); \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + V PFX##_iter_value(SNAME##_iter *iter); \ + size_t PFX##_iter_index(SNAME##_iter *iter); \ + \ + /* Default Value */ \ + static inline V PFX##_impl_default_value(void) \ + { \ + V _empty_value_; \ + \ + memset(&_empty_value_, 0, sizeof(V)); \ + \ + return _empty_value_; \ + } \ + \ /* SOURCE ********************************************************************/ -#define INTERVALHEAP_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ +#define CMC_GENERATE_INTERVALHEAP_SOURCE(PFX, SNAME, V) \ \ /* Implementation Detail Functions */ \ static bool PFX##_impl_grow(SNAME *_heap_); \ @@ -165,7 +165,7 @@ static SNAME##_iter PFX##_impl_it_start(SNAME *_heap_); \ static SNAME##_iter PFX##_impl_it_end(SNAME *_heap_); \ \ - FMOD SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)) \ + SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)) \ { \ SNAME *_heap_ = malloc(sizeof(SNAME)); \ \ @@ -197,7 +197,7 @@ return _heap_; \ } \ \ - FMOD void PFX##_clear(SNAME *_heap_, void (*deallocator)(V)) \ + void PFX##_clear(SNAME *_heap_, void (*deallocator)(V)) \ { \ if (deallocator) \ { \ @@ -213,7 +213,7 @@ _heap_->count = 0; \ } \ \ - FMOD void PFX##_free(SNAME *_heap_, void (*deallocator)(V)) \ + void PFX##_free(SNAME *_heap_, void (*deallocator)(V)) \ { \ if (deallocator) \ { \ @@ -228,7 +228,7 @@ free(_heap_); \ } \ \ - FMOD bool PFX##_insert(SNAME *_heap_, V element) \ + bool PFX##_insert(SNAME *_heap_, V element) \ { \ if (PFX##_full(_heap_)) \ { \ @@ -279,7 +279,7 @@ return true; \ } \ \ - FMOD bool PFX##_remove_max(SNAME *_heap_, V *result) \ + bool PFX##_remove_max(SNAME *_heap_, V *result) \ { \ if (PFX##_empty(_heap_)) \ return false; \ @@ -324,7 +324,7 @@ return true; \ } \ \ - FMOD bool PFX##_remove_min(SNAME *_heap_, V *result) \ + bool PFX##_remove_min(SNAME *_heap_, V *result) \ { \ if (PFX##_empty(_heap_)) \ return false; \ @@ -367,7 +367,7 @@ return true; \ } \ \ - FMOD bool PFX##_insert_if(SNAME *_heap_, V element, bool condition) \ + bool PFX##_insert_if(SNAME *_heap_, V element, bool condition) \ { \ if (condition) \ return PFX##_insert(_heap_, element); \ @@ -375,7 +375,7 @@ return false; \ } \ \ - FMOD bool PFX##_remove_max_if(SNAME *_heap_, V *result, bool condition) \ + bool PFX##_remove_max_if(SNAME *_heap_, V *result, bool condition) \ { \ if (condition) \ return PFX##_remove_max(_heap_, result); \ @@ -383,7 +383,7 @@ return false; \ } \ \ - FMOD bool PFX##_remove_min_if(SNAME *_heap_, V *result, bool condition) \ + bool PFX##_remove_min_if(SNAME *_heap_, V *result, bool condition) \ { \ if (condition) \ return PFX##_remove_min(_heap_, result); \ @@ -391,7 +391,7 @@ return false; \ } \ \ - FMOD bool PFX##_update_max(SNAME *_heap_, V element) \ + bool PFX##_update_max(SNAME *_heap_, V element) \ { \ if (PFX##_empty(_heap_)) \ return false; \ @@ -420,7 +420,7 @@ return true; \ } \ \ - FMOD bool PFX##_update_min(SNAME *_heap_, V element) \ + bool PFX##_update_min(SNAME *_heap_, V element) \ { \ if (PFX##_empty(_heap_)) \ return false; \ @@ -449,7 +449,7 @@ return true; \ } \ \ - FMOD bool PFX##_max(SNAME *_heap_, V *value) \ + bool PFX##_max(SNAME *_heap_, V *value) \ { \ if (PFX##_empty(_heap_)) \ return false; \ @@ -464,7 +464,7 @@ return true; \ } \ \ - FMOD bool PFX##_min(SNAME *_heap_, V *value) \ + bool PFX##_min(SNAME *_heap_, V *value) \ { \ if (PFX##_empty(_heap_)) \ return false; \ @@ -474,7 +474,7 @@ return true; \ } \ \ - FMOD bool PFX##_contains(SNAME *_heap_, V element) \ + bool PFX##_contains(SNAME *_heap_, V element) \ { \ for (size_t i = 0; i < _heap_->count; i++) \ { \ @@ -485,28 +485,28 @@ return false; \ } \ \ - FMOD bool PFX##_empty(SNAME *_heap_) \ + bool PFX##_empty(SNAME *_heap_) \ { \ return _heap_->count == 0; \ } \ \ - FMOD bool PFX##_full(SNAME *_heap_) \ + bool PFX##_full(SNAME *_heap_) \ { \ /* The heap is full if all nodes are completely filled */ \ return _heap_->size >= _heap_->capacity && _heap_->count % 2 == 0; \ } \ \ - FMOD size_t PFX##_count(SNAME *_heap_) \ + size_t PFX##_count(SNAME *_heap_) \ { \ return _heap_->count; \ } \ \ - FMOD size_t PFX##_capacity(SNAME *_heap_) \ + size_t PFX##_capacity(SNAME *_heap_) \ { \ return _heap_->capacity; \ } \ \ - FMOD SNAME *PFX##_copy_of(SNAME *_heap_, V (*copy_func)(V)) \ + SNAME *PFX##_copy_of(SNAME *_heap_, V (*copy_func)(V)) \ { \ SNAME *result = malloc(sizeof(SNAME)); \ \ @@ -534,7 +534,7 @@ return result; \ } \ \ - FMOD bool PFX##_equals(SNAME *_heap1_, SNAME *_heap2_) \ + bool PFX##_equals(SNAME *_heap1_, SNAME *_heap2_) \ { \ if (PFX##_count(_heap1_) != PFX##_count(_heap2_)) \ return false; \ @@ -551,7 +551,7 @@ return false; \ } \ \ - FMOD cmc_string PFX##_to_string(SNAME *_heap_) \ + cmc_string PFX##_to_string(SNAME *_heap_) \ { \ cmc_string str; \ SNAME *h_ = _heap_; \ @@ -563,7 +563,7 @@ return str; \ } \ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ + SNAME##_iter *PFX##_iter_new(SNAME *target) \ { \ SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ \ @@ -575,12 +575,12 @@ return iter; \ } \ \ - FMOD void PFX##_iter_free(SNAME##_iter *iter) \ + void PFX##_iter_free(SNAME##_iter *iter) \ { \ free(iter); \ } \ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ { \ iter->target = target; \ iter->cursor = 0; \ @@ -588,17 +588,17 @@ iter->end = PFX##_empty(target); \ } \ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ + bool PFX##_iter_start(SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->start; \ } \ \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ + bool PFX##_iter_end(SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->end; \ } \ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ + void PFX##_iter_to_start(SNAME##_iter *iter) \ { \ if (!PFX##_empty(iter->target)) \ { \ @@ -608,7 +608,7 @@ } \ } \ \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ + void PFX##_iter_to_end(SNAME##_iter *iter) \ { \ if (!PFX##_empty(iter->target)) \ { \ @@ -618,7 +618,7 @@ } \ } \ \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ + bool PFX##_iter_next(SNAME##_iter *iter) \ { \ if (iter->end) \ return false; \ @@ -636,7 +636,7 @@ return true; \ } \ \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ + bool PFX##_iter_prev(SNAME##_iter *iter) \ { \ if (iter->start) \ return false; \ @@ -655,7 +655,7 @@ } \ \ /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ { \ if (iter->start) \ return false; \ @@ -677,7 +677,7 @@ } \ \ /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ { \ if (iter->start) \ return false; \ @@ -699,7 +699,7 @@ } \ \ /* Returns true only if the iterator was able to be positioned at the given index */ \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ { \ if (index >= PFX##_count(iter->target)) \ return false; \ @@ -712,7 +712,7 @@ return true; \ } \ \ - FMOD V PFX##_iter_value(SNAME##_iter *iter) \ + V PFX##_iter_value(SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ return PFX##_impl_default_value(); \ @@ -720,7 +720,7 @@ return iter->target->buffer[iter->cursor / 2].data[iter->cursor % 2]; \ } \ \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ + size_t PFX##_iter_index(SNAME##_iter *iter) \ { \ return iter->cursor; \ } \ diff --git a/src/ext/multimap.h b/src/ext/multimap.h index a57114a..fe4ad52 100644 --- a/src/ext/multimap.h +++ b/src/ext/multimap.h @@ -86,1055 +86,1055 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, #endif /* CMC_HASH_TABLE_SETUP */ -#define MULTIMAP_GENERATE(PFX, SNAME, FMOD, K, V) \ - MULTIMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \ - MULTIMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) +#define CMC_GENERATE_MULTIMAP(PFX, SNAME, K, V) \ + CMC_GENERATE_MULTIMAP_HEADER(PFX, SNAME, K, V) \ + CMC_GENERATE_MULTIMAP_SOURCE(PFX, SNAME, K, V) -#define MULTIMAP_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \ - MULTIMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) +#define CMC_WRAPGEN_MULTIMAP_HEADER(PFX, SNAME, K, V) \ + CMC_GENERATE_MULTIMAP_HEADER(PFX, SNAME, K, V) -#define MULTIMAP_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \ - MULTIMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) +#define CMC_WRAPGEN_MULTIMAP_SOURCE(PFX, SNAME, K, V) \ + CMC_GENERATE_MULTIMAP_SOURCE(PFX, SNAME, K, V) /* HEADER ********************************************************************/ -#define MULTIMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \ - \ - /* Multimap Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Array of linked list to entries */ \ - struct SNAME##_entry_s *(*buffer)[2]; \ - \ - /* Current array capacity */ \ - size_t capacity; \ - \ - /* Current amount of keys */ \ - size_t count; \ - \ - /* Load factor in range (0.0, infinity) */ \ - double load; \ - \ - /* Key comparison functions */ \ - int (*cmp)(K, K); \ - \ - /* Key hash function */ \ - size_t (*hash)(K); \ - \ - /* Function that returns an iterator to the start of the multimap */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the multimap */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Multimap Entry */ \ - typedef struct SNAME##_entry_s \ - { \ - /* Entry Key */ \ - K key; \ - \ - /* Entry Value */ \ - V value; \ - \ - /* Next entry on the linked list */ \ - struct SNAME##_entry_s *next; \ - \ - /* Previous entry on the linked list */ \ - struct SNAME##_entry_s *prev; \ - \ - } SNAME##_entry, *SNAME##_entry_ptr; \ - \ - typedef struct SNAME##_iter_s \ - { \ - /* Target multimap */ \ - struct SNAME##_s *target; \ - \ - /* Current entry */ \ - struct SNAME##_entry_s *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; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - FMOD SNAME *PFX##_new(size_t capacity, double load, int (*compare)(K, K), size_t (*hash)(K)); \ - FMOD void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)); \ - FMOD void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)); \ - /* Collection Input and Output */ \ - FMOD bool PFX##_insert(SNAME *_map_, K key, V value); \ - FMOD bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value); \ - FMOD size_t PFX##_update_all(SNAME *_map_, K key, V new_value, V **old_values); \ - FMOD bool PFX##_remove(SNAME *_map_, K key, V *out_value); \ - FMOD size_t PFX##_remove_all(SNAME *_map_, K key, V **out_values); \ - /* Conditional Input and Output */ \ - FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition); \ - FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *out_value, bool condition); \ - /* Element Access */ \ - FMOD bool PFX##_max(SNAME *_map_, K *key, V *value); \ - FMOD bool PFX##_min(SNAME *_map_, K *key, V *value); \ - FMOD V PFX##_get(SNAME *_map_, K key); \ - FMOD V *PFX##_get_ref(SNAME *_map_, K key); \ - /* Collection State */ \ - FMOD bool PFX##_contains(SNAME *_map_, K key); \ - FMOD bool PFX##_empty(SNAME *_map_); \ - FMOD size_t PFX##_count(SNAME *_map_); \ - FMOD bool PFX##_key_count(SNAME *_map_, K key); \ - FMOD size_t PFX##_capacity(SNAME *_map_); \ - /* Collection Utility */ \ - FMOD SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)); \ - FMOD bool PFX##_equals(SNAME *_map1_, SNAME *_map2_, bool ignore_key_count); \ - FMOD cmc_string PFX##_to_string(SNAME *_map_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ - FMOD void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - FMOD K PFX##_iter_key(SNAME##_iter *iter); \ - FMOD V PFX##_iter_value(SNAME##_iter *iter); \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ - /* Default Key */ \ - static inline K PFX##_impl_default_key(void) \ - { \ - K _empty_key_; \ - \ - memset(&_empty_key_, 0, sizeof(K)); \ - \ - return _empty_key_; \ - } \ - \ - /* Default Value */ \ - static inline V PFX##_impl_default_value(void) \ - { \ - V _empty_value_; \ - \ - memset(&_empty_value_, 0, sizeof(V)); \ - \ - return _empty_value_; \ - } \ - \ +#define CMC_GENERATE_MULTIMAP_HEADER(PFX, SNAME, K, V) \ + \ + /* Multimap Structure */ \ + typedef struct SNAME##_s \ + { \ + /* Array of linked list to entries */ \ + struct SNAME##_entry_s *(*buffer)[2]; \ + \ + /* Current array capacity */ \ + size_t capacity; \ + \ + /* Current amount of keys */ \ + size_t count; \ + \ + /* Load factor in range (0.0, infinity) */ \ + double load; \ + \ + /* Key comparison functions */ \ + int (*cmp)(K, K); \ + \ + /* Key hash function */ \ + size_t (*hash)(K); \ + \ + /* Function that returns an iterator to the start of the multimap */ \ + struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + \ + /* Function that returns an iterator to the end of the multimap */ \ + struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + \ + } SNAME, *SNAME##_ptr; \ + \ + /* Multimap Entry */ \ + typedef struct SNAME##_entry_s \ + { \ + /* Entry Key */ \ + K key; \ + \ + /* Entry Value */ \ + V value; \ + \ + /* Next entry on the linked list */ \ + struct SNAME##_entry_s *next; \ + \ + /* Previous entry on the linked list */ \ + struct SNAME##_entry_s *prev; \ + \ + } SNAME##_entry, *SNAME##_entry_ptr; \ + \ + typedef struct SNAME##_iter_s \ + { \ + /* Target multimap */ \ + struct SNAME##_s *target; \ + \ + /* Current entry */ \ + struct SNAME##_entry_s *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; \ + \ + } SNAME##_iter, *SNAME##_iter_ptr; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + SNAME *PFX##_new(size_t capacity, double load, int (*compare)(K, K), size_t (*hash)(K)); \ + void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)); \ + void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)); \ + /* Collection Input and Output */ \ + bool PFX##_insert(SNAME *_map_, K key, V value); \ + bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value); \ + size_t PFX##_update_all(SNAME *_map_, K key, V new_value, V **old_values); \ + bool PFX##_remove(SNAME *_map_, K key, V *out_value); \ + size_t PFX##_remove_all(SNAME *_map_, K key, V **out_values); \ + /* Conditional Input and Output */ \ + bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition); \ + bool PFX##_remove_if(SNAME *_map_, K key, V *out_value, bool condition); \ + /* Element Access */ \ + bool PFX##_max(SNAME *_map_, K *key, V *value); \ + bool PFX##_min(SNAME *_map_, K *key, V *value); \ + V PFX##_get(SNAME *_map_, K key); \ + V *PFX##_get_ref(SNAME *_map_, K key); \ + /* Collection State */ \ + bool PFX##_contains(SNAME *_map_, K key); \ + bool PFX##_empty(SNAME *_map_); \ + size_t PFX##_count(SNAME *_map_); \ + bool PFX##_key_count(SNAME *_map_, K key); \ + size_t PFX##_capacity(SNAME *_map_); \ + /* Collection Utility */ \ + SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)); \ + bool PFX##_equals(SNAME *_map1_, SNAME *_map2_, bool ignore_key_count); \ + cmc_string PFX##_to_string(SNAME *_map_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + SNAME##_iter *PFX##_iter_new(SNAME *target); \ + void PFX##_iter_free(SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(SNAME##_iter *iter); \ + bool PFX##_iter_end(SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(SNAME##_iter *iter); \ + void PFX##_iter_to_end(SNAME##_iter *iter); \ + bool PFX##_iter_next(SNAME##_iter *iter); \ + bool PFX##_iter_prev(SNAME##_iter *iter); \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + K PFX##_iter_key(SNAME##_iter *iter); \ + V PFX##_iter_value(SNAME##_iter *iter); \ + V *PFX##_iter_rvalue(SNAME##_iter *iter); \ + size_t PFX##_iter_index(SNAME##_iter *iter); \ + \ + /* Default Key */ \ + static inline K PFX##_impl_default_key(void) \ + { \ + K _empty_key_; \ + \ + memset(&_empty_key_, 0, sizeof(K)); \ + \ + return _empty_key_; \ + } \ + \ + /* Default Value */ \ + static inline V PFX##_impl_default_value(void) \ + { \ + V _empty_value_; \ + \ + memset(&_empty_value_, 0, sizeof(V)); \ + \ + return _empty_value_; \ + } \ + \ /* SOURCE ********************************************************************/ -#define MULTIMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) \ - \ - /* Implementation Detail Functions */ \ - FMOD bool PFX##_impl_grow(SNAME *_map_); \ - FMOD SNAME##_entry *PFX##_impl_new_entry(K key, V value); \ - FMOD SNAME##_entry *PFX##_impl_get_entry(SNAME *_map_, K key); \ - FMOD size_t PFX##_impl_calculate_size(size_t required); \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_map_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_map_); \ - \ - FMOD SNAME *PFX##_new(size_t capacity, double load, int (*compare)(K, K), size_t (*hash)(K)) \ - { \ - if (capacity == 0 || load <= 0) \ - return NULL; \ - \ - /* Prevent integer overflow */ \ - if (capacity >= UINTMAX_MAX * load) \ - return NULL; \ - \ - size_t real_capacity = PFX##_impl_calculate_size(capacity / load); \ - \ - SNAME *_map_ = malloc(sizeof(SNAME)); \ - \ - if (!_map_) \ - return NULL; \ - \ - _map_->buffer = malloc(sizeof(SNAME##_entry_ptr[2]) * real_capacity); \ - \ - if (!_map_->buffer) \ - { \ - free(_map_); \ - return NULL; \ - } \ - \ - memset(_map_->buffer, 0, sizeof(SNAME##_entry_ptr[2]) * real_capacity); \ - \ - _map_->count = 0; \ - _map_->capacity = real_capacity; \ - _map_->load = load; \ - _map_->cmp = compare; \ - _map_->hash = hash; \ - \ - _map_->it_start = PFX##_impl_it_start; \ - _map_->it_end = PFX##_impl_it_end; \ - \ - return _map_; \ - } \ - \ - FMOD void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - size_t index = 0; \ - SNAME##_entry *scan; \ - \ - while (index < _map_->capacity) \ - { \ - scan = _map_->buffer[index][0]; \ - \ - if (scan != NULL) \ - { \ - if (scan->next == NULL && scan->prev == NULL) \ - { \ - if (deallocator) \ - deallocator(scan->key, scan->value); \ - \ - free(scan); \ - } \ - else \ - { \ - while (scan != NULL) \ - { \ - SNAME##_entry *tmp = scan; \ - \ - scan = scan->next; \ - \ - if (deallocator) \ - deallocator(tmp->key, tmp->value); \ - \ - free(tmp); \ - } \ - } \ - } \ - \ - index++; \ - } \ - \ - memset(_map_->buffer, 0, sizeof(SNAME##_entry_ptr[2]) * _map_->capacity); \ - \ - _map_->count = 0; \ - } \ - \ - FMOD void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - size_t index = 0; \ - SNAME##_entry *scan; \ - \ - while (index < _map_->capacity) \ - { \ - scan = _map_->buffer[index][0]; \ - \ - if (scan != NULL) \ - { \ - if (scan->next == NULL && scan->prev == NULL) \ - free(scan); \ - else \ - { \ - while (scan != NULL) \ - { \ - SNAME##_entry *tmp = scan; \ - \ - scan = scan->next; \ - \ - if (deallocator) \ - deallocator(tmp->key, tmp->value); \ - \ - free(tmp); \ - } \ - } \ - } \ - \ - index++; \ - } \ - \ - free(_map_->buffer); \ - free(_map_); \ - } \ - \ - FMOD bool PFX##_insert(SNAME *_map_, K key, V value) \ - { \ - if ((double)_map_->capacity * _map_->load <= (double)_map_->count) \ - { \ - if (!PFX##_impl_grow(_map_)) \ - return false; \ - } \ - \ - size_t hash = _map_->hash(key); \ - size_t pos = hash % _map_->capacity; \ - \ - SNAME##_entry *entry = PFX##_impl_new_entry(key, value); \ - \ - if (_map_->buffer[pos][0] == NULL) \ - { \ - _map_->buffer[pos][0] = entry; \ - _map_->buffer[pos][1] = entry; \ - } \ - else \ - { \ - entry->prev = _map_->buffer[pos][1]; \ - \ - _map_->buffer[pos][1]->next = entry; \ - _map_->buffer[pos][1] = entry; \ - } \ - \ - _map_->count++; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value) \ - { \ - SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ - \ - if (!entry) \ - return false; \ - \ - if (old_value) \ - *old_value = entry->value; \ - \ - entry->value = new_value; \ - \ - return false; \ - } \ - \ - FMOD size_t PFX##_update_all(SNAME *_map_, K key, V new_value, V **old_values) \ - { \ - size_t total = PFX##_key_count(_map_, key); \ - size_t index = 0; \ - \ - if (total == 0) \ - return total; \ - \ - if (old_values) \ - { \ - *old_values = malloc(sizeof(V) * total); \ - \ - if (!(*old_values)) \ - return false; \ - } \ - \ - size_t hash = _map_->hash(key); \ - \ - SNAME##_entry *entry = _map_->buffer[hash % _map_->capacity][0]; \ - \ - while (entry != NULL) \ - { \ - if (_map_->cmp(entry->key, key) == 0) \ - { \ - if (old_values) \ - (*old_values)[index++] = entry->value; \ - \ - entry->value = new_value; \ - } \ - \ - entry = entry->next; \ - } \ - \ - return index; \ - } \ - \ - FMOD bool PFX##_remove(SNAME *_map_, K key, V *out_value) \ - { \ - size_t hash = _map_->hash(key); \ - \ - SNAME##_entry **head = &(_map_->buffer[hash % _map_->capacity][0]); \ - SNAME##_entry **tail = &(_map_->buffer[hash % _map_->capacity][1]); \ - \ - if (*head == NULL) \ - return false; \ - \ - SNAME##_entry *entry = *head; \ - \ - if (entry->next == NULL && entry->prev == NULL) \ - { \ - if (_map_->cmp(entry->key, key) == 0) \ - { \ - *head = NULL; \ - *tail = NULL; \ - \ - if (out_value) \ - *out_value = entry->value; \ - } \ - else \ - return false; \ - } \ - else \ - { \ - bool found = false; \ - \ - while (entry != NULL) \ - { \ - if (_map_->cmp(entry->key, key) == 0) \ - { \ - if (*head == entry) \ - *head = entry->next; \ - if (*tail == entry) \ - *tail = entry->prev; \ - \ - if (entry->prev != NULL) \ - entry->prev->next = entry->next; \ - if (entry->next != NULL) \ - entry->next->prev = entry->prev; \ - \ - if (out_value) \ - *out_value = entry->value; \ - \ - found = true; \ - \ - break; \ - } \ - else \ - entry = entry->next; \ - } \ - \ - if (!found) \ - return false; \ - } \ - \ - free(entry); \ - \ - _map_->count--; \ - \ - return true; \ - } \ - \ - FMOD size_t PFX##_remove_all(SNAME *_map_, K key, V **out_values) \ - { \ - size_t hash = _map_->hash(key); \ - \ - SNAME##_entry **head = &(_map_->buffer[hash % _map_->capacity][0]); \ - SNAME##_entry **tail = &(_map_->buffer[hash % _map_->capacity][1]); \ - \ - if (*head == NULL) \ - return 0; \ - \ - size_t total = PFX##_key_count(_map_, key); \ - size_t index = 0; \ - \ - if (out_values) \ - *out_values = malloc(sizeof(SNAME##_entry) * total); \ - \ - SNAME##_entry *entry = *head; \ - \ - if (entry->next == NULL) \ - { \ - *head = NULL; \ - *tail = NULL; \ - \ - if (out_values) \ - (*out_values)[index++] = entry->value; \ - \ - free(entry); \ - } \ - else \ - { \ - while (entry != NULL) \ - { \ - if (_map_->cmp(entry->key, key) == 0) \ - { \ - if (*head == entry) \ - *head = entry->next; \ - if (*tail == entry) \ - *tail = entry->prev; \ - \ - SNAME##_entry *temp = entry->next; \ - \ - if (entry->prev != NULL) \ - entry->prev->next = entry->next; \ - if (entry->next != NULL) \ - entry->next->prev = entry->prev; \ - \ - if (out_values) \ - (*out_values)[index++] = entry->value; \ - \ - free(entry); \ - \ - entry = temp; \ - } \ - else \ - entry = entry->next; \ - } \ - } \ - \ - _map_->count -= index; \ - \ - return index; \ - } \ - \ - FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition) \ - { \ - if (condition) \ - return PFX##_insert(_map_, key, value); \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *out_value, bool condition) \ - { \ - if (condition) \ - return PFX##_remove(_map_, key, out_value); \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_max(SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - SNAME##_iter iter; \ - \ - for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - K result_key = PFX##_iter_key(&iter); \ - V result_value = PFX##_iter_value(&iter); \ - size_t index = PFX##_iter_index(&iter); \ - \ - if (index == 0) \ - { \ - *key = result_key; \ - *value = result_value; \ - } \ - else if (_map_->cmp(result_key, *key) > 0) \ - { \ - *key = result_key; \ - *value = result_value; \ - } \ - } \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_min(SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - SNAME##_iter iter; \ - \ - for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - K result_key = PFX##_iter_key(&iter); \ - V result_value = PFX##_iter_value(&iter); \ - size_t index = PFX##_iter_index(&iter); \ - \ - if (index == 0) \ - { \ - *key = result_key; \ - *value = result_value; \ - } \ - else if (_map_->cmp(result_key, *key) < 0) \ - { \ - *key = result_key; \ - *value = result_value; \ - } \ - } \ - \ - return true; \ - } \ - \ - FMOD V PFX##_get(SNAME *_map_, K key) \ - { \ - SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ - \ - if (!entry) \ - return PFX##_impl_default_value(); \ - \ - return entry->value; \ - } \ - \ - FMOD V *PFX##_get_ref(SNAME *_map_, K key) \ - { \ - SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ - \ - if (!entry) \ - return NULL; \ - \ - return &(entry->value); \ - } \ - \ - FMOD bool PFX##_contains(SNAME *_map_, K key) \ - { \ - return PFX##_impl_get_entry(_map_, key) != NULL; \ - } \ - \ - FMOD bool PFX##_empty(SNAME *_map_) \ - { \ - return _map_->count == 0; \ - } \ - \ - FMOD size_t PFX##_count(SNAME *_map_) \ - { \ - return _map_->count; \ - } \ - \ - FMOD bool PFX##_key_count(SNAME *_map_, K key) \ - { \ - size_t hash = _map_->hash(key); \ - \ - SNAME##_entry *entry = _map_->buffer[hash % _map_->capacity][0]; \ - \ - size_t total_count = 0; \ - \ - if (!entry) \ - return total_count; \ - \ - while (entry != NULL) \ - { \ - if (_map_->cmp(entry->key, key) == 0) \ - total_count++; \ - \ - entry = entry->next; \ - } \ - \ - return total_count; \ - } \ - \ - FMOD size_t PFX##_capacity(SNAME *_map_) \ - { \ - return _map_->capacity; \ - } \ - \ - FMOD SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)) \ - { \ - SNAME *result = PFX##_new(_map_->capacity, _map_->load, _map_->cmp, _map_->hash); \ - \ - if (!result) \ - return NULL; \ - \ - SNAME##_iter iter; \ - PFX##_iter_init(&iter, _map_); \ - \ - if (!PFX##_empty(_map_)) \ - { \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - K key = PFX##_iter_key(&iter); \ - V value = PFX##_iter_value(&iter); \ - \ - if (key_copy_func) \ - key = key_copy_func(key); \ - if (value_copy_func) \ - value = value_copy_func(value); \ - \ - PFX##_insert(result, key, value); \ - } \ - } \ - \ - return result; \ - } \ - \ - FMOD bool PFX##_equals(SNAME *_map1_, SNAME *_map2_, bool ignore_key_count) \ - { \ - if (ignore_key_count) \ - { \ - SNAME##_iter iter; \ - PFX##_iter_init(&iter, _map1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - if (PFX##_impl_get_entry(_map2_, PFX##_iter_key(&iter)) == NULL) \ - return false; \ - } \ - } \ - else \ - { \ - /* Since the key count matters this can be checked and an early exit */ \ - if (PFX##_count(_map1_) != PFX##_count(_map2_)) \ - return false; \ - \ - SNAME##_iter iter; \ - PFX##_iter_init(&iter, _map1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - K key = PFX##_iter_key(&iter); \ - \ - if (PFX##_key_count(_map1_, key) != PFX##_key_count(_map2_, key)) \ - return false; \ - } \ - } \ - \ - return true; \ - } \ - \ - FMOD cmc_string PFX##_to_string(SNAME *_map_) \ - { \ - cmc_string str; \ - SNAME *m_ = _map_; \ - const char *name = #SNAME; \ - \ - 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; \ - } \ - \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ - { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - FMOD void PFX##_iter_free(SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ - { \ - memset(iter, 0, sizeof(SNAME##_iter)); \ - \ - iter->target = target; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - \ - if (!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][0] != NULL) \ - { \ - iter->last = i - 1; \ - break; \ - } \ - } \ - } \ - } \ - \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->first; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - iter->curr_entry = iter->target->buffer[iter->first][0]; \ - } \ - } \ - \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->last; \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - iter->curr_entry = iter->target->buffer[iter->last][1]; \ - } \ - } \ - \ - FMOD bool PFX##_iter_next(SNAME##_iter *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 = PFX##_empty(iter->target); \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_iter_prev(SNAME##_iter *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 = PFX##_empty(iter->target); \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->index + 1 == PFX##_count(iter->target)) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ - return false; \ - \ - for (size_t i = 0; i < steps; i++) \ - PFX##_iter_next(iter); \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *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++) \ - PFX##_iter_prev(iter); \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator was able to be positioned at the given index */ \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ - { \ - if (index >= PFX##_count(iter->target)) \ - return false; \ - \ - if (iter->index > index) \ - return PFX##_iter_rewind(iter, iter->index - index); \ - else if (iter->index < index) \ - return PFX##_iter_advance(iter, index - iter->index); \ - \ - return true; \ - } \ - \ - FMOD K PFX##_iter_key(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return PFX##_impl_default_key(); \ - \ - return iter->curr_entry->key; \ - } \ - \ - FMOD V PFX##_iter_value(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return PFX##_impl_default_value(); \ - \ - return iter->curr_entry->value; \ - } \ - \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->curr_entry->value); \ - } \ - \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - FMOD bool PFX##_impl_grow(SNAME *_map_) \ - { \ - size_t new_capacity = PFX##_impl_calculate_size(_map_->capacity * 1.5); \ - \ - SNAME *_new_map_ = PFX##_new(new_capacity, _map_->load, _map_->cmp, _map_->hash); \ - \ - if (!_new_map_) \ - return false; \ - \ - SNAME##_iter iter; \ - \ - for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - K key = PFX##_iter_key(&iter); \ - V value = PFX##_iter_value(&iter); \ - \ - PFX##_insert(_new_map_, key, value); \ - } \ - \ - if (_map_->count != _new_map_->count) \ - { \ - PFX##_free(_new_map_, NULL); \ - return false; \ - } \ - \ - if (_map_->count != _new_map_->count) \ - { \ - PFX##_free(_new_map_, NULL); \ - \ - return false; \ - } \ - \ - SNAME##_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; \ - \ - PFX##_free(_new_map_, NULL); \ - \ - return true; \ - } \ - \ - FMOD SNAME##_entry *PFX##_impl_new_entry(K key, V value) \ - { \ - SNAME##_entry *entry = malloc(sizeof(SNAME##_entry)); \ - \ - if (!entry) \ - return NULL; \ - \ - entry->key = key; \ - entry->value = value; \ - entry->next = NULL; \ - entry->prev = NULL; \ - \ - return entry; \ - } \ - \ - FMOD SNAME##_entry *PFX##_impl_get_entry(SNAME *_map_, K key) \ - { \ - size_t hash = _map_->hash(key); \ - \ - SNAME##_entry *entry = _map_->buffer[hash % _map_->capacity][0]; \ - \ - while (entry != NULL) \ - { \ - if (_map_->cmp(entry->key, key) == 0) \ - return entry; \ - \ - entry = entry->next; \ - } \ - \ - return NULL; \ - } \ - \ - FMOD size_t PFX##_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 SNAME##_iter PFX##_impl_it_start(SNAME *_map_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _map_); \ - \ - return iter; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_map_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _map_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ +#define CMC_GENERATE_MULTIMAP_SOURCE(PFX, SNAME, K, V) \ + \ + /* Implementation Detail Functions */ \ + bool PFX##_impl_grow(SNAME *_map_); \ + SNAME##_entry *PFX##_impl_new_entry(K key, V value); \ + SNAME##_entry *PFX##_impl_get_entry(SNAME *_map_, K key); \ + size_t PFX##_impl_calculate_size(size_t required); \ + static SNAME##_iter PFX##_impl_it_start(SNAME *_map_); \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_map_); \ + \ + SNAME *PFX##_new(size_t capacity, double load, int (*compare)(K, K), size_t (*hash)(K)) \ + { \ + if (capacity == 0 || load <= 0) \ + return NULL; \ + \ + /* Prevent integer overflow */ \ + if (capacity >= UINTMAX_MAX * load) \ + return NULL; \ + \ + size_t real_capacity = PFX##_impl_calculate_size(capacity / load); \ + \ + SNAME *_map_ = malloc(sizeof(SNAME)); \ + \ + if (!_map_) \ + return NULL; \ + \ + _map_->buffer = malloc(sizeof(SNAME##_entry_ptr[2]) * real_capacity); \ + \ + if (!_map_->buffer) \ + { \ + free(_map_); \ + return NULL; \ + } \ + \ + memset(_map_->buffer, 0, sizeof(SNAME##_entry_ptr[2]) * real_capacity); \ + \ + _map_->count = 0; \ + _map_->capacity = real_capacity; \ + _map_->load = load; \ + _map_->cmp = compare; \ + _map_->hash = hash; \ + \ + _map_->it_start = PFX##_impl_it_start; \ + _map_->it_end = PFX##_impl_it_end; \ + \ + return _map_; \ + } \ + \ + void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)) \ + { \ + size_t index = 0; \ + SNAME##_entry *scan; \ + \ + while (index < _map_->capacity) \ + { \ + scan = _map_->buffer[index][0]; \ + \ + if (scan != NULL) \ + { \ + if (scan->next == NULL && scan->prev == NULL) \ + { \ + if (deallocator) \ + deallocator(scan->key, scan->value); \ + \ + free(scan); \ + } \ + else \ + { \ + while (scan != NULL) \ + { \ + SNAME##_entry *tmp = scan; \ + \ + scan = scan->next; \ + \ + if (deallocator) \ + deallocator(tmp->key, tmp->value); \ + \ + free(tmp); \ + } \ + } \ + } \ + \ + index++; \ + } \ + \ + memset(_map_->buffer, 0, sizeof(SNAME##_entry_ptr[2]) * _map_->capacity); \ + \ + _map_->count = 0; \ + } \ + \ + void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)) \ + { \ + size_t index = 0; \ + SNAME##_entry *scan; \ + \ + while (index < _map_->capacity) \ + { \ + scan = _map_->buffer[index][0]; \ + \ + if (scan != NULL) \ + { \ + if (scan->next == NULL && scan->prev == NULL) \ + free(scan); \ + else \ + { \ + while (scan != NULL) \ + { \ + SNAME##_entry *tmp = scan; \ + \ + scan = scan->next; \ + \ + if (deallocator) \ + deallocator(tmp->key, tmp->value); \ + \ + free(tmp); \ + } \ + } \ + } \ + \ + index++; \ + } \ + \ + free(_map_->buffer); \ + free(_map_); \ + } \ + \ + bool PFX##_insert(SNAME *_map_, K key, V value) \ + { \ + if ((double)_map_->capacity * _map_->load <= (double)_map_->count) \ + { \ + if (!PFX##_impl_grow(_map_)) \ + return false; \ + } \ + \ + size_t hash = _map_->hash(key); \ + size_t pos = hash % _map_->capacity; \ + \ + SNAME##_entry *entry = PFX##_impl_new_entry(key, value); \ + \ + if (_map_->buffer[pos][0] == NULL) \ + { \ + _map_->buffer[pos][0] = entry; \ + _map_->buffer[pos][1] = entry; \ + } \ + else \ + { \ + entry->prev = _map_->buffer[pos][1]; \ + \ + _map_->buffer[pos][1]->next = entry; \ + _map_->buffer[pos][1] = entry; \ + } \ + \ + _map_->count++; \ + \ + return true; \ + } \ + \ + bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value) \ + { \ + SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ + \ + if (!entry) \ + return false; \ + \ + if (old_value) \ + *old_value = entry->value; \ + \ + entry->value = new_value; \ + \ + return false; \ + } \ + \ + size_t PFX##_update_all(SNAME *_map_, K key, V new_value, V **old_values) \ + { \ + size_t total = PFX##_key_count(_map_, key); \ + size_t index = 0; \ + \ + if (total == 0) \ + return total; \ + \ + if (old_values) \ + { \ + *old_values = malloc(sizeof(V) * total); \ + \ + if (!(*old_values)) \ + return false; \ + } \ + \ + size_t hash = _map_->hash(key); \ + \ + SNAME##_entry *entry = _map_->buffer[hash % _map_->capacity][0]; \ + \ + while (entry != NULL) \ + { \ + 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 PFX##_remove(SNAME *_map_, K key, V *out_value) \ + { \ + size_t hash = _map_->hash(key); \ + \ + SNAME##_entry **head = &(_map_->buffer[hash % _map_->capacity][0]); \ + SNAME##_entry **tail = &(_map_->buffer[hash % _map_->capacity][1]); \ + \ + if (*head == NULL) \ + return false; \ + \ + SNAME##_entry *entry = *head; \ + \ + if (entry->next == NULL && entry->prev == NULL) \ + { \ + if (_map_->cmp(entry->key, key) == 0) \ + { \ + *head = NULL; \ + *tail = NULL; \ + \ + if (out_value) \ + *out_value = entry->value; \ + } \ + else \ + return false; \ + } \ + else \ + { \ + bool found = false; \ + \ + while (entry != NULL) \ + { \ + if (_map_->cmp(entry->key, key) == 0) \ + { \ + if (*head == entry) \ + *head = entry->next; \ + if (*tail == entry) \ + *tail = entry->prev; \ + \ + if (entry->prev != NULL) \ + entry->prev->next = entry->next; \ + if (entry->next != NULL) \ + entry->next->prev = entry->prev; \ + \ + if (out_value) \ + *out_value = entry->value; \ + \ + found = true; \ + \ + break; \ + } \ + else \ + entry = entry->next; \ + } \ + \ + if (!found) \ + return false; \ + } \ + \ + free(entry); \ + \ + _map_->count--; \ + \ + return true; \ + } \ + \ + size_t PFX##_remove_all(SNAME *_map_, K key, V **out_values) \ + { \ + size_t hash = _map_->hash(key); \ + \ + SNAME##_entry **head = &(_map_->buffer[hash % _map_->capacity][0]); \ + SNAME##_entry **tail = &(_map_->buffer[hash % _map_->capacity][1]); \ + \ + if (*head == NULL) \ + return 0; \ + \ + size_t total = PFX##_key_count(_map_, key); \ + size_t index = 0; \ + \ + if (out_values) \ + *out_values = malloc(sizeof(SNAME##_entry) * total); \ + \ + SNAME##_entry *entry = *head; \ + \ + if (entry->next == NULL) \ + { \ + *head = NULL; \ + *tail = NULL; \ + \ + if (out_values) \ + (*out_values)[index++] = entry->value; \ + \ + free(entry); \ + } \ + else \ + { \ + while (entry != NULL) \ + { \ + if (_map_->cmp(entry->key, key) == 0) \ + { \ + if (*head == entry) \ + *head = entry->next; \ + if (*tail == entry) \ + *tail = entry->prev; \ + \ + SNAME##_entry *temp = entry->next; \ + \ + if (entry->prev != NULL) \ + entry->prev->next = entry->next; \ + if (entry->next != NULL) \ + entry->next->prev = entry->prev; \ + \ + if (out_values) \ + (*out_values)[index++] = entry->value; \ + \ + free(entry); \ + \ + entry = temp; \ + } \ + else \ + entry = entry->next; \ + } \ + } \ + \ + _map_->count -= index; \ + \ + return index; \ + } \ + \ + bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition) \ + { \ + if (condition) \ + return PFX##_insert(_map_, key, value); \ + \ + return false; \ + } \ + \ + bool PFX##_remove_if(SNAME *_map_, K key, V *out_value, bool condition) \ + { \ + if (condition) \ + return PFX##_remove(_map_, key, out_value); \ + \ + return false; \ + } \ + \ + bool PFX##_max(SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + SNAME##_iter iter; \ + \ + for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + K result_key = PFX##_iter_key(&iter); \ + V result_value = PFX##_iter_value(&iter); \ + size_t index = PFX##_iter_index(&iter); \ + \ + if (index == 0) \ + { \ + *key = result_key; \ + *value = result_value; \ + } \ + else if (_map_->cmp(result_key, *key) > 0) \ + { \ + *key = result_key; \ + *value = result_value; \ + } \ + } \ + \ + return true; \ + } \ + \ + bool PFX##_min(SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + SNAME##_iter iter; \ + \ + for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + K result_key = PFX##_iter_key(&iter); \ + V result_value = PFX##_iter_value(&iter); \ + size_t index = PFX##_iter_index(&iter); \ + \ + if (index == 0) \ + { \ + *key = result_key; \ + *value = result_value; \ + } \ + else if (_map_->cmp(result_key, *key) < 0) \ + { \ + *key = result_key; \ + *value = result_value; \ + } \ + } \ + \ + return true; \ + } \ + \ + V PFX##_get(SNAME *_map_, K key) \ + { \ + SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ + \ + if (!entry) \ + return PFX##_impl_default_value(); \ + \ + return entry->value; \ + } \ + \ + V *PFX##_get_ref(SNAME *_map_, K key) \ + { \ + SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ + \ + if (!entry) \ + return NULL; \ + \ + return &(entry->value); \ + } \ + \ + bool PFX##_contains(SNAME *_map_, K key) \ + { \ + return PFX##_impl_get_entry(_map_, key) != NULL; \ + } \ + \ + bool PFX##_empty(SNAME *_map_) \ + { \ + return _map_->count == 0; \ + } \ + \ + size_t PFX##_count(SNAME *_map_) \ + { \ + return _map_->count; \ + } \ + \ + bool PFX##_key_count(SNAME *_map_, K key) \ + { \ + size_t hash = _map_->hash(key); \ + \ + SNAME##_entry *entry = _map_->buffer[hash % _map_->capacity][0]; \ + \ + size_t total_count = 0; \ + \ + if (!entry) \ + return total_count; \ + \ + while (entry != NULL) \ + { \ + if (_map_->cmp(entry->key, key) == 0) \ + total_count++; \ + \ + entry = entry->next; \ + } \ + \ + return total_count; \ + } \ + \ + size_t PFX##_capacity(SNAME *_map_) \ + { \ + return _map_->capacity; \ + } \ + \ + SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)) \ + { \ + SNAME *result = PFX##_new(_map_->capacity, _map_->load, _map_->cmp, _map_->hash); \ + \ + if (!result) \ + return NULL; \ + \ + SNAME##_iter iter; \ + PFX##_iter_init(&iter, _map_); \ + \ + if (!PFX##_empty(_map_)) \ + { \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + K key = PFX##_iter_key(&iter); \ + V value = PFX##_iter_value(&iter); \ + \ + if (key_copy_func) \ + key = key_copy_func(key); \ + if (value_copy_func) \ + value = value_copy_func(value); \ + \ + PFX##_insert(result, key, value); \ + } \ + } \ + \ + return result; \ + } \ + \ + bool PFX##_equals(SNAME *_map1_, SNAME *_map2_, bool ignore_key_count) \ + { \ + if (ignore_key_count) \ + { \ + SNAME##_iter iter; \ + PFX##_iter_init(&iter, _map1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + if (PFX##_impl_get_entry(_map2_, PFX##_iter_key(&iter)) == NULL) \ + return false; \ + } \ + } \ + else \ + { \ + /* Since the key count matters this can be checked and an early exit */ \ + if (PFX##_count(_map1_) != PFX##_count(_map2_)) \ + return false; \ + \ + SNAME##_iter iter; \ + PFX##_iter_init(&iter, _map1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + K key = PFX##_iter_key(&iter); \ + \ + if (PFX##_key_count(_map1_, key) != PFX##_key_count(_map2_, key)) \ + return false; \ + } \ + } \ + \ + return true; \ + } \ + \ + cmc_string PFX##_to_string(SNAME *_map_) \ + { \ + cmc_string str; \ + SNAME *m_ = _map_; \ + const char *name = #SNAME; \ + \ + 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; \ + } \ + \ + SNAME##_iter *PFX##_iter_new(SNAME *target) \ + { \ + SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + void PFX##_iter_free(SNAME##_iter *iter) \ + { \ + free(iter); \ + } \ + \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + { \ + memset(iter, 0, sizeof(SNAME##_iter)); \ + \ + iter->target = target; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + \ + if (!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][0] != NULL) \ + { \ + iter->last = i - 1; \ + break; \ + } \ + } \ + } \ + } \ + \ + bool PFX##_iter_start(SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + bool PFX##_iter_end(SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + void PFX##_iter_to_start(SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->first; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + iter->curr_entry = iter->target->buffer[iter->first][0]; \ + } \ + } \ + \ + void PFX##_iter_to_end(SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->last; \ + iter->index = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + iter->curr_entry = iter->target->buffer[iter->last][1]; \ + } \ + } \ + \ + bool PFX##_iter_next(SNAME##_iter *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 = PFX##_empty(iter->target); \ + \ + return true; \ + } \ + \ + bool PFX##_iter_prev(SNAME##_iter *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 = PFX##_empty(iter->target); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->index + 1 == PFX##_count(iter->target)) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ + return false; \ + \ + for (size_t i = 0; i < steps; i++) \ + PFX##_iter_next(iter); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool PFX##_iter_rewind(SNAME##_iter *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++) \ + PFX##_iter_prev(iter); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator was able to be positioned at the given index */ \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + { \ + if (index >= PFX##_count(iter->target)) \ + return false; \ + \ + if (iter->index > index) \ + return PFX##_iter_rewind(iter, iter->index - index); \ + else if (iter->index < index) \ + return PFX##_iter_advance(iter, index - iter->index); \ + \ + return true; \ + } \ + \ + K PFX##_iter_key(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return PFX##_impl_default_key(); \ + \ + return iter->curr_entry->key; \ + } \ + \ + V PFX##_iter_value(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return PFX##_impl_default_value(); \ + \ + return iter->curr_entry->value; \ + } \ + \ + V *PFX##_iter_rvalue(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return NULL; \ + \ + return &(iter->curr_entry->value); \ + } \ + \ + size_t PFX##_iter_index(SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + bool PFX##_impl_grow(SNAME *_map_) \ + { \ + size_t new_capacity = PFX##_impl_calculate_size(_map_->capacity * 1.5); \ + \ + SNAME *_new_map_ = PFX##_new(new_capacity, _map_->load, _map_->cmp, _map_->hash); \ + \ + if (!_new_map_) \ + return false; \ + \ + SNAME##_iter iter; \ + \ + for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + K key = PFX##_iter_key(&iter); \ + V value = PFX##_iter_value(&iter); \ + \ + PFX##_insert(_new_map_, key, value); \ + } \ + \ + if (_map_->count != _new_map_->count) \ + { \ + PFX##_free(_new_map_, NULL); \ + return false; \ + } \ + \ + if (_map_->count != _new_map_->count) \ + { \ + PFX##_free(_new_map_, NULL); \ + \ + return false; \ + } \ + \ + SNAME##_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; \ + \ + PFX##_free(_new_map_, NULL); \ + \ + return true; \ + } \ + \ + SNAME##_entry *PFX##_impl_new_entry(K key, V value) \ + { \ + SNAME##_entry *entry = malloc(sizeof(SNAME##_entry)); \ + \ + if (!entry) \ + return NULL; \ + \ + entry->key = key; \ + entry->value = value; \ + entry->next = NULL; \ + entry->prev = NULL; \ + \ + return entry; \ + } \ + \ + SNAME##_entry *PFX##_impl_get_entry(SNAME *_map_, K key) \ + { \ + size_t hash = _map_->hash(key); \ + \ + SNAME##_entry *entry = _map_->buffer[hash % _map_->capacity][0]; \ + \ + while (entry != NULL) \ + { \ + if (_map_->cmp(entry->key, key) == 0) \ + return entry; \ + \ + entry = entry->next; \ + } \ + \ + return NULL; \ + } \ + \ + size_t PFX##_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 SNAME##_iter PFX##_impl_it_start(SNAME *_map_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _map_); \ + \ + return iter; \ + } \ + \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_map_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _map_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_MULTIMAP_H */ diff --git a/src/ext/multiset.h b/src/ext/multiset.h index e15cfdf..20cf699 100644 --- a/src/ext/multiset.h +++ b/src/ext/multiset.h @@ -71,168 +71,168 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, #endif /* CMC_HASH_TABLE_SETUP */ -#define MULTISET_GENERATE(PFX, SNAME, FMOD, V) \ - MULTISET_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - MULTISET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) +#define CMC_GENERATE_MULTISET(PFX, SNAME, V) \ + CMC_GENERATE_MULTISET_HEADER(PFX, SNAME, V) \ + CMC_GENERATE_MULTISET_SOURCE(PFX, SNAME, V) -#define MULTISET_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \ - MULTISET_GENERATE_HEADER(PFX, SNAME, FMOD, V) +#define CMC_WRAPGEN_MULTISET_HEADER(PFX, SNAME, K, V) \ + CMC_GENERATE_MULTISET_HEADER(PFX, SNAME, V) -#define MULTISET_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \ - MULTISET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) +#define CMC_WRAPGEN_MULTISET_SOURCE(PFX, SNAME, K, V) \ + CMC_GENERATE_MULTISET_SOURCE(PFX, SNAME, V) /* HEADER ********************************************************************/ -#define MULTISET_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - \ - /* Hashset Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Array of Entries */ \ - struct SNAME##_entry_s *buffer; \ - \ - /* Current Array Capcity */ \ - size_t capacity; \ - \ - /* Current amount of unique elements */ \ - size_t count; \ - \ - /* Total amount of elements taking into account their multiplicity */ \ - size_t cardinality; \ - \ - /* Load factor in range (0.0, 1.0) */ \ - double load; \ - \ - /* Element comparison function */ \ - int (*cmp)(V, V); \ - \ - /* Element hash function */ \ - size_t (*hash)(V); \ - \ - /* Function that returns an iterator to the start of the hashset */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the hashset */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - typedef struct SNAME##_entry_s \ - { \ - /* Entry element */ \ - V value; \ - \ - /* The element's multiplicity */ \ - size_t multiplicity; \ - \ - /* 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_e state; \ - \ - } SNAME##_entry, *SNAME##_entry_ptr; \ - \ - /* Hashset Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target Hashset */ \ - struct SNAME##_s *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; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - FMOD SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), size_t (*hash)(V)); \ - FMOD void PFX##_clear(SNAME *_set_, void (*deallocator)(V)); \ - FMOD void PFX##_free(SNAME *_set_, void (*deallocator)(V)); \ - /* Collection Input and Output */ \ - FMOD bool PFX##_insert(SNAME *_set_, V element); \ - FMOD bool PFX##_insert_many(SNAME *_set_, V element, size_t count); \ - FMOD bool PFX##_update(SNAME *_set_, V element, size_t multiplicity); \ - FMOD bool PFX##_remove(SNAME *_set_, V element); \ - FMOD size_t PFX##_remove_all(SNAME *_set_, V element); \ - /* Conditional Input and Output */ \ - FMOD bool PFX##_insert_if(SNAME *_set_, V element, bool condition); \ - FMOD bool PFX##_remove_if(SNAME *_set_, V element, bool condition); \ - /* Element Access */ \ - FMOD bool PFX##_max(SNAME *_set_, V *value); \ - FMOD bool PFX##_min(SNAME *_set_, V *value); \ - FMOD size_t PFX##_multiplicity_of(SNAME *_set_, V element); \ - /* Collection State */ \ - FMOD bool PFX##_contains(SNAME *_set_, V element); \ - FMOD bool PFX##_empty(SNAME *_set_); \ - FMOD size_t PFX##_count(SNAME *_set_); \ - FMOD size_t PFX##_cardinality(SNAME *_set_); \ - FMOD size_t PFX##_capacity(SNAME *_set_); \ - /* Collection Utility */ \ - FMOD SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)); \ - FMOD bool PFX##_equals(SNAME *_set1_, SNAME *_set2_, bool ignore_multiplicity); \ - FMOD cmc_string PFX##_to_string(SNAME *_set_); \ - \ - /* Set Operations */ \ - FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_); \ - FMOD SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_); \ - FMOD SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_); \ - FMOD SNAME *PFX##_summation(SNAME *_set1_, SNAME *_set2_); \ - FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_); \ - FMOD bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_); \ - FMOD bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_); \ - FMOD bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_); \ - FMOD bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_); \ - FMOD bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ - FMOD void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - FMOD V PFX##_iter_value(SNAME##_iter *iter); \ - FMOD size_t PFX##_iter_multiplicity(SNAME##_iter *iter); \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ - /* Default Value */ \ - static inline V PFX##_impl_default_value(void) \ - { \ - V _empty_value_; \ - \ - memset(&_empty_value_, 0, sizeof(V)); \ - \ - return _empty_value_; \ - } \ - \ +#define CMC_GENERATE_MULTISET_HEADER(PFX, SNAME, V) \ + \ + /* Hashset Structure */ \ + typedef struct SNAME##_s \ + { \ + /* Array of Entries */ \ + struct SNAME##_entry_s *buffer; \ + \ + /* Current Array Capcity */ \ + size_t capacity; \ + \ + /* Current amount of unique elements */ \ + size_t count; \ + \ + /* Total amount of elements taking into account their multiplicity */ \ + size_t cardinality; \ + \ + /* Load factor in range (0.0, 1.0) */ \ + double load; \ + \ + /* Element comparison function */ \ + int (*cmp)(V, V); \ + \ + /* Element hash function */ \ + size_t (*hash)(V); \ + \ + /* Function that returns an iterator to the start of the hashset */ \ + struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + \ + /* Function that returns an iterator to the end of the hashset */ \ + struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + \ + } SNAME, *SNAME##_ptr; \ + \ + typedef struct SNAME##_entry_s \ + { \ + /* Entry element */ \ + V value; \ + \ + /* The element's multiplicity */ \ + size_t multiplicity; \ + \ + /* 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_e state; \ + \ + } SNAME##_entry, *SNAME##_entry_ptr; \ + \ + /* Hashset Iterator */ \ + typedef struct SNAME##_iter_s \ + { \ + /* Target Hashset */ \ + struct SNAME##_s *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; \ + \ + } SNAME##_iter, *SNAME##_iter_ptr; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), size_t (*hash)(V)); \ + void PFX##_clear(SNAME *_set_, void (*deallocator)(V)); \ + void PFX##_free(SNAME *_set_, void (*deallocator)(V)); \ + /* Collection Input and Output */ \ + bool PFX##_insert(SNAME *_set_, V element); \ + bool PFX##_insert_many(SNAME *_set_, V element, size_t count); \ + bool PFX##_update(SNAME *_set_, V element, size_t multiplicity); \ + bool PFX##_remove(SNAME *_set_, V element); \ + size_t PFX##_remove_all(SNAME *_set_, V element); \ + /* Conditional Input and Output */ \ + bool PFX##_insert_if(SNAME *_set_, V element, bool condition); \ + bool PFX##_remove_if(SNAME *_set_, V element, bool condition); \ + /* Element Access */ \ + bool PFX##_max(SNAME *_set_, V *value); \ + bool PFX##_min(SNAME *_set_, V *value); \ + size_t PFX##_multiplicity_of(SNAME *_set_, V element); \ + /* Collection State */ \ + bool PFX##_contains(SNAME *_set_, V element); \ + bool PFX##_empty(SNAME *_set_); \ + size_t PFX##_count(SNAME *_set_); \ + size_t PFX##_cardinality(SNAME *_set_); \ + size_t PFX##_capacity(SNAME *_set_); \ + /* Collection Utility */ \ + SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)); \ + bool PFX##_equals(SNAME *_set1_, SNAME *_set2_, bool ignore_multiplicity); \ + cmc_string PFX##_to_string(SNAME *_set_); \ + \ + /* Set Operations */ \ + SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_); \ + SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_); \ + SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_); \ + SNAME *PFX##_summation(SNAME *_set1_, SNAME *_set2_); \ + SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_); \ + bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_); \ + bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_); \ + bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_); \ + bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_); \ + bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + SNAME##_iter *PFX##_iter_new(SNAME *target); \ + void PFX##_iter_free(SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(SNAME##_iter *iter); \ + bool PFX##_iter_end(SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(SNAME##_iter *iter); \ + void PFX##_iter_to_end(SNAME##_iter *iter); \ + bool PFX##_iter_next(SNAME##_iter *iter); \ + bool PFX##_iter_prev(SNAME##_iter *iter); \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + V PFX##_iter_value(SNAME##_iter *iter); \ + size_t PFX##_iter_multiplicity(SNAME##_iter *iter); \ + size_t PFX##_iter_index(SNAME##_iter *iter); \ + \ + /* Default Value */ \ + static inline V PFX##_impl_default_value(void) \ + { \ + V _empty_value_; \ + \ + memset(&_empty_value_, 0, sizeof(V)); \ + \ + return _empty_value_; \ + } \ + \ /* SOURCE ********************************************************************/ -#define MULTISET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ +#define CMC_GENERATE_MULTISET_SOURCE(PFX, SNAME, V) \ \ /* Implementation Detail Functions */ \ static SNAME##_entry *PFX##_impl_insert_and_return(SNAME *_set_, V element, bool *new_node); \ @@ -242,7 +242,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, static SNAME##_iter PFX##_impl_it_start(SNAME *_set_); \ static SNAME##_iter PFX##_impl_it_end(SNAME *_set_); \ \ - FMOD SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), size_t (*hash)(V)) \ + SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), size_t (*hash)(V)) \ { \ if (capacity == 0 || load <= 0 || load >= 1) \ return NULL; \ @@ -281,7 +281,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return _set_; \ } \ \ - FMOD void PFX##_clear(SNAME *_set_, void (*deallocator)(V)) \ + void PFX##_clear(SNAME *_set_, void (*deallocator)(V)) \ { \ if (deallocator) \ { \ @@ -301,7 +301,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, _set_->count = 0; \ } \ \ - FMOD void PFX##_free(SNAME *_set_, void (*deallocator)(V)) \ + void PFX##_free(SNAME *_set_, void (*deallocator)(V)) \ { \ if (deallocator) \ { \ @@ -320,7 +320,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, free(_set_); \ } \ \ - FMOD bool PFX##_insert(SNAME *_set_, V element) \ + bool PFX##_insert(SNAME *_set_, V element) \ { \ bool new_node; \ \ @@ -337,7 +337,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - FMOD bool PFX##_insert_many(SNAME *_set_, V element, size_t count) \ + bool PFX##_insert_many(SNAME *_set_, V element, size_t count) \ { \ if (count == 0) \ return true; \ @@ -359,7 +359,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - FMOD bool PFX##_update(SNAME *_set_, V element, size_t multiplicity) \ + bool PFX##_update(SNAME *_set_, V element, size_t multiplicity) \ { \ if (multiplicity == 0) \ return PFX##_remove_all(_set_, element); \ @@ -381,7 +381,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - FMOD bool PFX##_remove(SNAME *_set_, V element) \ + bool PFX##_remove(SNAME *_set_, V element) \ { \ SNAME##_entry *result = PFX##_impl_get_entry(_set_, element); \ \ @@ -405,7 +405,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - FMOD size_t PFX##_remove_all(SNAME *_set_, V element) \ + size_t PFX##_remove_all(SNAME *_set_, V element) \ { \ SNAME##_entry *result = PFX##_impl_get_entry(_set_, element); \ \ @@ -425,7 +425,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return removed; \ } \ \ - FMOD bool PFX##_insert_if(SNAME *_set_, V element, bool condition) \ + bool PFX##_insert_if(SNAME *_set_, V element, bool condition) \ { \ if (condition) \ return PFX##_insert(_set_, element); \ @@ -433,7 +433,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return false; \ } \ \ - FMOD bool PFX##_remove_if(SNAME *_set_, V element, bool condition) \ + bool PFX##_remove_if(SNAME *_set_, V element, bool condition) \ { \ if (condition) \ return PFX##_remove(_set_, element); \ @@ -441,7 +441,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return false; \ } \ \ - FMOD bool PFX##_max(SNAME *_set_, V *value) \ + bool PFX##_max(SNAME *_set_, V *value) \ { \ if (PFX##_empty(_set_)) \ return false; \ @@ -462,7 +462,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - FMOD bool PFX##_min(SNAME *_set_, V *value) \ + bool PFX##_min(SNAME *_set_, V *value) \ { \ if (PFX##_empty(_set_)) \ return false; \ @@ -483,7 +483,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - FMOD size_t PFX##_multiplicity_of(SNAME *_set_, V element) \ + size_t PFX##_multiplicity_of(SNAME *_set_, V element) \ { \ SNAME##_entry *entry = PFX##_impl_get_entry(_set_, element); \ \ @@ -493,32 +493,32 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return entry->multiplicity; \ } \ \ - FMOD bool PFX##_contains(SNAME *_set_, V element) \ + bool PFX##_contains(SNAME *_set_, V element) \ { \ return PFX##_impl_get_entry(_set_, element) != NULL; \ } \ \ - FMOD bool PFX##_empty(SNAME *_set_) \ + bool PFX##_empty(SNAME *_set_) \ { \ return _set_->count == 0; \ } \ \ - FMOD size_t PFX##_count(SNAME *_set_) \ + size_t PFX##_count(SNAME *_set_) \ { \ return _set_->count; \ } \ \ - FMOD size_t PFX##_cardinality(SNAME *_set_) \ + size_t PFX##_cardinality(SNAME *_set_) \ { \ return _set_->cardinality; \ } \ \ - FMOD size_t PFX##_capacity(SNAME *_set_) \ + size_t PFX##_capacity(SNAME *_set_) \ { \ return _set_->capacity; \ } \ \ - FMOD SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)) \ + SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)) \ { \ SNAME *result = PFX##_new(_set_->capacity, _set_->load, _set_->cmp, _set_->hash); \ \ @@ -557,7 +557,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return result; \ } \ \ - FMOD bool PFX##_equals(SNAME *_set1_, SNAME *_set2_, bool ignore_multiplicity) \ + bool PFX##_equals(SNAME *_set1_, SNAME *_set2_, bool ignore_multiplicity) \ { \ if (PFX##_count(_set1_) != PFX##_count(_set2_)) \ return false; \ @@ -585,7 +585,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - FMOD cmc_string PFX##_to_string(SNAME *_set_) \ + cmc_string PFX##_to_string(SNAME *_set_) \ { \ cmc_string str; \ SNAME *s_ = _set_; \ @@ -597,7 +597,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return str; \ } \ \ - FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_) \ + SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_) \ { \ SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ \ @@ -633,7 +633,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return _set_r_; \ } \ \ - FMOD SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_) \ + SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_) \ { \ SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ \ @@ -660,7 +660,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return _set_r_; \ } \ \ - FMOD SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_) \ + SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_) \ { \ SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ \ @@ -684,7 +684,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return _set_r_; \ } \ \ - FMOD SNAME *PFX##_summation(SNAME *_set1_, SNAME *_set2_) \ + SNAME *PFX##_summation(SNAME *_set1_, SNAME *_set2_) \ { \ SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ \ @@ -708,7 +708,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return _set_r_; \ } \ \ - FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_) \ + SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_) \ { \ SNAME##_iter iter1, iter2; \ \ @@ -755,7 +755,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return _set_r_; \ } \ \ - FMOD bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_) \ + bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_) \ { \ if (PFX##_count(_set1_) > PFX##_count(_set2_)) \ return false; \ @@ -781,12 +781,12 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - FMOD bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_) \ + bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_) \ { \ return PFX##_is_subset(_set2_, _set1_); \ } \ \ - FMOD bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_) \ + bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_) \ { \ if (PFX##_count(_set1_) >= PFX##_count(_set2_)) \ return false; \ @@ -817,12 +817,12 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - FMOD bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_) \ + bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_) \ { \ return PFX##_is_proper_subset(_set2_, _set1_); \ } \ \ - FMOD bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_) \ + bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_) \ { \ if (PFX##_empty(_set1_)) \ return true; \ @@ -842,7 +842,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ + SNAME##_iter *PFX##_iter_new(SNAME *target) \ { \ SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ \ @@ -854,12 +854,12 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return iter; \ } \ \ - FMOD void PFX##_iter_free(SNAME##_iter *iter) \ + void PFX##_iter_free(SNAME##_iter *iter) \ { \ free(iter); \ } \ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ { \ memset(iter, 0, sizeof(SNAME##_iter)); \ \ @@ -891,17 +891,17 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, } \ } \ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ + bool PFX##_iter_start(SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->start; \ } \ \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ + bool PFX##_iter_end(SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->end; \ } \ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ + void PFX##_iter_to_start(SNAME##_iter *iter) \ { \ if (!PFX##_empty(iter->target)) \ { \ @@ -912,7 +912,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, } \ } \ \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ + void PFX##_iter_to_end(SNAME##_iter *iter) \ { \ if (!PFX##_empty(iter->target)) \ { \ @@ -923,7 +923,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, } \ } \ \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ + bool PFX##_iter_next(SNAME##_iter *iter) \ { \ if (iter->end) \ return false; \ @@ -952,7 +952,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ + bool PFX##_iter_prev(SNAME##_iter *iter) \ { \ if (iter->start) \ return false; \ @@ -982,7 +982,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, } \ \ /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ { \ if (iter->end) \ return false; \ @@ -1003,7 +1003,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, } \ \ /* Returns true only if the iterator moved */ \ - FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ { \ if (iter->start) \ return false; \ @@ -1024,7 +1024,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, } \ \ /* Returns true only if the iterator was able to be positioned at the given index */ \ - FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ { \ if (index >= PFX##_count(iter->target)) \ return false; \ @@ -1037,7 +1037,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - FMOD V PFX##_iter_value(SNAME##_iter *iter) \ + V PFX##_iter_value(SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ return PFX##_impl_default_value(); \ @@ -1045,7 +1045,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return iter->target->buffer[iter->cursor].value; \ } \ \ - FMOD size_t PFX##_iter_multiplicity(SNAME##_iter *iter) \ + size_t PFX##_iter_multiplicity(SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ return 0; \ @@ -1053,7 +1053,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return iter->target->buffer[iter->cursor].multiplicity; \ } \ \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ + size_t PFX##_iter_index(SNAME##_iter *iter) \ { \ return iter->index; \ } \ diff --git a/src/macro_collections.h b/src/macro_collections.h index 1dfdea9..2607d9b 100644 --- a/src/macro_collections.h +++ b/src/macro_collections.h @@ -8,26 +8,24 @@ * */ -#ifndef CMC_MACRO_COLLECTIONS -#define CMC_MACRO_COLLECTIONS +#ifndef CMC_MACRO_COLLECTIONS_H +#define CMC_MACRO_COLLECTIONS_H -#define CMC_CONCATH_(C) C##_WRAPGEN_HEADER -#define CMC_CONCATC_(C) C##_WRAPGEN_SOURCE +#define CMC_CONCATH_(C) CMC_WRAPGEN_##C##_HEADER +#define CMC_CONCATC_(C) CMC_WRAPGEN_##C##_SOURCE #define CMC_CONCATH(C) CMC_CONCATH_(C) #define CMC_CONCATC(C) CMC_CONCATC_(C) -#define COLLECTION_GENERATE(C, PFX, SNAME, FMOD, K, V) \ - COLLECTION_GENERATE_HEADER(C, PFX, SNAME, FMOD, K, V) \ - COLLECTION_GENERATE_SOURCE(C, PFX, SNAME, FMOD, K, V) +#define CMC_COLLECTION_GENERATE(C, PFX, SNAME, K, V) \ + CMC_COLLECTION_GENERATE_HEADER(C, PFX, SNAME, K, V) \ + CMC_COLLECTION_GENERATE_SOURCE(C, PFX, SNAME, K, V) -#define COLLECTION_GENERATE_HEADER(C, PFX, SNAME, FMOD, K, V) \ - CMC_CONCATH(C) \ - (PFX, SNAME, FMOD, K, V) +#define CMC_COLLECTION_GENERATE_HEADER(C, PFX, SNAME, K, V) \ + CMC_CONCATH(C)(PFX, SNAME, K, V) -#define COLLECTION_GENERATE_SOURCE(C, PFX, SNAME, FMOD, K, V) \ - CMC_CONCATC(C) \ - (PFX, SNAME, FMOD, K, V) +#define CMC_COLLECTION_GENERATE_SOURCE(C, PFX, SNAME, K, V) \ + CMC_CONCATC(C)(PFX, SNAME, K, V) #include "cmc/deque.h" #include "cmc/hashmap.h" @@ -53,4 +51,4 @@ #include "utl/test.h" #include "utl/timer.h" -#endif /* CMC_MACRO_COLLECTIONS */ +#endif /* CMC_MACRO_COLLECTIONS_H */ diff --git a/src/utl/foreach.h b/src/utl/foreach.h index f9c1b6d..5a8cd21 100644 --- a/src/utl/foreach.h +++ b/src/utl/foreach.h @@ -8,31 +8,25 @@ * */ -/** - * ForEach utility - * - * Read Documentation.md for more information - */ +#ifndef CMC_FOR_EACH_H +#define CMC_FOR_EACH_H -#ifndef CMC_FOR_EACH -#define CMC_FOR_EACH - -#define FOR_EACH(PFX, SNAME, TARGET, BODY) \ - do \ - { \ - for (SNAME##_iter iter = TARGET->it_start(TARGET); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - BODY; \ - } \ +#define CMC_FOR_EACH(PFX, SNAME, TARGET, BODY) \ + do \ + { \ + for (SNAME##_iter iter = (TARGET)->it_start(TARGET); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + BODY; \ + } \ } while (0) -#define FOR_EACH_REV(PFX, SNAME, TARGET, BODY) \ - do \ - { \ - for (SNAME##_iter iter = TARGET->it_end(TARGET); !PFX##_iter_start(&iter); PFX##_iter_prev(&iter)) \ - { \ - BODY; \ - } \ +#define CMC_FOR_EACH_REV(PFX, SNAME, TARGET, BODY) \ + do \ + { \ + for (SNAME##_iter iter = (TARGET)->it_end(TARGET); !PFX##_iter_start(&iter); PFX##_iter_prev(&iter)) \ + { \ + BODY; \ + } \ } while (0) -#endif /* CMC_FOR_EACH */ +#endif /* CMC_FOR_EACH_H */ diff --git a/tests/contains.c b/tests/contains.c index 5bb4218..4a40a3e 100644 --- a/tests/contains.c +++ b/tests/contains.c @@ -20,20 +20,20 @@ size_t inthash(int t) return a; } -COLLECTION_GENERATE(LIST, l, list, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(STACK, s, stack, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(QUEUE, q, queue, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(DEQUE, d, deque, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(LINKEDLIST, ll, linked, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(HEAP, h, heap, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(TREESET, ts, tset, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(TREEMAP, tm, tmap, /* FMOD */, int, int) -COLLECTION_GENERATE(HASHSET, hs, hset, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(HASHMAP, hm, hmap, /* FMOD */, int, int) +CMC_COLLECTION_GENERATE(LIST, l, list, /* K */, int) +CMC_COLLECTION_GENERATE(STACK, s, stack, /* K */, int) +CMC_COLLECTION_GENERATE(QUEUE, q, queue, /* K */, int) +CMC_COLLECTION_GENERATE(DEQUE, d, deque, /* K */, int) +CMC_COLLECTION_GENERATE(LINKEDLIST, ll, linked, /* K */, int) +CMC_COLLECTION_GENERATE(HEAP, h, heap, /* K */, int) +CMC_COLLECTION_GENERATE(TREESET, ts, tset, /* K */, int) +CMC_COLLECTION_GENERATE(TREEMAP, tm, tmap, int, int) +CMC_COLLECTION_GENERATE(HASHSET, hs, hset, /* K */, int) +CMC_COLLECTION_GENERATE(HASHMAP, hm, hmap, int, int) -COLLECTION_GENERATE(INTERVALHEAP, ih, iheap, /* FMOD */, , int) -COLLECTION_GENERATE(MULTIMAP, mm, mmap, /* FMOD */, int, int) -COLLECTION_GENERATE(MULTISET, ms, mset, , , int) +CMC_COLLECTION_GENERATE(INTERVALHEAP, ih, iheap, , int) +CMC_COLLECTION_GENERATE(MULTIMAP, mm, mmap, int, int) +CMC_COLLECTION_GENERATE(MULTISET, ms, mset, , int) int main(void) { diff --git a/tests/foreach.c b/tests/foreach.c index 9b9c266..02db0a4 100644 --- a/tests/foreach.c +++ b/tests/foreach.c @@ -20,20 +20,20 @@ size_t inthash(int t) return a; } -COLLECTION_GENERATE(LIST, l, list, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(STACK, s, stack, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(QUEUE, q, queue, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(DEQUE, d, deque, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(LINKEDLIST, ll, linked, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(HEAP, h, heap, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(TREESET, ts, tset, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(TREEMAP, tm, tmap, /* FMOD */, int, int) -COLLECTION_GENERATE(HASHSET, hs, hset, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(HASHMAP, hm, hmap, /* FMOD */, int, int) +CMC_COLLECTION_GENERATE(LIST, l, list, /* K */, int) +CMC_COLLECTION_GENERATE(STACK, s, stack, /* K */, int) +CMC_COLLECTION_GENERATE(QUEUE, q, queue, /* K */, int) +CMC_COLLECTION_GENERATE(DEQUE, d, deque, /* K */, int) +CMC_COLLECTION_GENERATE(LINKEDLIST, ll, linked, /* K */, int) +CMC_COLLECTION_GENERATE(HEAP, h, heap, /* K */, int) +CMC_COLLECTION_GENERATE(TREESET, ts, tset, /* K */, int) +CMC_COLLECTION_GENERATE(TREEMAP, tm, tmap, int, int) +CMC_COLLECTION_GENERATE(HASHSET, hs, hset, /* K */, int) +CMC_COLLECTION_GENERATE(HASHMAP, hm, hmap, int, int) -COLLECTION_GENERATE(INTERVALHEAP, ih, iheap, /* FMOD */, , int) -COLLECTION_GENERATE(MULTIMAP, mm, mmap, /* FMOD */, int, int) -COLLECTION_GENERATE(MULTISET, ms, mset, , , int) +CMC_COLLECTION_GENERATE(INTERVALHEAP, ih, iheap, , int) +CMC_COLLECTION_GENERATE(MULTIMAP, mm, mmap, int, int) +CMC_COLLECTION_GENERATE(MULTISET, ms, mset, , int) int main(void) { @@ -84,62 +84,62 @@ int main(void) int sums[16] = {0}; - FOR_EACH(d, deque, d, { + CMC_FOR_EACH(d, deque, d, { sums[0] += d_iter_value(&iter); }); - FOR_EACH(hm, hmap, hm, { + CMC_FOR_EACH(hm, hmap, hm, { sums[1] += hm_iter_key(&iter); sums[2] += hm_iter_value(&iter); }); - FOR_EACH(hs, hset, hs, { + CMC_FOR_EACH(hs, hset, hs, { sums[3] += hs_iter_value(&iter); }); - FOR_EACH(h, heap, h, { + CMC_FOR_EACH(h, heap, h, { sums[4] += h_iter_value(&iter); }); - FOR_EACH(ll, linked, ll, { + CMC_FOR_EACH(ll, linked, ll, { sums[5] += ll_iter_value(&iter); }); - FOR_EACH(l, list, l, { + CMC_FOR_EACH(l, list, l, { sums[6] += l_iter_value(&iter); }); - FOR_EACH(q, queue, q, { + CMC_FOR_EACH(q, queue, q, { sums[7] += q_iter_value(&iter); }); - FOR_EACH(s, stack, s, { + CMC_FOR_EACH(s, stack, s, { sums[8] += s_iter_value(&iter); }); - FOR_EACH(tm, tmap, tm, { + CMC_FOR_EACH(tm, tmap, tm, { sums[9] += tm_iter_key(&iter); sums[10] += tm_iter_value(&iter); }); - FOR_EACH(ts, tset, ts, { + CMC_FOR_EACH(ts, tset, ts, { sums[11] += ts_iter_value(&iter); }); - FOR_EACH(ih, iheap, ih, { + CMC_FOR_EACH(ih, iheap, ih, { sums[12] += ih_iter_value(&iter); }); - FOR_EACH(mm, mmap, mm, { + CMC_FOR_EACH(mm, mmap, mm, { sums[13] += mm_iter_key(&iter); sums[14] += mm_iter_value(&iter); }); - FOR_EACH(ms, mset, ms, { + CMC_FOR_EACH(ms, mset, ms, { sums[15] += ms_iter_value(&iter); }); - printf("\n-------------------- FOR_EACH --------------------\n"); + printf("\n-------------------- CMC_FOR_EACH --------------------\n"); if (sums[0] == 50005000) printf("%12s PASSED\n", "DEQUE"); else @@ -197,62 +197,62 @@ int main(void) memset(sums, 0, sizeof sums); - FOR_EACH_REV(d, deque, d, { + CMC_FOR_EACH_REV(d, deque, d, { sums[0] += d_iter_value(&iter); }); - FOR_EACH_REV(hm, hmap, hm, { + CMC_FOR_EACH_REV(hm, hmap, hm, { sums[1] += hm_iter_key(&iter); sums[2] += hm_iter_value(&iter); }); - FOR_EACH_REV(hs, hset, hs, { + CMC_FOR_EACH_REV(hs, hset, hs, { sums[3] += hs_iter_value(&iter); }); - FOR_EACH_REV(h, heap, h, { + CMC_FOR_EACH_REV(h, heap, h, { sums[4] += h_iter_value(&iter); }); - FOR_EACH_REV(ll, linked, ll, { + CMC_FOR_EACH_REV(ll, linked, ll, { sums[5] += ll_iter_value(&iter); }); - FOR_EACH_REV(l, list, l, { + CMC_FOR_EACH_REV(l, list, l, { sums[6] += l_iter_value(&iter); }); - FOR_EACH_REV(q, queue, q, { + CMC_FOR_EACH_REV(q, queue, q, { sums[7] += q_iter_value(&iter); }); - FOR_EACH_REV(s, stack, s, { + CMC_FOR_EACH_REV(s, stack, s, { sums[8] += s_iter_value(&iter); }); - FOR_EACH_REV(tm, tmap, tm, { + CMC_FOR_EACH_REV(tm, tmap, tm, { sums[9] += tm_iter_key(&iter); sums[10] += tm_iter_value(&iter); }); - FOR_EACH_REV(ts, tset, ts, { + CMC_FOR_EACH_REV(ts, tset, ts, { sums[11] += ts_iter_value(&iter); }); - FOR_EACH_REV(ih, iheap, ih, { + CMC_FOR_EACH_REV(ih, iheap, ih, { sums[12] += ih_iter_value(&iter); }); - FOR_EACH_REV(mm, mmap, mm, { + CMC_FOR_EACH_REV(mm, mmap, mm, { sums[13] += mm_iter_key(&iter); sums[14] += mm_iter_value(&iter); }); - FOR_EACH_REV(ms, mset, ms, { + CMC_FOR_EACH_REV(ms, mset, ms, { sums[15] += ms_iter_value(&iter); }); - printf("-------------------- FOR_EACH_REV --------------------\n"); + printf("-------------------- CMC_FOR_EACH_REV --------------------\n"); if (sums[0] == 50005000) printf("%12s PASSED\n", "DEQUE"); else diff --git a/tests/iterators.c b/tests/iterators.c index 0b23d08..d60282d 100644 --- a/tests/iterators.c +++ b/tests/iterators.c @@ -18,20 +18,20 @@ size_t inthash(int t) return a; } -COLLECTION_GENERATE(LIST, l, list, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(STACK, s, stack, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(QUEUE, q, queue, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(DEQUE, d, deque, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(LINKEDLIST, ll, linked, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(HEAP, h, heap, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(TREESET, ts, tset, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(TREEMAP, tm, tmap, /* FMOD */, int, double) -COLLECTION_GENERATE(HASHSET, hs, hset, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(HASHMAP, hm, hmap, /* FMOD */, int, double) +CMC_COLLECTION_GENERATE(LIST, l, list, /* K */, int) +CMC_COLLECTION_GENERATE(STACK, s, stack, /* K */, int) +CMC_COLLECTION_GENERATE(QUEUE, q, queue, /* K */, int) +CMC_COLLECTION_GENERATE(DEQUE, d, deque, /* K */, int) +CMC_COLLECTION_GENERATE(LINKEDLIST, ll, linked, /* K */, int) +CMC_COLLECTION_GENERATE(HEAP, h, heap, /* K */, int) +CMC_COLLECTION_GENERATE(TREESET, ts, tset, /* K */, int) +CMC_COLLECTION_GENERATE(TREEMAP, tm, tmap, int, double) +CMC_COLLECTION_GENERATE(HASHSET, hs, hset, /* K */, int) +CMC_COLLECTION_GENERATE(HASHMAP, hm, hmap, int, double) -COLLECTION_GENERATE(INTERVALHEAP, ih, iheap, /* FMOD */, , int) -COLLECTION_GENERATE(MULTIMAP, mm, mmap, /* FMOD */, int, double) -COLLECTION_GENERATE(MULTISET, ms, mset, , , int) +CMC_COLLECTION_GENERATE(INTERVALHEAP, ih, iheap, /* K */, int) +CMC_COLLECTION_GENERATE(MULTIMAP, mm, mmap, int, double) +CMC_COLLECTION_GENERATE(MULTISET, ms, mset, /* K */, int) #define ITERATOR_TEST(NAME, PFX, sname, initfunc, insertbody, sumbody, validation1, validation2) \ void NAME##_iterator_test(void) \ diff --git a/tests/sep/sep.c b/tests/sep/sep.c index e582047..e42664e 100644 --- a/tests/sep/sep.c +++ b/tests/sep/sep.c @@ -1,16 +1,16 @@ #include "sep.h" -COLLECTION_GENERATE_SOURCE(LIST, l, list, /* FMOD */, /* K */, int) -COLLECTION_GENERATE_SOURCE(STACK, s, stack, /* FMOD */, /* K */, int) -COLLECTION_GENERATE_SOURCE(QUEUE, q, queue, /* FMOD */, /* K */, int) -COLLECTION_GENERATE_SOURCE(DEQUE, d, deque, /* FMOD */, /* K */, int) -COLLECTION_GENERATE_SOURCE(LINKEDLIST, ll, linked, /* FMOD */, /* K */, int) -COLLECTION_GENERATE_SOURCE(HEAP, h, heap, /* FMOD */, /* K */, int) -COLLECTION_GENERATE_SOURCE(TREESET, ts, tset, /* FMOD */, /* K */, int) -COLLECTION_GENERATE_SOURCE(TREEMAP, tm, tmap, /* FMOD */, int, int) -COLLECTION_GENERATE_SOURCE(HASHSET, hs, hset, /* FMOD */, /* K */, int) -COLLECTION_GENERATE_SOURCE(HASHMAP, hm, hmap, /* FMOD */, int, int) +CMC_COLLECTION_GENERATE_SOURCE(LIST, l, list, /* K */, int) +CMC_COLLECTION_GENERATE_SOURCE(STACK, s, stack, /* K */, int) +CMC_COLLECTION_GENERATE_SOURCE(QUEUE, q, queue, /* K */, int) +CMC_COLLECTION_GENERATE_SOURCE(DEQUE, d, deque, /* K */, int) +CMC_COLLECTION_GENERATE_SOURCE(LINKEDLIST, ll, linked, /* K */, int) +CMC_COLLECTION_GENERATE_SOURCE(HEAP, h, heap, /* K */, int) +CMC_COLLECTION_GENERATE_SOURCE(TREESET, ts, tset, /* K */, int) +CMC_COLLECTION_GENERATE_SOURCE(TREEMAP, tm, tmap, int, int) +CMC_COLLECTION_GENERATE_SOURCE(HASHSET, hs, hset, /* K */, int) +CMC_COLLECTION_GENERATE_SOURCE(HASHMAP, hm, hmap, int, int) -COLLECTION_GENERATE_SOURCE(INTERVALHEAP, ih, iheap, /* FMOD */, , int) -COLLECTION_GENERATE_SOURCE(MULTIMAP, mm, mmap, /* FMOD */, int, int) -COLLECTION_GENERATE_SOURCE(MULTISET, ms, mset, , , int) +CMC_COLLECTION_GENERATE_SOURCE(INTERVALHEAP, ih, iheap, , int) +CMC_COLLECTION_GENERATE_SOURCE(MULTIMAP, mm, mmap, int, int) +CMC_COLLECTION_GENERATE_SOURCE(MULTISET, ms, mset, , int) diff --git a/tests/sep/sep.h b/tests/sep/sep.h index faf2ea6..649b844 100644 --- a/tests/sep/sep.h +++ b/tests/sep/sep.h @@ -1,16 +1,16 @@ #include "../../src/macro_collections.h" -COLLECTION_GENERATE_HEADER(LIST, l, list, /* FMOD */, /* K */, int) -COLLECTION_GENERATE_HEADER(STACK, s, stack, /* FMOD */, /* K */, int) -COLLECTION_GENERATE_HEADER(QUEUE, q, queue, /* FMOD */, /* K */, int) -COLLECTION_GENERATE_HEADER(DEQUE, d, deque, /* FMOD */, /* K */, int) -COLLECTION_GENERATE_HEADER(LINKEDLIST, ll, linked, /* FMOD */, /* K */, int) -COLLECTION_GENERATE_HEADER(HEAP, h, heap, /* FMOD */, /* K */, int) -COLLECTION_GENERATE_HEADER(TREESET, ts, tset, /* FMOD */, /* K */, int) -COLLECTION_GENERATE_HEADER(TREEMAP, tm, tmap, /* FMOD */, int, int) -COLLECTION_GENERATE_HEADER(HASHSET, hs, hset, /* FMOD */, /* K */, int) -COLLECTION_GENERATE_HEADER(HASHMAP, hm, hmap, /* FMOD */, int, int) +CMC_COLLECTION_GENERATE_HEADER(LIST, l, list, /* K */, int) +CMC_COLLECTION_GENERATE_HEADER(STACK, s, stack, /* K */, int) +CMC_COLLECTION_GENERATE_HEADER(QUEUE, q, queue, /* K */, int) +CMC_COLLECTION_GENERATE_HEADER(DEQUE, d, deque, /* K */, int) +CMC_COLLECTION_GENERATE_HEADER(LINKEDLIST, ll, linked, /* K */, int) +CMC_COLLECTION_GENERATE_HEADER(HEAP, h, heap, /* K */, int) +CMC_COLLECTION_GENERATE_HEADER(TREESET, ts, tset, /* K */, int) +CMC_COLLECTION_GENERATE_HEADER(TREEMAP, tm, tmap, int, int) +CMC_COLLECTION_GENERATE_HEADER(HASHSET, hs, hset, /* K */, int) +CMC_COLLECTION_GENERATE_HEADER(HASHMAP, hm, hmap, int, int) -COLLECTION_GENERATE_HEADER(INTERVALHEAP, ih, iheap, /* FMOD */, , int) -COLLECTION_GENERATE_HEADER(MULTIMAP, mm, mmap, /* FMOD */, int, int) -COLLECTION_GENERATE_HEADER(MULTISET, ms, mset, , , int) +CMC_COLLECTION_GENERATE_HEADER(INTERVALHEAP, ih, iheap, , int) +CMC_COLLECTION_GENERATE_HEADER(MULTIMAP, mm, mmap, int, int) +CMC_COLLECTION_GENERATE_HEADER(MULTISET, ms, mset, , int) diff --git a/tests/types.c b/tests/types.c index c879b85..9ee6797 100644 --- a/tests/types.c +++ b/tests/types.c @@ -26,143 +26,142 @@ typedef union union_u { typedef int (*func_t)(int, double, char *); -COLLECTION_GENERATE(LIST, l0, list0, static, /* K */, struct_t *) -COLLECTION_GENERATE(STACK, s0, stack0, static, /* K */, struct_t *) -COLLECTION_GENERATE(QUEUE, q0, queue0, static, /* K */, struct_t *) -COLLECTION_GENERATE(DEQUE, d0, deque0, static, /* K */, struct_t *) -COLLECTION_GENERATE(LINKEDLIST, ll0, linked0, static, /* K */, struct_t *) -COLLECTION_GENERATE(HEAP, h0, heap0, static, /* K */, struct_t *) -COLLECTION_GENERATE(TREESET, ts0, tset0, static, /* K */, struct_t *) -COLLECTION_GENERATE(TREEMAP, tm0, tmap0, static, struct_t *, struct_t *) -COLLECTION_GENERATE(HASHSET, hs0, hset0, static, /* K */, struct_t *) -COLLECTION_GENERATE(HASHMAP, hm0, hmap0, static, struct_t *, struct_t *) -COLLECTION_GENERATE(INTERVALHEAP, ih0, iheap0, static, struct_t *, struct_t *) -COLLECTION_GENERATE(MULTIMAP, mm0, mmap0, static, struct_t *, struct_t *) -COLLECTION_GENERATE(MULTISET, ms0, mset0, static, struct_t *, struct_t *) +CMC_COLLECTION_GENERATE(LIST, l0, list0, /* K */, struct_t *) +CMC_COLLECTION_GENERATE(STACK, s0, stack0, /* K */, struct_t *) +CMC_COLLECTION_GENERATE(QUEUE, q0, queue0, /* K */, struct_t *) +CMC_COLLECTION_GENERATE(DEQUE, d0, deque0, /* K */, struct_t *) +CMC_COLLECTION_GENERATE(LINKEDLIST, ll0, linked0, /* K */, struct_t *) +CMC_COLLECTION_GENERATE(HEAP, h0, heap0, /* K */, struct_t *) +CMC_COLLECTION_GENERATE(TREESET, ts0, tset0, /* K */, struct_t *) +CMC_COLLECTION_GENERATE(TREEMAP, tm0, tmap0, struct_t *, struct_t *) +CMC_COLLECTION_GENERATE(HASHSET, hs0, hset0, /* K */, struct_t *) +CMC_COLLECTION_GENERATE(HASHMAP, hm0, hmap0, struct_t *, struct_t *) +CMC_COLLECTION_GENERATE(INTERVALHEAP, ih0, iheap0, struct_t *, struct_t *) +CMC_COLLECTION_GENERATE(MULTIMAP, mm0, mmap0, struct_t *, struct_t *) +CMC_COLLECTION_GENERATE(MULTISET, ms0, mset0, struct_t *, struct_t *) -COLLECTION_GENERATE(LIST, l1, list1, static, /* K */, struct_t) -COLLECTION_GENERATE(STACK, s1, stack1, static, /* K */, struct_t) -COLLECTION_GENERATE(QUEUE, q1, queue1, static, /* K */, struct_t) -COLLECTION_GENERATE(DEQUE, d1, deque1, static, /* K */, struct_t) -COLLECTION_GENERATE(LINKEDLIST, ll1, linked1, static, /* K */, struct_t) -COLLECTION_GENERATE(HEAP, h1, heap1, static, /* K */, struct_t) -COLLECTION_GENERATE(TREESET, ts1, tset1, static, /* K */, struct_t) -COLLECTION_GENERATE(TREEMAP, tm1, tmap1, static, struct_t, struct_t) -COLLECTION_GENERATE(HASHSET, hs1, hset1, static, /* K */, struct_t) -COLLECTION_GENERATE(HASHMAP, hm1, hmap1, static, struct_t, struct_t) -COLLECTION_GENERATE(INTERVALHEAP, ih1, iheap1, static, struct_t, struct_t) -COLLECTION_GENERATE(MULTIMAP, mm1, mmap1, static, struct_t, struct_t) -COLLECTION_GENERATE(MULTISET, ms1, mset1, static, struct_t, struct_t) +CMC_COLLECTION_GENERATE(LIST, l1, list1, /* K */, struct_t) +CMC_COLLECTION_GENERATE(STACK, s1, stack1, /* K */, struct_t) +CMC_COLLECTION_GENERATE(QUEUE, q1, queue1, /* K */, struct_t) +CMC_COLLECTION_GENERATE(DEQUE, d1, deque1, /* K */, struct_t) +CMC_COLLECTION_GENERATE(LINKEDLIST, ll1, linked1, /* K */, struct_t) +CMC_COLLECTION_GENERATE(HEAP, h1, heap1, /* K */, struct_t) +CMC_COLLECTION_GENERATE(TREESET, ts1, tset1, /* K */, struct_t) +CMC_COLLECTION_GENERATE(TREEMAP, tm1, tmap1, struct_t, struct_t) +CMC_COLLECTION_GENERATE(HASHSET, hs1, hset1, /* K */, struct_t) +CMC_COLLECTION_GENERATE(HASHMAP, hm1, hmap1, struct_t, struct_t) +CMC_COLLECTION_GENERATE(INTERVALHEAP, ih1, iheap1, struct_t, struct_t) +CMC_COLLECTION_GENERATE(MULTIMAP, mm1, mmap1, struct_t, struct_t) +CMC_COLLECTION_GENERATE(MULTISET, ms1, mset1, struct_t, struct_t) -COLLECTION_GENERATE(LIST, l2, list2, static, /* K */, int) -COLLECTION_GENERATE(STACK, s2, stack2, static, /* K */, int) -COLLECTION_GENERATE(QUEUE, q2, queue2, static, /* K */, int) -COLLECTION_GENERATE(DEQUE, d2, deque2, static, /* K */, int) -COLLECTION_GENERATE(LINKEDLIST, ll2, linked2, static, /* K */, int) -COLLECTION_GENERATE(HEAP, h2, heap2, static, /* K */, int) -COLLECTION_GENERATE(TREESET, ts2, tset2, static, /* K */, int) -COLLECTION_GENERATE(TREEMAP, tm2, tmap2, static, int, int) -COLLECTION_GENERATE(HASHSET, hs2, hset2, static, /* K */, int) -COLLECTION_GENERATE(HASHMAP, hm2, hmap2, static, int, int) -COLLECTION_GENERATE(INTERVALHEAP, ih2, iheap2, static, /* K */, int) -COLLECTION_GENERATE(MULTIMAP, mm2, mmap2, static, int, int) -COLLECTION_GENERATE(MULTISET, ms2, mset2, static, /* K */, int) +CMC_COLLECTION_GENERATE(LIST, l2, list2, /* K */, int) +CMC_COLLECTION_GENERATE(STACK, s2, stack2, /* K */, int) +CMC_COLLECTION_GENERATE(QUEUE, q2, queue2, /* K */, int) +CMC_COLLECTION_GENERATE(DEQUE, d2, deque2, /* K */, int) +CMC_COLLECTION_GENERATE(LINKEDLIST, ll2, linked2, /* K */, int) +CMC_COLLECTION_GENERATE(HEAP, h2, heap2, /* K */, int) +CMC_COLLECTION_GENERATE(TREESET, ts2, tset2, /* K */, int) +CMC_COLLECTION_GENERATE(TREEMAP, tm2, tmap2, int, int) +CMC_COLLECTION_GENERATE(HASHSET, hs2, hset2, /* K */, int) +CMC_COLLECTION_GENERATE(HASHMAP, hm2, hmap2, int, int) +CMC_COLLECTION_GENERATE(INTERVALHEAP, ih2, iheap2, /* K */, int) +CMC_COLLECTION_GENERATE(MULTIMAP, mm2, mmap2, int, int) +CMC_COLLECTION_GENERATE(MULTISET, ms2, mset2, /* K */, int) -COLLECTION_GENERATE(LIST, l3, list3, static, /* K */, int *) -COLLECTION_GENERATE(STACK, s3, stack3, static, /* K */, int *) -COLLECTION_GENERATE(QUEUE, q3, queue3, static, /* K */, int *) -COLLECTION_GENERATE(DEQUE, d3, deque3, static, /* K */, int *) -COLLECTION_GENERATE(LINKEDLIST, ll3, linked3, static, /* K */, int *) -COLLECTION_GENERATE(HEAP, h3, heap3, static, /* K */, int *) -COLLECTION_GENERATE(TREESET, ts3, tset3, static, /* K */, int *) -COLLECTION_GENERATE(TREEMAP, tm3, tmap3, static, int *, int *) -COLLECTION_GENERATE(HASHSET, hs3, hset3, static, /* K */, int *) -COLLECTION_GENERATE(HASHMAP, hm3, hmap3, static, int *, int *) -COLLECTION_GENERATE(INTERVALHEAP, ih3, iheap3, static, /* K */, int *) -COLLECTION_GENERATE(MULTIMAP, mm3, mmap3, static, int *, int *) -COLLECTION_GENERATE(MULTISET, ms3, mset3, static, /* K */, int *) +CMC_COLLECTION_GENERATE(LIST, l3, list3, /* K */, int *) +CMC_COLLECTION_GENERATE(STACK, s3, stack3, /* K */, int *) +CMC_COLLECTION_GENERATE(QUEUE, q3, queue3, /* K */, int *) +CMC_COLLECTION_GENERATE(DEQUE, d3, deque3, /* K */, int *) +CMC_COLLECTION_GENERATE(LINKEDLIST, ll3, linked3, /* K */, int *) +CMC_COLLECTION_GENERATE(HEAP, h3, heap3, /* K */, int *) +CMC_COLLECTION_GENERATE(TREESET, ts3, tset3, /* K */, int *) +CMC_COLLECTION_GENERATE(TREEMAP, tm3, tmap3, int *, int *) +CMC_COLLECTION_GENERATE(HASHSET, hs3, hset3, /* K */, int *) +CMC_COLLECTION_GENERATE(HASHMAP, hm3, hmap3, int *, int *) +CMC_COLLECTION_GENERATE(INTERVALHEAP, ih3, iheap3, /* K */, int *) +CMC_COLLECTION_GENERATE(MULTIMAP, mm3, mmap3, int *, int *) +CMC_COLLECTION_GENERATE(MULTISET, ms3, mset3, /* K */, int *) -COLLECTION_GENERATE(LIST, l4, list4, static, /* K */, enum_t *) -COLLECTION_GENERATE(STACK, s4, stack4, static, /* K */, enum_t *) -COLLECTION_GENERATE(QUEUE, q4, queue4, static, /* K */, enum_t *) -COLLECTION_GENERATE(DEQUE, d4, deque4, static, /* K */, enum_t *) -COLLECTION_GENERATE(LINKEDLIST, ll4, linked4, static, /* K */, enum_t *) -COLLECTION_GENERATE(HEAP, h4, heap4, static, /* K */, enum_t *) -COLLECTION_GENERATE(TREESET, ts4, tset4, static, /* K */, enum_t *) -COLLECTION_GENERATE(TREEMAP, tm4, tmap4, static, enum_t *, enum_t *) -COLLECTION_GENERATE(HASHSET, hs4, hset4, static, /* K */, enum_t *) -COLLECTION_GENERATE(HASHMAP, hm4, hmap4, static, enum_t *, enum_t *) -COLLECTION_GENERATE(INTERVALHEAP, ih4, iheap4, static, /* K */, enum_t *) -COLLECTION_GENERATE(MULTIMAP, mm4, mmap4, static, enum_t *, enum_t *) -COLLECTION_GENERATE(MULTISET, ms4, mset4, static, /* K */, enum_t *) +CMC_COLLECTION_GENERATE(LIST, l4, list4, /* K */, enum_t *) +CMC_COLLECTION_GENERATE(STACK, s4, stack4, /* K */, enum_t *) +CMC_COLLECTION_GENERATE(QUEUE, q4, queue4, /* K */, enum_t *) +CMC_COLLECTION_GENERATE(DEQUE, d4, deque4, /* K */, enum_t *) +CMC_COLLECTION_GENERATE(LINKEDLIST, ll4, linked4, /* K */, enum_t *) +CMC_COLLECTION_GENERATE(HEAP, h4, heap4, /* K */, enum_t *) +CMC_COLLECTION_GENERATE(TREESET, ts4, tset4, /* K */, enum_t *) +CMC_COLLECTION_GENERATE(TREEMAP, tm4, tmap4, enum_t *, enum_t *) +CMC_COLLECTION_GENERATE(HASHSET, hs4, hset4, /* K */, enum_t *) +CMC_COLLECTION_GENERATE(HASHMAP, hm4, hmap4, enum_t *, enum_t *) +CMC_COLLECTION_GENERATE(INTERVALHEAP, ih4, iheap4, /* K */, enum_t *) +CMC_COLLECTION_GENERATE(MULTIMAP, mm4, mmap4, enum_t *, enum_t *) +CMC_COLLECTION_GENERATE(MULTISET, ms4, mset4, /* K */, enum_t *) -COLLECTION_GENERATE(LIST, l5, list5, static, /* K */, enum_t) -COLLECTION_GENERATE(STACK, s5, stack5, static, /* K */, enum_t) -COLLECTION_GENERATE(QUEUE, q5, queue5, static, /* K */, enum_t) -COLLECTION_GENERATE(DEQUE, d5, deque5, static, /* K */, enum_t) -COLLECTION_GENERATE(LINKEDLIST, ll5, linked5, static, /* K */, enum_t) -COLLECTION_GENERATE(HEAP, h5, heap5, static, /* K */, enum_t) -COLLECTION_GENERATE(TREESET, ts5, tset5, static, /* K */, enum_t) -COLLECTION_GENERATE(TREEMAP, tm5, tmap5, static, enum_t, enum_t) -COLLECTION_GENERATE(HASHSET, hs5, hset5, static, /* K */, enum_t) -COLLECTION_GENERATE(HASHMAP, hm5, hmap5, static, enum_t, enum_t) -COLLECTION_GENERATE(INTERVALHEAP, ih5, iheap5, static, /* K */, enum_t) -COLLECTION_GENERATE(MULTIMAP, mm5, mmap5, static, enum_t, enum_t) -COLLECTION_GENERATE(MULTISET, ms5, mset5, static, /* K */, enum_t) +CMC_COLLECTION_GENERATE(LIST, l5, list5, /* K */, enum_t) +CMC_COLLECTION_GENERATE(STACK, s5, stack5, /* K */, enum_t) +CMC_COLLECTION_GENERATE(QUEUE, q5, queue5, /* K */, enum_t) +CMC_COLLECTION_GENERATE(DEQUE, d5, deque5, /* K */, enum_t) +CMC_COLLECTION_GENERATE(LINKEDLIST, ll5, linked5, /* K */, enum_t) +CMC_COLLECTION_GENERATE(HEAP, h5, heap5, /* K */, enum_t) +CMC_COLLECTION_GENERATE(TREESET, ts5, tset5, /* K */, enum_t) +CMC_COLLECTION_GENERATE(TREEMAP, tm5, tmap5, enum_t, enum_t) +CMC_COLLECTION_GENERATE(HASHSET, hs5, hset5, /* K */, enum_t) +CMC_COLLECTION_GENERATE(HASHMAP, hm5, hmap5, enum_t, enum_t) +CMC_COLLECTION_GENERATE(INTERVALHEAP, ih5, iheap5, /* K */, enum_t) +CMC_COLLECTION_GENERATE(MULTIMAP, mm5, mmap5, enum_t, enum_t) +CMC_COLLECTION_GENERATE(MULTISET, ms5, mset5, /* K */, enum_t) -COLLECTION_GENERATE(LIST, l6, list6, static, /* K */, union_t *) -COLLECTION_GENERATE(STACK, s6, stack6, static, /* K */, union_t *) -COLLECTION_GENERATE(QUEUE, q6, queue6, static, /* K */, union_t *) -COLLECTION_GENERATE(DEQUE, d6, deque6, static, /* K */, union_t *) -COLLECTION_GENERATE(LINKEDLIST, ll6, linked6, static, /* K */, union_t *) -COLLECTION_GENERATE(HEAP, h6, heap6, static, /* K */, union_t *) -COLLECTION_GENERATE(TREESET, ts6, tset6, static, /* K */, union_t *) -COLLECTION_GENERATE(TREEMAP, tm6, tmap6, static, union_t *, union_t *) -COLLECTION_GENERATE(HASHSET, hs6, hset6, static, /* K */, union_t *) -COLLECTION_GENERATE(HASHMAP, hm6, hmap6, static, union_t *, union_t *) -COLLECTION_GENERATE(INTERVALHEAP, ih6, iheap6, static, /* K */, union_t *) -COLLECTION_GENERATE(MULTIMAP, mm6, mmap6, static, union_t *, union_t *) -COLLECTION_GENERATE(MULTISET, ms6, mset6, static, /* K */, union_t *) +CMC_COLLECTION_GENERATE(LIST, l6, list6, /* K */, union_t *) +CMC_COLLECTION_GENERATE(STACK, s6, stack6, /* K */, union_t *) +CMC_COLLECTION_GENERATE(QUEUE, q6, queue6, /* K */, union_t *) +CMC_COLLECTION_GENERATE(DEQUE, d6, deque6, /* K */, union_t *) +CMC_COLLECTION_GENERATE(LINKEDLIST, ll6, linked6, /* K */, union_t *) +CMC_COLLECTION_GENERATE(HEAP, h6, heap6, /* K */, union_t *) +CMC_COLLECTION_GENERATE(TREESET, ts6, tset6, /* K */, union_t *) +CMC_COLLECTION_GENERATE(TREEMAP, tm6, tmap6, union_t *, union_t *) +CMC_COLLECTION_GENERATE(HASHSET, hs6, hset6, /* K */, union_t *) +CMC_COLLECTION_GENERATE(HASHMAP, hm6, hmap6, union_t *, union_t *) +CMC_COLLECTION_GENERATE(INTERVALHEAP, ih6, iheap6, /* K */, union_t *) +CMC_COLLECTION_GENERATE(MULTIMAP, mm6, mmap6, union_t *, union_t *) +CMC_COLLECTION_GENERATE(MULTISET, ms6, mset6, /* K */, union_t *) +CMC_COLLECTION_GENERATE(LIST, l7, list7, /* K */, union_t) +CMC_COLLECTION_GENERATE(STACK, s7, stack7, /* K */, union_t) +CMC_COLLECTION_GENERATE(QUEUE, q7, queue7, /* K */, union_t) +CMC_COLLECTION_GENERATE(DEQUE, d7, deque7, /* K */, union_t) +CMC_COLLECTION_GENERATE(LINKEDLIST, ll7, linked7, /* K */, union_t) +CMC_COLLECTION_GENERATE(HEAP, h7, heap7, /* K */, union_t) +CMC_COLLECTION_GENERATE(TREESET, ts7, tset7, /* K */, union_t) +CMC_COLLECTION_GENERATE(TREEMAP, tm7, tmap7, union_t, union_t) +CMC_COLLECTION_GENERATE(HASHSET, hs7, hset7, /* K */, union_t) +CMC_COLLECTION_GENERATE(HASHMAP, hm7, hmap7, union_t, union_t) +CMC_COLLECTION_GENERATE(INTERVALHEAP, ih7, iheap7, /* K */, union_t) +CMC_COLLECTION_GENERATE(MULTIMAP, mm7, mmap7, union_t, union_t) +CMC_COLLECTION_GENERATE(MULTISET, ms7, mset7, /* K */, union_t) -COLLECTION_GENERATE(LIST, l7, list7, static, /* K */, union_t) -COLLECTION_GENERATE(STACK, s7, stack7, static, /* K */, union_t) -COLLECTION_GENERATE(QUEUE, q7, queue7, static, /* K */, union_t) -COLLECTION_GENERATE(DEQUE, d7, deque7, static, /* K */, union_t) -COLLECTION_GENERATE(LINKEDLIST, ll7, linked7, static, /* K */, union_t) -COLLECTION_GENERATE(HEAP, h7, heap7, static, /* K */, union_t) -COLLECTION_GENERATE(TREESET, ts7, tset7, static, /* K */, union_t) -COLLECTION_GENERATE(TREEMAP, tm7, tmap7, static, union_t, union_t) -COLLECTION_GENERATE(HASHSET, hs7, hset7, static, /* K */, union_t) -COLLECTION_GENERATE(HASHMAP, hm7, hmap7, static, union_t, union_t) -COLLECTION_GENERATE(INTERVALHEAP, ih7, iheap7, static, /* K */, union_t) -COLLECTION_GENERATE(MULTIMAP, mm7, mmap7, static, union_t, union_t) -COLLECTION_GENERATE(MULTISET, ms7, mset7, static, /* K */, union_t) +CMC_COLLECTION_GENERATE(LIST, l8, list8, /* K */, func_t) +CMC_COLLECTION_GENERATE(STACK, s8, stack8, /* K */, func_t) +CMC_COLLECTION_GENERATE(QUEUE, q8, queue8, /* K */, func_t) +CMC_COLLECTION_GENERATE(DEQUE, d8, deque8, /* K */, func_t) +CMC_COLLECTION_GENERATE(LINKEDLIST, ll8, linked8, /* K */, func_t) +CMC_COLLECTION_GENERATE(HEAP, h8, heap8, /* K */, func_t) +CMC_COLLECTION_GENERATE(TREESET, ts8, tset8, /* K */, func_t) +CMC_COLLECTION_GENERATE(TREEMAP, tm8, tmap8, func_t, func_t) +CMC_COLLECTION_GENERATE(HASHSET, hs8, hset8, /* K */, func_t) +CMC_COLLECTION_GENERATE(HASHMAP, hm8, hmap8, func_t, func_t) +CMC_COLLECTION_GENERATE(INTERVALHEAP, ih8, iheap8, /* K */, func_t) +CMC_COLLECTION_GENERATE(MULTIMAP, mm8, mmap8, func_t, func_t) +CMC_COLLECTION_GENERATE(MULTISET, ms8, mset8, /* K */, func_t) -COLLECTION_GENERATE(LIST, l8, list8, static, /* K */, func_t) -COLLECTION_GENERATE(STACK, s8, stack8, static, /* K */, func_t) -COLLECTION_GENERATE(QUEUE, q8, queue8, static, /* K */, func_t) -COLLECTION_GENERATE(DEQUE, d8, deque8, static, /* K */, func_t) -COLLECTION_GENERATE(LINKEDLIST, ll8, linked8, static, /* K */, func_t) -COLLECTION_GENERATE(HEAP, h8, heap8, static, /* K */, func_t) -COLLECTION_GENERATE(TREESET, ts8, tset8, static, /* K */, func_t) -COLLECTION_GENERATE(TREEMAP, tm8, tmap8, static, func_t, func_t) -COLLECTION_GENERATE(HASHSET, hs8, hset8, static, /* K */, func_t) -COLLECTION_GENERATE(HASHMAP, hm8, hmap8, static, func_t, func_t) -COLLECTION_GENERATE(INTERVALHEAP, ih8, iheap8, static, /* K */, func_t) -COLLECTION_GENERATE(MULTIMAP, mm8, mmap8, static, func_t, func_t) -COLLECTION_GENERATE(MULTISET, ms8, mset8, static, /* K */, func_t) - -COLLECTION_GENERATE(LIST, l9, list9, static, /* K */, func_t) -COLLECTION_GENERATE(STACK, s9, stack9, static, /* K */, func_t) -COLLECTION_GENERATE(QUEUE, q9, queue9, static, /* K */, func_t) -COLLECTION_GENERATE(DEQUE, d9, deque9, static, /* K */, func_t) -COLLECTION_GENERATE(LINKEDLIST, ll9, linked9, static, /* K */, func_t) -COLLECTION_GENERATE(HEAP, h9, heap9, static, /* K */, func_t) -COLLECTION_GENERATE(TREESET, ts9, tset9, static, /* K */, func_t) -COLLECTION_GENERATE(TREEMAP, tm9, tmap9, static, func_t, func_t) -COLLECTION_GENERATE(HASHSET, hs9, hset9, static, /* K */, func_t) -COLLECTION_GENERATE(HASHMAP, hm9, hmap9, static, func_t, func_t) +CMC_COLLECTION_GENERATE(LIST, l9, list9, /* K */, func_t) +CMC_COLLECTION_GENERATE(STACK, s9, stack9, /* K */, func_t) +CMC_COLLECTION_GENERATE(QUEUE, q9, queue9, /* K */, func_t) +CMC_COLLECTION_GENERATE(DEQUE, d9, deque9, /* K */, func_t) +CMC_COLLECTION_GENERATE(LINKEDLIST, ll9, linked9, /* K */, func_t) +CMC_COLLECTION_GENERATE(HEAP, h9, heap9, /* K */, func_t) +CMC_COLLECTION_GENERATE(TREESET, ts9, tset9, /* K */, func_t) +CMC_COLLECTION_GENERATE(TREEMAP, tm9, tmap9, func_t, func_t) +CMC_COLLECTION_GENERATE(HASHSET, hs9, hset9, /* K */, func_t) +CMC_COLLECTION_GENERATE(HASHMAP, hm9, hmap9, func_t, func_t) int main(void) {