diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..36f4664 --- /dev/null +++ b/.clang-format @@ -0,0 +1,19 @@ +# clang-format 9.0.0 +Language: Cpp +BasedOnStyle: LLVM +AlignEscapedNewlines: Left +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +BreakBeforeBraces: Allman +BreakStringLiterals: false +ColumnLimit: 80 +Cpp11BracedListStyle: false +ForEachMacros: ["CMC_FOREACH", "CMC_FOREACH_REV"] +IndentCaseLabels: true +IndentWidth: 4 +KeepEmptyLinesAtTheStartOfBlocks: true +MaxEmptyLinesToKeep: 1 +SpacesInContainerLiterals: false +TabWidth: 4 +UseTab: Never diff --git a/src/cmc/bidimap.h b/src/cmc/bidimap.h index 7b12a4d..efbb27b 100644 --- a/src/cmc/bidimap.h +++ b/src/cmc/bidimap.h @@ -28,13 +28,13 @@ #include #include -#include #include +#include #include -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Core functionalities of the C Macro Collections Library - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ #ifndef CMC_CORE_H #define CMC_CORE_H @@ -53,7 +53,8 @@ static const size_t cmc_string_len = 400; /** * struct cmc_alloc_node * - * Custom allocation node. Allows collections to use custom allocation functions. + * Custom allocation node. Allows collections to use custom allocation + * functions. */ struct cmc_alloc_node { @@ -63,13 +64,14 @@ struct cmc_alloc_node void (*free)(void *); }; -static struct cmc_alloc_node cmc_alloc_node_default = {malloc, calloc, realloc, free}; +static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, + free }; #endif /* CMC_CORE_H */ -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Hashtable Implementation - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ #ifndef CMC_IMPL_ENTRY_DELETED #define CMC_IMPL_ENTRY_DELETED @@ -80,22 +82,52 @@ static struct cmc_alloc_node cmc_alloc_node_default = {malloc, calloc, realloc, #ifndef CMC_IMPL_HASHTABLE_PRIMES #define CMC_IMPL_HASHTABLE_PRIMES -static const size_t cmc_hashtable_primes[] = - {53, 97, 191, 383, 769, 1531, 3067, 6143, 12289, 24571, 49157, 98299, 196613, 393209, 786431, - 1572869, 3145721, 6291449, 12582917, 25165813, 50331653, 100663291, 201326611, 402653189, - 805306357, 1610612741, 3221225473, 6442450939, 12884901893, 25769803799, 51539607551, - 103079215111, 206158430209, 412316860441, 824633720831, 1649267441651, 3298534883309, - 6597069766657, 13194139533299, 26388279066623, 52776558133303, 105553116266489, - 211106232532969, 422212465066001, 844424930131963, 1688849860263953, 3377699720527861, - 6755399441055731, 13510798882111483, 27021597764222939, 54043195528445957, 108086391056891903, - 216172782113783773, 432345564227567621, 864691128455135207, 1729382256910270481, - 3458764513820540933, 6917529027641081903, 13835058055282163729llu}; +// clang-format off +static const size_t cmc_hashtable_primes[] = { + /* < 1e3 */ + 53, 97, 191, 383, 769, + /* < 1e4 */ + 1531, 3067, 6143, + /* < 1e5 */ + 12289, 24571, 49157, 98299, + /* < 1e6 */ + 196613, 393209, 786431, + /* < 1e7 */ + 1572869, 3145721, 6291449, + /* < 1e8 */ + 12582917, 25165813, 50331653, + /* < 1e9 */ + 100663291, 201326611, 402653189, 805306357, + /* < 1e10 */ + 1610612741, 3221225473, 6442450939, + /* < 1e11 */ + 12884901893, 25769803799, 51539607551, + /* < 1e12 */ + 103079215111, 206158430209, 412316860441, 824633720831, + /* < 1e13 */ + 1649267441651, 3298534883309, 6597069766657, + /* < 1e14 */ + 13194139533299, 26388279066623, 52776558133303, + /* < 1e15 */ + 105553116266489, 211106232532969, 422212465066001, 844424930131963, + /* < 1e16 */ + 1688849860263953, 3377699720527861, 6755399441055731, + /* < 1e17 */ + 13510798882111483, 27021597764222939, 54043195528445957, + /* < 1e18 */ + 108086391056891903, 216172782113783773, 432345564227567621, 864691128455135207, + /* < 1e19 */ + 1729382256910270481, 3458764513820540933, 6917529027641081903, + /* < 1e20 */ + 13835058055282163729llu, +}; +// clang-format on #endif /* CMC_IMPL_HASHTABLE_PRIMES */ -/* ------------------------------------------------------------------------------------------------- - * BidiMap specific - ------------------------------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------- + * Bidimap Specific + * ------------------------------------------------------------------------- */ /* to_string format */ static const char *cmc_string_fmt_bidimap = "struct %s<%s, %s> " "at %p { " @@ -136,1168 +168,1201 @@ struct cmc_callbacks_bidimap #define CMC_WRAPGEN_BIDIMAP_SOURCE(PFX, SNAME, K, V) \ CMC_GENERATE_BIDIMAP_SOURCE(PFX, SNAME, K, V) -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Header - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_BIDIMAP_HEADER(PFX, SNAME, K, V) \ - \ - /* BidiMap Structure */ \ - struct SNAME \ - { \ - /* Array of Entries mapping K -> V */ \ - struct SNAME##_entry **key_buffer; \ - \ - /* Array of entries mapping V -> K */ \ - struct SNAME##_entry **val_buffer; \ - \ - /* Current arrays 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 (*key_cmp)(K, K); \ - \ - /* Value comparison function */ \ - int (*val_cmp)(V, V); \ - \ - /* Key hash function */ \ - size_t (*key_hash)(K); \ - \ - /* Value hash function */ \ - size_t (*val_hash)(V); \ - \ - /* Function that returns an iterator to the start of the bidimap */ \ - struct SNAME##_iter (*it_start)(struct SNAME *); \ - \ - /* Function that returns an iterator to the end of the bidimap */ \ - struct SNAME##_iter (*it_end)(struct SNAME *); \ - \ - /* Custom allocation functions */ \ - struct cmc_alloc_node *alloc; \ - \ - /* Custom callback functions */ \ - struct cmc_callbacks_bidimap *callbacks; \ - }; \ - \ - /* BidiMap Entry */ \ - struct SNAME##_entry \ - { \ - /* Entry Key */ \ - K key; \ - \ - /* Entry Value */ \ - V value; \ - \ - /* The distance of this node to its original position, used by */ \ - /* robin-hood hashing relative to the key_buffer */ \ - size_t key_dist; \ - \ - /* The distance of this node to its original position, used by */ \ - /* robin-hood hashing relative to the value_buffer */ \ - size_t val_dist; \ - }; \ - \ - /* BidiMap Iterator */ \ - struct SNAME##_iter \ - { \ - /* Target bidimap */ \ - struct SNAME *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* The index of the first element */ \ - size_t first; \ - \ - /* The index of the last element */ \ - size_t last; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - }; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - struct SNAME *PFX##_new(size_t capacity, double load, \ - int (*key_cmp)(K, K), size_t (*key_hash)(K), \ - int (*val_cmp)(V, V), size_t (*val_hash)(V)); \ - struct SNAME *PFX##_new_custom(size_t capacity, double load, \ - int (*key_cmp)(K, K), size_t (*key_hash)(K), \ - int (*val_cmp)(V, V), size_t (*val_hash)(V), \ - struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_bidimap *callbacks); \ - void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)); \ - void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)); \ - /* Customization of Allocation and Callbacks */ \ - void PFX##_customize(struct SNAME *_map_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_bidimap *callbacks); \ - /* Collection Input and Output */ \ - bool PFX##_insert(struct SNAME *_map_, K key, V value); \ - bool PFX##_update_key(struct SNAME *_map_, K key, K new_key); \ - bool PFX##_update_key_by_val(struct SNAME *_map_, V val, K new_key); \ - bool PFX##_update_val(struct SNAME *_map_, V val, V new_val); \ - bool PFX##_update_val_by_key(struct SNAME *_map_, K key, V new_val); \ - bool PFX##_remove_by_key(struct SNAME *_map_, K key, K *out_key, V *out_val); \ - bool PFX##_remove_by_val(struct SNAME *_map_, V val, K *out_key, V *out_val); \ - /* Element Access */ \ - K PFX##_get_key(struct SNAME *_map_, V val); \ - V PFX##_get_val(struct SNAME *_map_, K key); \ - /* Collection State */ \ - bool PFX##_contains_key(struct SNAME *_map_, K key); \ - bool PFX##_contains_val(struct SNAME *_map_, V val); \ - bool PFX##_empty(struct SNAME *_map_); \ - bool PFX##_full(struct SNAME *_map_); \ - size_t PFX##_count(struct SNAME *_map_); \ - size_t PFX##_capacity(struct SNAME *_map_); \ - double PFX##_load(struct SNAME *_map_); \ - /* Collection Utility */ \ - bool PFX##_resize(struct SNAME *_map_, size_t capacity); \ - struct SNAME *PFX##_copy_of(struct SNAME *_map_, K (*key_copy_func)(K), \ - V (*value_copy_func)(V)); \ - bool PFX##_equals(struct SNAME *_map1_, struct SNAME *_map2_); \ - struct cmc_string PFX##_to_string(struct SNAME *_map_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ - void PFX##_iter_free(struct SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(struct SNAME##_iter *iter); \ - bool PFX##_iter_end(struct SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(struct SNAME##_iter *iter); \ - void PFX##_iter_to_end(struct SNAME##_iter *iter); \ - bool PFX##_iter_next(struct SNAME##_iter *iter); \ - bool PFX##_iter_prev(struct SNAME##_iter *iter); \ - bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - K PFX##_iter_key(struct SNAME##_iter *iter); \ - V PFX##_iter_value(struct SNAME##_iter *iter); \ + * ------------------------------------------------------------------------- */ +#define CMC_GENERATE_BIDIMAP_HEADER(PFX, SNAME, K, V) \ + \ + /* BidiMap Structure */ \ + struct SNAME \ + { \ + /* Array of Entries mapping K -> V */ \ + struct SNAME##_entry **key_buffer; \ + \ + /* Array of entries mapping V -> K */ \ + struct SNAME##_entry **val_buffer; \ + \ + /* Current arrays 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 (*key_cmp)(K, K); \ + \ + /* Value comparison function */ \ + int (*val_cmp)(V, V); \ + \ + /* Key hash function */ \ + size_t (*key_hash)(K); \ + \ + /* Value hash function */ \ + size_t (*val_hash)(V); \ + \ + /* Function that returns an iterator to the start of the bidimap */ \ + struct SNAME##_iter (*it_start)(struct SNAME *); \ + \ + /* Function that returns an iterator to the end of the bidimap */ \ + struct SNAME##_iter (*it_end)(struct SNAME *); \ + \ + /* Custom allocation functions */ \ + struct cmc_alloc_node *alloc; \ + \ + /* Custom callback functions */ \ + struct cmc_callbacks_bidimap *callbacks; \ + }; \ + \ + /* BidiMap Entry */ \ + struct SNAME##_entry \ + { \ + /* Entry Key */ \ + K key; \ + \ + /* Entry Value */ \ + V value; \ + \ + /* The distance of this node to its original position, used by */ \ + /* robin-hood hashing relative to the key_buffer */ \ + size_t key_dist; \ + \ + /* The distance of this node to its original position, used by */ \ + /* robin-hood hashing relative to the value_buffer */ \ + size_t val_dist; \ + }; \ + \ + /* BidiMap Iterator */ \ + struct SNAME##_iter \ + { \ + /* Target bidimap */ \ + struct SNAME *target; \ + \ + /* Cursor's position (index) */ \ + size_t cursor; \ + \ + /* Keeps track of relative index to the iteration of elements */ \ + size_t index; \ + \ + /* The index of the first element */ \ + size_t first; \ + \ + /* The index of the last element */ \ + size_t last; \ + \ + /* If the iterator has reached the start of the iteration */ \ + bool start; \ + \ + /* If the iterator has reached the end of the iteration */ \ + bool end; \ + }; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + struct SNAME *PFX##_new(size_t capacity, double load, \ + int (*key_cmp)(K, K), size_t (*key_hash)(K), \ + int (*val_cmp)(V, V), size_t (*val_hash)(V)); \ + struct SNAME *PFX##_new_custom( \ + size_t capacity, double load, int (*key_cmp)(K, K), \ + size_t (*key_hash)(K), int (*val_cmp)(V, V), size_t (*val_hash)(V), \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_bidimap *callbacks); \ + void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)); \ + void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)); \ + /* Customization of Allocation and Callbacks */ \ + void PFX##_customize(struct SNAME *_map_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_bidimap *callbacks); \ + /* Collection Input and Output */ \ + bool PFX##_insert(struct SNAME *_map_, K key, V value); \ + bool PFX##_update_key(struct SNAME *_map_, K key, K new_key); \ + bool PFX##_update_key_by_val(struct SNAME *_map_, V val, K new_key); \ + bool PFX##_update_val(struct SNAME *_map_, V val, V new_val); \ + bool PFX##_update_val_by_key(struct SNAME *_map_, K key, V new_val); \ + bool PFX##_remove_by_key(struct SNAME *_map_, K key, K *out_key, \ + V *out_val); \ + bool PFX##_remove_by_val(struct SNAME *_map_, V val, K *out_key, \ + V *out_val); \ + /* Element Access */ \ + K PFX##_get_key(struct SNAME *_map_, V val); \ + V PFX##_get_val(struct SNAME *_map_, K key); \ + /* Collection State */ \ + bool PFX##_contains_key(struct SNAME *_map_, K key); \ + bool PFX##_contains_val(struct SNAME *_map_, V val); \ + bool PFX##_empty(struct SNAME *_map_); \ + bool PFX##_full(struct SNAME *_map_); \ + size_t PFX##_count(struct SNAME *_map_); \ + size_t PFX##_capacity(struct SNAME *_map_); \ + double PFX##_load(struct SNAME *_map_); \ + /* Collection Utility */ \ + bool PFX##_resize(struct SNAME *_map_, size_t capacity); \ + struct SNAME *PFX##_copy_of(struct SNAME *_map_, K (*key_copy_func)(K), \ + V (*value_copy_func)(V)); \ + bool PFX##_equals(struct SNAME *_map1_, struct SNAME *_map2_); \ + struct cmc_string PFX##_to_string(struct SNAME *_map_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ + void PFX##_iter_free(struct SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(struct SNAME##_iter *iter); \ + bool PFX##_iter_end(struct SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(struct SNAME##_iter *iter); \ + void PFX##_iter_to_end(struct SNAME##_iter *iter); \ + bool PFX##_iter_next(struct SNAME##_iter *iter); \ + bool PFX##_iter_prev(struct SNAME##_iter *iter); \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + K PFX##_iter_key(struct SNAME##_iter *iter); \ + V PFX##_iter_value(struct SNAME##_iter *iter); \ size_t PFX##_iter_index(struct SNAME##_iter *iter); -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Source - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_BIDIMAP_SOURCE(PFX, SNAME, K, V) \ - \ - /* Implementation Detail Functions */ \ - static struct SNAME##_entry *PFX##_impl_new_entry(struct SNAME *_map_, K key, V value); \ - static struct SNAME##_entry **PFX##_impl_get_entry_by_key(struct SNAME *_map_, K key); \ - static struct SNAME##_entry **PFX##_impl_get_entry_by_val(struct SNAME *_map_, V val); \ - static struct SNAME##_entry **PFX##_impl_add_entry_to_key(struct SNAME *_map_, \ - struct SNAME##_entry *entry); \ - static struct SNAME##_entry **PFX##_impl_add_entry_to_val(struct SNAME *_map_, \ - struct SNAME##_entry *entry); \ - static size_t PFX##_impl_calculate_size(size_t required); \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_map_); \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_map_); \ - \ - struct SNAME *PFX##_new(size_t capacity, double load, \ - int (*key_cmp)(K, K), size_t (*key_hash)(K), \ - int (*val_cmp)(V, V), size_t (*val_hash)(V)) \ - { \ - struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ - \ - 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); \ - \ - struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_map_) \ - return NULL; \ - \ - _map_->key_buffer = alloc->calloc(real_capacity, sizeof(struct SNAME##_entry *)); \ - _map_->val_buffer = alloc->calloc(real_capacity, sizeof(struct SNAME##_entry *)); \ - \ - if (!_map_->key_buffer || !_map_->val_buffer) \ - { \ - alloc->free(_map_->key_buffer); \ - alloc->free(_map_->val_buffer); \ - alloc->free(_map_); \ - return NULL; \ - } \ - \ - _map_->count = 0; \ - _map_->capacity = real_capacity; \ - _map_->load = load; \ - _map_->key_cmp = key_cmp; \ - _map_->val_cmp = val_cmp; \ - _map_->key_hash = key_hash; \ - _map_->val_hash = val_hash; \ - \ - _map_->it_start = PFX##_impl_it_start; \ - _map_->it_end = PFX##_impl_it_end; \ - \ - _map_->alloc = alloc; \ - _map_->callbacks = NULL; \ - \ - return _map_; \ - } \ - \ - struct SNAME *PFX##_new_custom(size_t capacity, double load, \ - int (*key_cmp)(K, K), size_t (*key_hash)(K), \ - int (*val_cmp)(V, V), size_t (*val_hash)(V), \ - struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_bidimap *callbacks) \ - { \ - 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); \ - \ - if (!alloc) \ - alloc = &cmc_alloc_node_default; \ - \ - struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_map_) \ - return NULL; \ - \ - _map_->key_buffer = alloc->calloc(real_capacity, sizeof(struct SNAME##_entry *)); \ - _map_->val_buffer = alloc->calloc(real_capacity, sizeof(struct SNAME##_entry *)); \ - \ - if (!_map_->key_buffer || !_map_->val_buffer) \ - { \ - alloc->free(_map_->key_buffer); \ - alloc->free(_map_->val_buffer); \ - alloc->free(_map_); \ - return NULL; \ - } \ - \ - _map_->count = 0; \ - _map_->capacity = real_capacity; \ - _map_->load = load; \ - _map_->key_cmp = key_cmp; \ - _map_->val_cmp = val_cmp; \ - _map_->key_hash = key_hash; \ - _map_->val_hash = val_hash; \ - \ - _map_->it_start = PFX##_impl_it_start; \ - _map_->it_end = PFX##_impl_it_end; \ - \ - _map_->alloc = alloc; \ - _map_->callbacks = callbacks; \ - \ - return _map_; \ - } \ - \ - void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - for (size_t i = 0; i < _map_->capacity; i++) \ - { \ - struct SNAME##_entry *entry = _map_->key_buffer[i]; \ - \ - if (entry && entry != CMC_ENTRY_DELETED) \ - { \ - if (deallocator) \ - deallocator(entry->key, entry->value); \ - \ - _map_->alloc->free(entry); \ - } \ - \ - _map_->key_buffer[i] = NULL; \ - _map_->val_buffer[i] = NULL; \ - } \ - \ - _map_->count = 0; \ - } \ - \ - void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - PFX##_clear(_map_, deallocator); \ - \ - _map_->alloc->free(_map_->key_buffer); \ - _map_->alloc->free(_map_->val_buffer); \ - _map_->alloc->free(_map_); \ - } \ - \ - void PFX##_customize(struct SNAME *_map_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_bidimap *callbacks) \ - { \ - if (alloc) \ - _map_->alloc = alloc; \ - \ - if (callbacks) \ - _map_->callbacks = callbacks; \ - } \ - \ - bool PFX##_insert(struct SNAME *_map_, K key, V value) \ - { \ - if (PFX##_full(_map_)) \ - { \ - if (!PFX##_resize(_map_, PFX##_capacity(_map_) + 1)) \ - return false; \ - } \ - \ - if (PFX##_impl_get_entry_by_key(_map_, key) != NULL || \ - PFX##_impl_get_entry_by_val(_map_, value) != NULL) \ - return false; \ - \ - struct SNAME##_entry *entry = PFX##_impl_new_entry(_map_, key, value); \ - \ - struct SNAME##_entry **key_entry = PFX##_impl_add_entry_to_key(_map_, entry); \ - struct SNAME##_entry **val_entry = PFX##_impl_add_entry_to_val(_map_, entry); \ - \ - if (!key_entry || !val_entry) \ - { \ - if (key_entry) \ - *key_entry = CMC_ENTRY_DELETED; \ - if (val_entry) \ - *val_entry = CMC_ENTRY_DELETED; \ - \ - _map_->alloc->free(entry); \ - \ - return false; \ - } \ - \ - _map_->count++; \ - \ - return true; \ - } \ - \ - bool PFX##_update_key(struct SNAME *_map_, K key, K new_key) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - struct SNAME##_entry **entry = PFX##_impl_get_entry_by_key(_map_, key); \ - \ - if (!entry) \ - return false; \ - \ - if (PFX##_contains_key(_map_, new_key)) \ - return false; \ - \ - struct SNAME##_entry *to_add = *entry; \ - K tmp_key = to_add->key; \ - to_add->key = new_key; \ - \ - *entry = CMC_ENTRY_DELETED; \ - \ - if (!PFX##_impl_add_entry_to_key(_map_, to_add)) \ - { \ - to_add->key = tmp_key; \ - *entry = to_add; \ - \ - return false; \ - } \ - \ - return true; \ - } \ - \ - bool PFX##_update_key_by_val(struct SNAME *_map_, V val, K new_key) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - struct SNAME##_entry **entry = PFX##_impl_get_entry_by_val(_map_, val); \ - \ - if (!entry) \ - return false; \ - \ - if (PFX##_contains_key(_map_, new_key)) \ - return false; \ - \ - struct SNAME##_entry *to_add = *entry; \ - K tmp_key = to_add->key; \ - to_add->key = new_key; \ - \ - *entry = CMC_ENTRY_DELETED; \ - \ - if (!PFX##_impl_add_entry_to_key(_map_, to_add)) \ - { \ - to_add->key = tmp_key; \ - *entry = to_add; \ - \ - return false; \ - } \ - \ - return true; \ - } \ - \ - bool PFX##_update_val(struct SNAME *_map_, V val, V new_val) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - struct SNAME##_entry **entry = PFX##_impl_get_entry_by_val(_map_, val); \ - \ - if (!entry) \ - return false; \ - \ - if (PFX##_contains_val(_map_, new_val)) \ - return false; \ - \ - struct SNAME##_entry *to_add = *entry; \ - V tmp_val = to_add->value; \ - to_add->value = new_val; \ - \ - *entry = CMC_ENTRY_DELETED; \ - \ - if (!PFX##_impl_add_entry_to_val(_map_, to_add)) \ - { \ - to_add->value = tmp_val; \ - *entry = to_add; \ - \ - return false; \ - } \ - \ - return true; \ - } \ - \ - bool PFX##_update_val_by_key(struct SNAME *_map_, K key, V new_val) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - struct SNAME##_entry **entry = PFX##_impl_get_entry_by_key(_map_, key); \ - \ - if (!entry) \ - return false; \ - \ - if (PFX##_contains_val(_map_, new_val)) \ - return false; \ - \ - struct SNAME##_entry *to_add = *entry; \ - V tmp_val = to_add->value; \ - to_add->value = new_val; \ - \ - *entry = CMC_ENTRY_DELETED; \ - \ - if (!PFX##_impl_add_entry_to_val(_map_, to_add)) \ - { \ - to_add->value = tmp_val; \ - *entry = to_add; \ - \ - return false; \ - } \ - \ - return true; \ - } \ - \ - bool PFX##_remove_by_key(struct SNAME *_map_, K key, K *out_key, V *out_val) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - struct SNAME##_entry **key_entry, **val_entry; \ - \ - key_entry = PFX##_impl_get_entry_by_key(_map_, key); \ - \ - if (!key_entry) \ - return false; \ - \ - val_entry = PFX##_impl_get_entry_by_val(_map_, (*key_entry)->value); \ - \ - if (!val_entry) \ - return false; \ - \ - if (*val_entry != *key_entry) \ - return false; \ - \ - if (out_key) \ - *out_key = (*key_entry)->key; \ - if (out_val) \ - *out_val = (*key_entry)->value; \ - \ - _map_->alloc->free(*key_entry); \ - \ - *key_entry = CMC_ENTRY_DELETED; \ - *val_entry = CMC_ENTRY_DELETED; \ - \ - _map_->count--; \ - \ - return true; \ - } \ - \ - bool PFX##_remove_by_val(struct SNAME *_map_, V val, K *out_key, V *out_val) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - struct SNAME##_entry **key_entry, **val_entry; \ - \ - val_entry = PFX##_impl_get_entry_by_val(_map_, val); \ - \ - if (!val_entry) \ - return false; \ - \ - key_entry = PFX##_impl_get_entry_by_key(_map_, (*val_entry)->key); \ - \ - if (!key_entry) \ - return false; \ - \ - if (*val_entry != *key_entry) \ - return false; \ - \ - if (out_key) \ - *out_key = (*val_entry)->key; \ - if (out_val) \ - *out_val = (*val_entry)->value; \ - \ - _map_->alloc->free(*val_entry); \ - \ - *key_entry = CMC_ENTRY_DELETED; \ - *val_entry = CMC_ENTRY_DELETED; \ - \ - _map_->count--; \ - \ - return true; \ - } \ - \ - K PFX##_get_key(struct SNAME *_map_, V val) \ - { \ - struct SNAME##_entry **entry = PFX##_impl_get_entry_by_val(_map_, val); \ - \ - if (!entry) \ - return (V){0}; \ - \ - return (*entry)->key; \ - } \ - \ - V PFX##_get_val(struct SNAME *_map_, K key) \ - { \ - struct SNAME##_entry **entry = PFX##_impl_get_entry_by_key(_map_, key); \ - \ - if (!entry) \ - return (V){0}; \ - \ - return (*entry)->value; \ - } \ - \ - bool PFX##_contains_key(struct SNAME *_map_, K key) \ - { \ - return PFX##_impl_get_entry_by_key(_map_, key) != NULL; \ - } \ - \ - bool PFX##_contains_val(struct SNAME *_map_, V val) \ - { \ - return PFX##_impl_get_entry_by_val(_map_, val) != NULL; \ - } \ - \ - bool PFX##_empty(struct SNAME *_map_) \ - { \ - return _map_->count == 0; \ - } \ - \ - bool PFX##_full(struct SNAME *_map_) \ - { \ - return (double)PFX##_capacity(_map_) * PFX##_load(_map_) <= (double)PFX##_count(_map_); \ - } \ - \ - size_t PFX##_count(struct SNAME *_map_) \ - { \ - return _map_->count; \ - } \ - \ - size_t PFX##_capacity(struct SNAME *_map_) \ - { \ - return _map_->capacity; \ - } \ - \ - double PFX##_load(struct SNAME *_map_) \ - { \ - return _map_->load; \ - } \ - \ - bool PFX##_resize(struct SNAME *_map_, size_t capacity) \ - { \ - if (PFX##_capacity(_map_) == capacity) \ - return true; \ - \ - if (PFX##_capacity(_map_) > capacity / PFX##_load(_map_)) \ - return true; \ - \ - /* Prevent integer overflow */ \ - if (capacity >= UINTMAX_MAX * PFX##_load(_map_)) \ - return false; \ - \ - /* Calculate required capacity based on the prime numbers */ \ - size_t new_cap = PFX##_impl_calculate_size(capacity); \ - \ - /* Not possible to shrink with current available prime numbers */ \ - if (new_cap < PFX##_count(_map_) / PFX##_load(_map_)) \ - return false; \ - \ - struct SNAME *_new_map_ = PFX##_new_custom(capacity, PFX##_load(_map_), \ - _map_->key_cmp, _map_->key_hash, \ - _map_->val_cmp, _map_->val_hash, \ - _map_->alloc, _map_->callbacks); \ - \ - if (!_new_map_) \ - return false; \ - \ - for (size_t i = 0; i < _map_->capacity; i++) \ - { \ - struct SNAME##_entry *scan = _map_->key_buffer[i]; \ - \ - if (scan && scan != CMC_ENTRY_DELETED) \ - { \ - struct SNAME##_entry **e1 = PFX##_impl_add_entry_to_key(_new_map_, scan); \ - struct SNAME##_entry **e2 = PFX##_impl_add_entry_to_val(_new_map_, scan); \ - \ - if (!e1 || !e2) \ - { \ - _map_->alloc->free(_new_map_->key_buffer); \ - _map_->alloc->free(_new_map_->val_buffer); \ - _map_->alloc->free(_new_map_); \ - \ - return false; \ - } \ - \ - _new_map_->count++; \ - } \ - } \ - \ - if (PFX##_count(_map_) != PFX##_count(_new_map_)) \ - { \ - _map_->alloc->free(_new_map_->key_buffer); \ - _map_->alloc->free(_new_map_->val_buffer); \ - _map_->alloc->free(_new_map_); \ - \ - return false; \ - } \ - \ - struct SNAME##_entry **tmp_key_buf = _map_->key_buffer; \ - struct SNAME##_entry **tmp_val_buf = _map_->val_buffer; \ - \ - _map_->key_buffer = _new_map_->key_buffer; \ - _map_->val_buffer = _new_map_->val_buffer; \ - _map_->capacity = _new_map_->capacity; \ - \ - _map_->alloc->free(tmp_key_buf); \ - _map_->alloc->free(tmp_val_buf); \ - _map_->alloc->free(_new_map_); \ - \ - return true; \ - } \ - \ - struct SNAME *PFX##_copy_of(struct SNAME *_map_, K (*key_copy_func)(K), \ - V (*value_copy_func)(V)) \ - { \ - /* TODO this function can be optimized */ \ - struct SNAME *result = PFX##_new_custom(PFX##_capacity(_map_), PFX##_load(_map_), \ - _map_->key_cmp, _map_->key_hash, \ - _map_->val_cmp, _map_->val_hash, \ - _map_->alloc, _map_->callbacks); \ - \ - for (size_t i = 0; i < _map_->capacity; i++) \ - { \ - struct SNAME##_entry *scan = _map_->key_buffer[i]; \ - \ - if (scan && scan != CMC_ENTRY_DELETED) \ - { \ - K tmp_key; \ - V tmp_val; \ - \ - if (key_copy_func) \ - tmp_key = key_copy_func(scan->key); \ - else \ - tmp_key = scan->key; \ - \ - if (value_copy_func) \ - tmp_val = value_copy_func(scan->value); \ - else \ - tmp_val = scan->value; \ - \ - PFX##_insert(result, tmp_key, tmp_val); \ - } \ - } \ - \ - return result; \ - } \ - \ - bool PFX##_equals(struct SNAME *_map1_, struct SNAME *_map2_) \ - { \ - if (PFX##_count(_map1_) != PFX##_count(_map2_)) \ - return false; \ - \ - struct SNAME *_mapA_; \ - struct SNAME *_mapB_; \ - \ - if (PFX##_capacity(_map1_) < PFX##_capacity(_map2_)) \ - { \ - _mapA_ = _map1_; \ - _mapB_ = _map2_; \ - } \ - else \ - { \ - _mapA_ = _map2_; \ - _mapB_ = _map1_; \ - } \ - \ - for (size_t i = 0; i < _mapA_->capacity; i++) \ - { \ - struct SNAME##_entry *scan = _mapA_->key_buffer[i]; \ - \ - if (scan && scan != CMC_ENTRY_DELETED) \ - { \ - struct SNAME##_entry **entry_B = PFX##_impl_get_entry_by_key(_mapB_, scan->key); \ - \ - if (!entry_B) \ - return false; \ - \ - if (_mapA_->val_cmp((*entry_B)->value, scan->value) != 0) \ - return false; \ - } \ - } \ - \ - return true; \ - } \ - \ - struct cmc_string PFX##_to_string(struct SNAME *_map_) \ - { \ - struct cmc_string str; \ - struct SNAME *m_ = _map_; \ - \ - int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_bidimap, \ - #SNAME, #K, #V, m_, m_->key_buffer, m_->val_buffer, m_->capacity, \ - m_->count, m_->load, m_->key_cmp, m_->val_cmp, m_->key_hash, \ - m_->val_hash, m_->alloc, m_->callbacks); \ - \ - if (n < 0 || n == (int)cmc_string_len) \ - return (struct cmc_string){0}; \ - \ - str.s[n] = '\0'; \ - \ - return str; \ - } \ - \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ - { \ - struct SNAME##_iter *iter = target->alloc->malloc(sizeof(struct SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(struct SNAME##_iter *iter) \ - { \ - iter->target->alloc->free(iter); \ - } \ - \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ - { \ - memset(iter, 0, sizeof(struct 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++) \ - { \ - struct SNAME##_entry *tmp = target->key_buffer[i]; \ - \ - if (tmp != NULL && tmp != CMC_ENTRY_DELETED) \ - { \ - iter->first = i; \ - break; \ - } \ - } \ - \ - iter->cursor = iter->first; \ - \ - for (size_t i = target->capacity; i > 0; i--) \ - { \ - struct SNAME##_entry *tmp = target->key_buffer[i - 1]; \ - \ - if (tmp != NULL && tmp != CMC_ENTRY_DELETED) \ - { \ - iter->last = i - 1; \ - break; \ - } \ - } \ - } \ - } \ - \ - bool PFX##_iter_start(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(struct SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->first; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = false; \ - } \ - } \ - \ - void PFX##_iter_to_end(struct SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->last; \ - iter->index = PFX##_count(iter->target) - 1; \ - iter->start = false; \ - iter->end = true; \ - } \ - } \ - \ - bool PFX##_iter_next(struct 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); \ - \ - struct SNAME##_entry *scan = iter->target->key_buffer[iter->cursor]; \ - \ - iter->index++; \ - \ - while (1) \ - { \ - iter->cursor++; \ - scan = iter->target->key_buffer[iter->cursor]; \ - \ - if (scan != NULL && scan != CMC_ENTRY_DELETED) \ - break; \ - } \ - \ - return true; \ - } \ - \ - bool PFX##_iter_prev(struct SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->index == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - struct SNAME##_entry *scan = iter->target->key_buffer[iter->cursor]; \ - \ - iter->index--; \ - \ - while (1) \ - { \ - iter->cursor--; \ - scan = iter->target->key_buffer[iter->cursor]; \ - \ - if (scan != NULL && scan != CMC_ENTRY_DELETED) \ - break; \ - } \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool PFX##_iter_advance(struct 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(struct 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(struct 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(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (K){0}; \ - \ - return iter->target->key_buffer[iter->cursor]->key; \ - } \ - \ - V PFX##_iter_value(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){0}; \ - \ - return iter->target->key_buffer[iter->cursor]->value; \ - } \ - \ - size_t PFX##_iter_index(struct SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - static struct SNAME##_entry *PFX##_impl_new_entry(struct SNAME *_map_, K key, V value) \ - { \ - struct SNAME##_entry *entry = _map_->alloc->malloc(sizeof(struct SNAME##_entry)); \ - \ - if (!entry) \ - return NULL; \ - \ - entry->key = key; \ - entry->value = value; \ - entry->key_dist = 0; \ - entry->val_dist = 0; \ - \ - return entry; \ - } \ - \ - static struct SNAME##_entry **PFX##_impl_get_entry_by_key(struct SNAME *_map_, K key) \ - { \ - size_t hash = _map_->key_hash(key); \ - size_t pos = hash % _map_->capacity; \ - \ - struct SNAME##_entry *target = _map_->key_buffer[pos]; \ - \ - while (target != NULL) \ - { \ - if (target != CMC_ENTRY_DELETED && _map_->key_cmp(target->key, key) == 0) \ - return &(_map_->key_buffer[pos % _map_->capacity]); \ - \ - pos++; \ - target = _map_->key_buffer[pos % _map_->capacity]; \ - } \ - \ - return NULL; \ - } \ - \ - static struct SNAME##_entry **PFX##_impl_get_entry_by_val(struct SNAME *_map_, V val) \ - { \ - size_t hash = _map_->val_hash(val); \ - size_t pos = hash % _map_->capacity; \ - \ - struct SNAME##_entry *target = _map_->val_buffer[pos]; \ - \ - while (target != NULL) \ - { \ - if (target != CMC_ENTRY_DELETED && _map_->val_cmp(target->value, val) == 0) \ - return &(_map_->val_buffer[pos % _map_->capacity]); \ - \ - pos++; \ - target = _map_->val_buffer[pos % _map_->capacity]; \ - } \ - \ - return NULL; \ - } \ - \ - static struct SNAME##_entry **PFX##_impl_add_entry_to_key(struct SNAME *_map_, \ - struct SNAME##_entry *entry) \ - { \ - struct SNAME##_entry **to_return = NULL; \ - \ - size_t hash = _map_->key_hash(entry->key); \ - size_t original_pos = hash % _map_->capacity; \ - size_t pos = original_pos; \ - \ - struct SNAME##_entry **scan = &(_map_->key_buffer[hash % _map_->capacity]); \ - \ - if (*scan == NULL) \ - { \ - *scan = entry; \ - \ - return scan; \ - } \ - else \ - { \ - while (true) \ - { \ - pos++; \ - scan = &(_map_->key_buffer[pos % _map_->capacity]); \ - \ - if (*scan == NULL || *scan == CMC_ENTRY_DELETED) \ - { \ - if (!to_return) \ - to_return = scan; \ - \ - *scan = entry; \ - entry->key_dist = pos - original_pos; \ - \ - return to_return; \ - } \ - else if ((*scan)->key_dist < pos - original_pos) \ - { \ - if (!to_return) \ - to_return = scan; \ - \ - size_t tmp_dist = (*scan)->key_dist; \ - entry->key_dist = pos - original_pos; \ - original_pos = pos - tmp_dist; \ - \ - struct SNAME##_entry *_tmp_ = *scan; \ - *scan = entry; \ - entry = _tmp_; \ - } \ - } \ - } \ - \ - return NULL; \ - } \ - \ - static struct SNAME##_entry **PFX##_impl_add_entry_to_val(struct SNAME *_map_, \ - struct SNAME##_entry *entry) \ - { \ - struct SNAME##_entry **to_return = NULL; \ - \ - size_t hash = _map_->val_hash(entry->value); \ - size_t original_pos = hash % _map_->capacity; \ - size_t pos = original_pos; \ - \ - struct SNAME##_entry **scan = &(_map_->val_buffer[hash % _map_->capacity]); \ - \ - if (*scan == NULL) \ - { \ - *scan = entry; \ - \ - return scan; \ - } \ - else \ - { \ - while (true) \ - { \ - pos++; \ - scan = &(_map_->val_buffer[pos % _map_->capacity]); \ - \ - if (*scan == NULL || *scan == CMC_ENTRY_DELETED) \ - { \ - if (!to_return) \ - to_return = scan; \ - \ - *scan = entry; \ - entry->val_dist = pos - original_pos; \ - \ - return to_return; \ - } \ - else if ((*scan)->val_dist < pos - original_pos) \ - { \ - if (!to_return) \ - to_return = scan; \ - \ - size_t tmp_dist = (*scan)->val_dist; \ - entry->val_dist = pos - original_pos; \ - original_pos = pos - tmp_dist; \ - \ - struct SNAME##_entry *_tmp_ = *scan; \ - *scan = entry; \ - entry = _tmp_; \ - } \ - } \ - } \ - \ - 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 struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_map_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _map_); \ - \ - return iter; \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_map_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _map_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ + * ------------------------------------------------------------------------- */ +#define CMC_GENERATE_BIDIMAP_SOURCE(PFX, SNAME, K, V) \ + \ + /* Implementation Detail Functions */ \ + static struct SNAME##_entry *PFX##_impl_new_entry(struct SNAME *_map_, \ + K key, V value); \ + static struct SNAME##_entry **PFX##_impl_get_entry_by_key( \ + struct SNAME *_map_, K key); \ + static struct SNAME##_entry **PFX##_impl_get_entry_by_val( \ + struct SNAME *_map_, V val); \ + static struct SNAME##_entry **PFX##_impl_add_entry_to_key( \ + struct SNAME *_map_, struct SNAME##_entry *entry); \ + static struct SNAME##_entry **PFX##_impl_add_entry_to_val( \ + struct SNAME *_map_, struct SNAME##_entry *entry); \ + static size_t PFX##_impl_calculate_size(size_t required); \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_map_); \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_map_); \ + \ + struct SNAME *PFX##_new(size_t capacity, double load, \ + int (*key_cmp)(K, K), size_t (*key_hash)(K), \ + int (*val_cmp)(V, V), size_t (*val_hash)(V)) \ + { \ + struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ + \ + 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); \ + \ + struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_map_) \ + return NULL; \ + \ + _map_->key_buffer = \ + alloc->calloc(real_capacity, sizeof(struct SNAME##_entry *)); \ + _map_->val_buffer = \ + alloc->calloc(real_capacity, sizeof(struct SNAME##_entry *)); \ + \ + if (!_map_->key_buffer || !_map_->val_buffer) \ + { \ + alloc->free(_map_->key_buffer); \ + alloc->free(_map_->val_buffer); \ + alloc->free(_map_); \ + return NULL; \ + } \ + \ + _map_->count = 0; \ + _map_->capacity = real_capacity; \ + _map_->load = load; \ + _map_->key_cmp = key_cmp; \ + _map_->val_cmp = val_cmp; \ + _map_->key_hash = key_hash; \ + _map_->val_hash = val_hash; \ + \ + _map_->it_start = PFX##_impl_it_start; \ + _map_->it_end = PFX##_impl_it_end; \ + \ + _map_->alloc = alloc; \ + _map_->callbacks = NULL; \ + \ + return _map_; \ + } \ + \ + struct SNAME *PFX##_new_custom( \ + size_t capacity, double load, int (*key_cmp)(K, K), \ + size_t (*key_hash)(K), int (*val_cmp)(V, V), size_t (*val_hash)(V), \ + struct cmc_alloc_node *alloc, struct cmc_callbacks_bidimap *callbacks) \ + { \ + 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); \ + \ + if (!alloc) \ + alloc = &cmc_alloc_node_default; \ + \ + struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_map_) \ + return NULL; \ + \ + _map_->key_buffer = \ + alloc->calloc(real_capacity, sizeof(struct SNAME##_entry *)); \ + _map_->val_buffer = \ + alloc->calloc(real_capacity, sizeof(struct SNAME##_entry *)); \ + \ + if (!_map_->key_buffer || !_map_->val_buffer) \ + { \ + alloc->free(_map_->key_buffer); \ + alloc->free(_map_->val_buffer); \ + alloc->free(_map_); \ + return NULL; \ + } \ + \ + _map_->count = 0; \ + _map_->capacity = real_capacity; \ + _map_->load = load; \ + _map_->key_cmp = key_cmp; \ + _map_->val_cmp = val_cmp; \ + _map_->key_hash = key_hash; \ + _map_->val_hash = val_hash; \ + \ + _map_->it_start = PFX##_impl_it_start; \ + _map_->it_end = PFX##_impl_it_end; \ + \ + _map_->alloc = alloc; \ + _map_->callbacks = callbacks; \ + \ + return _map_; \ + } \ + \ + void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)) \ + { \ + for (size_t i = 0; i < _map_->capacity; i++) \ + { \ + struct SNAME##_entry *entry = _map_->key_buffer[i]; \ + \ + if (entry && entry != CMC_ENTRY_DELETED) \ + { \ + if (deallocator) \ + deallocator(entry->key, entry->value); \ + \ + _map_->alloc->free(entry); \ + } \ + \ + _map_->key_buffer[i] = NULL; \ + _map_->val_buffer[i] = NULL; \ + } \ + \ + _map_->count = 0; \ + } \ + \ + void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)) \ + { \ + PFX##_clear(_map_, deallocator); \ + \ + _map_->alloc->free(_map_->key_buffer); \ + _map_->alloc->free(_map_->val_buffer); \ + _map_->alloc->free(_map_); \ + } \ + \ + void PFX##_customize(struct SNAME *_map_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_bidimap *callbacks) \ + { \ + if (alloc) \ + _map_->alloc = alloc; \ + \ + if (callbacks) \ + _map_->callbacks = callbacks; \ + } \ + \ + bool PFX##_insert(struct SNAME *_map_, K key, V value) \ + { \ + if (PFX##_full(_map_)) \ + { \ + if (!PFX##_resize(_map_, PFX##_capacity(_map_) + 1)) \ + return false; \ + } \ + \ + if (PFX##_impl_get_entry_by_key(_map_, key) != NULL || \ + PFX##_impl_get_entry_by_val(_map_, value) != NULL) \ + return false; \ + \ + struct SNAME##_entry *entry = PFX##_impl_new_entry(_map_, key, value); \ + \ + struct SNAME##_entry **key_entry = \ + PFX##_impl_add_entry_to_key(_map_, entry); \ + struct SNAME##_entry **val_entry = \ + PFX##_impl_add_entry_to_val(_map_, entry); \ + \ + if (!key_entry || !val_entry) \ + { \ + if (key_entry) \ + *key_entry = CMC_ENTRY_DELETED; \ + if (val_entry) \ + *val_entry = CMC_ENTRY_DELETED; \ + \ + _map_->alloc->free(entry); \ + \ + return false; \ + } \ + \ + _map_->count++; \ + \ + return true; \ + } \ + \ + bool PFX##_update_key(struct SNAME *_map_, K key, K new_key) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + struct SNAME##_entry **entry = \ + PFX##_impl_get_entry_by_key(_map_, key); \ + \ + if (!entry) \ + return false; \ + \ + if (PFX##_contains_key(_map_, new_key)) \ + return false; \ + \ + struct SNAME##_entry *to_add = *entry; \ + K tmp_key = to_add->key; \ + to_add->key = new_key; \ + \ + *entry = CMC_ENTRY_DELETED; \ + \ + if (!PFX##_impl_add_entry_to_key(_map_, to_add)) \ + { \ + to_add->key = tmp_key; \ + *entry = to_add; \ + \ + return false; \ + } \ + \ + return true; \ + } \ + \ + bool PFX##_update_key_by_val(struct SNAME *_map_, V val, K new_key) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + struct SNAME##_entry **entry = \ + PFX##_impl_get_entry_by_val(_map_, val); \ + \ + if (!entry) \ + return false; \ + \ + if (PFX##_contains_key(_map_, new_key)) \ + return false; \ + \ + struct SNAME##_entry *to_add = *entry; \ + K tmp_key = to_add->key; \ + to_add->key = new_key; \ + \ + *entry = CMC_ENTRY_DELETED; \ + \ + if (!PFX##_impl_add_entry_to_key(_map_, to_add)) \ + { \ + to_add->key = tmp_key; \ + *entry = to_add; \ + \ + return false; \ + } \ + \ + return true; \ + } \ + \ + bool PFX##_update_val(struct SNAME *_map_, V val, V new_val) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + struct SNAME##_entry **entry = \ + PFX##_impl_get_entry_by_val(_map_, val); \ + \ + if (!entry) \ + return false; \ + \ + if (PFX##_contains_val(_map_, new_val)) \ + return false; \ + \ + struct SNAME##_entry *to_add = *entry; \ + V tmp_val = to_add->value; \ + to_add->value = new_val; \ + \ + *entry = CMC_ENTRY_DELETED; \ + \ + if (!PFX##_impl_add_entry_to_val(_map_, to_add)) \ + { \ + to_add->value = tmp_val; \ + *entry = to_add; \ + \ + return false; \ + } \ + \ + return true; \ + } \ + \ + bool PFX##_update_val_by_key(struct SNAME *_map_, K key, V new_val) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + struct SNAME##_entry **entry = \ + PFX##_impl_get_entry_by_key(_map_, key); \ + \ + if (!entry) \ + return false; \ + \ + if (PFX##_contains_val(_map_, new_val)) \ + return false; \ + \ + struct SNAME##_entry *to_add = *entry; \ + V tmp_val = to_add->value; \ + to_add->value = new_val; \ + \ + *entry = CMC_ENTRY_DELETED; \ + \ + if (!PFX##_impl_add_entry_to_val(_map_, to_add)) \ + { \ + to_add->value = tmp_val; \ + *entry = to_add; \ + \ + return false; \ + } \ + \ + return true; \ + } \ + \ + bool PFX##_remove_by_key(struct SNAME *_map_, K key, K *out_key, \ + V *out_val) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + struct SNAME##_entry **key_entry, **val_entry; \ + \ + key_entry = PFX##_impl_get_entry_by_key(_map_, key); \ + \ + if (!key_entry) \ + return false; \ + \ + val_entry = PFX##_impl_get_entry_by_val(_map_, (*key_entry)->value); \ + \ + if (!val_entry) \ + return false; \ + \ + if (*val_entry != *key_entry) \ + return false; \ + \ + if (out_key) \ + *out_key = (*key_entry)->key; \ + if (out_val) \ + *out_val = (*key_entry)->value; \ + \ + _map_->alloc->free(*key_entry); \ + \ + *key_entry = CMC_ENTRY_DELETED; \ + *val_entry = CMC_ENTRY_DELETED; \ + \ + _map_->count--; \ + \ + return true; \ + } \ + \ + bool PFX##_remove_by_val(struct SNAME *_map_, V val, K *out_key, \ + V *out_val) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + struct SNAME##_entry **key_entry, **val_entry; \ + \ + val_entry = PFX##_impl_get_entry_by_val(_map_, val); \ + \ + if (!val_entry) \ + return false; \ + \ + key_entry = PFX##_impl_get_entry_by_key(_map_, (*val_entry)->key); \ + \ + if (!key_entry) \ + return false; \ + \ + if (*val_entry != *key_entry) \ + return false; \ + \ + if (out_key) \ + *out_key = (*val_entry)->key; \ + if (out_val) \ + *out_val = (*val_entry)->value; \ + \ + _map_->alloc->free(*val_entry); \ + \ + *key_entry = CMC_ENTRY_DELETED; \ + *val_entry = CMC_ENTRY_DELETED; \ + \ + _map_->count--; \ + \ + return true; \ + } \ + \ + K PFX##_get_key(struct SNAME *_map_, V val) \ + { \ + struct SNAME##_entry **entry = \ + PFX##_impl_get_entry_by_val(_map_, val); \ + \ + if (!entry) \ + return (V){ 0 }; \ + \ + return (*entry)->key; \ + } \ + \ + V PFX##_get_val(struct SNAME *_map_, K key) \ + { \ + struct SNAME##_entry **entry = \ + PFX##_impl_get_entry_by_key(_map_, key); \ + \ + if (!entry) \ + return (V){ 0 }; \ + \ + return (*entry)->value; \ + } \ + \ + bool PFX##_contains_key(struct SNAME *_map_, K key) \ + { \ + return PFX##_impl_get_entry_by_key(_map_, key) != NULL; \ + } \ + \ + bool PFX##_contains_val(struct SNAME *_map_, V val) \ + { \ + return PFX##_impl_get_entry_by_val(_map_, val) != NULL; \ + } \ + \ + bool PFX##_empty(struct SNAME *_map_) \ + { \ + return _map_->count == 0; \ + } \ + \ + bool PFX##_full(struct SNAME *_map_) \ + { \ + return (double)PFX##_capacity(_map_) * PFX##_load(_map_) <= \ + (double)PFX##_count(_map_); \ + } \ + \ + size_t PFX##_count(struct SNAME *_map_) \ + { \ + return _map_->count; \ + } \ + \ + size_t PFX##_capacity(struct SNAME *_map_) \ + { \ + return _map_->capacity; \ + } \ + \ + double PFX##_load(struct SNAME *_map_) \ + { \ + return _map_->load; \ + } \ + \ + bool PFX##_resize(struct SNAME *_map_, size_t capacity) \ + { \ + if (PFX##_capacity(_map_) == capacity) \ + return true; \ + \ + if (PFX##_capacity(_map_) > capacity / PFX##_load(_map_)) \ + return true; \ + \ + /* Prevent integer overflow */ \ + if (capacity >= UINTMAX_MAX * PFX##_load(_map_)) \ + return false; \ + \ + /* Calculate required capacity based on the prime numbers */ \ + size_t new_cap = PFX##_impl_calculate_size(capacity); \ + \ + /* Not possible to shrink with current available prime numbers */ \ + if (new_cap < PFX##_count(_map_) / PFX##_load(_map_)) \ + return false; \ + \ + struct SNAME *_new_map_ = PFX##_new_custom( \ + capacity, PFX##_load(_map_), _map_->key_cmp, _map_->key_hash, \ + _map_->val_cmp, _map_->val_hash, _map_->alloc, _map_->callbacks); \ + \ + if (!_new_map_) \ + return false; \ + \ + for (size_t i = 0; i < _map_->capacity; i++) \ + { \ + struct SNAME##_entry *scan = _map_->key_buffer[i]; \ + \ + if (scan && scan != CMC_ENTRY_DELETED) \ + { \ + struct SNAME##_entry **e1 = \ + PFX##_impl_add_entry_to_key(_new_map_, scan); \ + struct SNAME##_entry **e2 = \ + PFX##_impl_add_entry_to_val(_new_map_, scan); \ + \ + if (!e1 || !e2) \ + { \ + _map_->alloc->free(_new_map_->key_buffer); \ + _map_->alloc->free(_new_map_->val_buffer); \ + _map_->alloc->free(_new_map_); \ + \ + return false; \ + } \ + \ + _new_map_->count++; \ + } \ + } \ + \ + if (PFX##_count(_map_) != PFX##_count(_new_map_)) \ + { \ + _map_->alloc->free(_new_map_->key_buffer); \ + _map_->alloc->free(_new_map_->val_buffer); \ + _map_->alloc->free(_new_map_); \ + \ + return false; \ + } \ + \ + struct SNAME##_entry **tmp_key_buf = _map_->key_buffer; \ + struct SNAME##_entry **tmp_val_buf = _map_->val_buffer; \ + \ + _map_->key_buffer = _new_map_->key_buffer; \ + _map_->val_buffer = _new_map_->val_buffer; \ + _map_->capacity = _new_map_->capacity; \ + \ + _map_->alloc->free(tmp_key_buf); \ + _map_->alloc->free(tmp_val_buf); \ + _map_->alloc->free(_new_map_); \ + \ + return true; \ + } \ + \ + struct SNAME *PFX##_copy_of(struct SNAME *_map_, K (*key_copy_func)(K), \ + V (*value_copy_func)(V)) \ + { \ + /* TODO this function can be optimized */ \ + struct SNAME *result = \ + PFX##_new_custom(PFX##_capacity(_map_), PFX##_load(_map_), \ + _map_->key_cmp, _map_->key_hash, _map_->val_cmp, \ + _map_->val_hash, _map_->alloc, _map_->callbacks); \ + \ + for (size_t i = 0; i < _map_->capacity; i++) \ + { \ + struct SNAME##_entry *scan = _map_->key_buffer[i]; \ + \ + if (scan && scan != CMC_ENTRY_DELETED) \ + { \ + K tmp_key; \ + V tmp_val; \ + \ + if (key_copy_func) \ + tmp_key = key_copy_func(scan->key); \ + else \ + tmp_key = scan->key; \ + \ + if (value_copy_func) \ + tmp_val = value_copy_func(scan->value); \ + else \ + tmp_val = scan->value; \ + \ + PFX##_insert(result, tmp_key, tmp_val); \ + } \ + } \ + \ + return result; \ + } \ + \ + bool PFX##_equals(struct SNAME *_map1_, struct SNAME *_map2_) \ + { \ + if (PFX##_count(_map1_) != PFX##_count(_map2_)) \ + return false; \ + \ + struct SNAME *_mapA_; \ + struct SNAME *_mapB_; \ + \ + if (PFX##_capacity(_map1_) < PFX##_capacity(_map2_)) \ + { \ + _mapA_ = _map1_; \ + _mapB_ = _map2_; \ + } \ + else \ + { \ + _mapA_ = _map2_; \ + _mapB_ = _map1_; \ + } \ + \ + for (size_t i = 0; i < _mapA_->capacity; i++) \ + { \ + struct SNAME##_entry *scan = _mapA_->key_buffer[i]; \ + \ + if (scan && scan != CMC_ENTRY_DELETED) \ + { \ + struct SNAME##_entry **entry_B = \ + PFX##_impl_get_entry_by_key(_mapB_, scan->key); \ + \ + if (!entry_B) \ + return false; \ + \ + if (_mapA_->val_cmp((*entry_B)->value, scan->value) != 0) \ + return false; \ + } \ + } \ + \ + return true; \ + } \ + \ + struct cmc_string PFX##_to_string(struct SNAME *_map_) \ + { \ + struct cmc_string str; \ + struct SNAME *m_ = _map_; \ + \ + int n = \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_bidimap, #SNAME, \ + #K, #V, m_, m_->key_buffer, m_->val_buffer, m_->capacity, \ + m_->count, m_->load, m_->key_cmp, m_->val_cmp, \ + m_->key_hash, m_->val_hash, m_->alloc, m_->callbacks); \ + \ + if (n < 0 || n == (int)cmc_string_len) \ + return (struct cmc_string){ 0 }; \ + \ + str.s[n] = '\0'; \ + \ + return str; \ + } \ + \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ + { \ + struct SNAME##_iter *iter = \ + target->alloc->malloc(sizeof(struct SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + void PFX##_iter_free(struct SNAME##_iter *iter) \ + { \ + iter->target->alloc->free(iter); \ + } \ + \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ + { \ + memset(iter, 0, sizeof(struct 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++) \ + { \ + struct SNAME##_entry *tmp = target->key_buffer[i]; \ + \ + if (tmp != NULL && tmp != CMC_ENTRY_DELETED) \ + { \ + iter->first = i; \ + break; \ + } \ + } \ + \ + iter->cursor = iter->first; \ + \ + for (size_t i = target->capacity; i > 0; i--) \ + { \ + struct SNAME##_entry *tmp = target->key_buffer[i - 1]; \ + \ + if (tmp != NULL && tmp != CMC_ENTRY_DELETED) \ + { \ + iter->last = i - 1; \ + break; \ + } \ + } \ + } \ + } \ + \ + bool PFX##_iter_start(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + bool PFX##_iter_end(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + void PFX##_iter_to_start(struct SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->first; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = false; \ + } \ + } \ + \ + void PFX##_iter_to_end(struct SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->last; \ + iter->index = PFX##_count(iter->target) - 1; \ + iter->start = false; \ + iter->end = true; \ + } \ + } \ + \ + bool PFX##_iter_next(struct 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); \ + \ + struct SNAME##_entry *scan = iter->target->key_buffer[iter->cursor]; \ + \ + iter->index++; \ + \ + while (1) \ + { \ + iter->cursor++; \ + scan = iter->target->key_buffer[iter->cursor]; \ + \ + if (scan != NULL && scan != CMC_ENTRY_DELETED) \ + break; \ + } \ + \ + return true; \ + } \ + \ + bool PFX##_iter_prev(struct SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->index == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + struct SNAME##_entry *scan = iter->target->key_buffer[iter->cursor]; \ + \ + iter->index--; \ + \ + while (1) \ + { \ + iter->cursor--; \ + scan = iter->target->key_buffer[iter->cursor]; \ + \ + if (scan != NULL && scan != CMC_ENTRY_DELETED) \ + break; \ + } \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool PFX##_iter_advance(struct 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(struct 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(struct 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(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return (K){ 0 }; \ + \ + return iter->target->key_buffer[iter->cursor]->key; \ + } \ + \ + V PFX##_iter_value(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return (V){ 0 }; \ + \ + return iter->target->key_buffer[iter->cursor]->value; \ + } \ + \ + size_t PFX##_iter_index(struct SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + static struct SNAME##_entry *PFX##_impl_new_entry(struct SNAME *_map_, \ + K key, V value) \ + { \ + struct SNAME##_entry *entry = \ + _map_->alloc->malloc(sizeof(struct SNAME##_entry)); \ + \ + if (!entry) \ + return NULL; \ + \ + entry->key = key; \ + entry->value = value; \ + entry->key_dist = 0; \ + entry->val_dist = 0; \ + \ + return entry; \ + } \ + \ + static struct SNAME##_entry **PFX##_impl_get_entry_by_key( \ + struct SNAME *_map_, K key) \ + { \ + size_t hash = _map_->key_hash(key); \ + size_t pos = hash % _map_->capacity; \ + \ + struct SNAME##_entry *target = _map_->key_buffer[pos]; \ + \ + while (target != NULL) \ + { \ + if (target != CMC_ENTRY_DELETED && \ + _map_->key_cmp(target->key, key) == 0) \ + return &(_map_->key_buffer[pos % _map_->capacity]); \ + \ + pos++; \ + target = _map_->key_buffer[pos % _map_->capacity]; \ + } \ + \ + return NULL; \ + } \ + \ + static struct SNAME##_entry **PFX##_impl_get_entry_by_val( \ + struct SNAME *_map_, V val) \ + { \ + size_t hash = _map_->val_hash(val); \ + size_t pos = hash % _map_->capacity; \ + \ + struct SNAME##_entry *target = _map_->val_buffer[pos]; \ + \ + while (target != NULL) \ + { \ + if (target != CMC_ENTRY_DELETED && \ + _map_->val_cmp(target->value, val) == 0) \ + return &(_map_->val_buffer[pos % _map_->capacity]); \ + \ + pos++; \ + target = _map_->val_buffer[pos % _map_->capacity]; \ + } \ + \ + return NULL; \ + } \ + \ + static struct SNAME##_entry **PFX##_impl_add_entry_to_key( \ + struct SNAME *_map_, struct SNAME##_entry *entry) \ + { \ + struct SNAME##_entry **to_return = NULL; \ + \ + size_t hash = _map_->key_hash(entry->key); \ + size_t original_pos = hash % _map_->capacity; \ + size_t pos = original_pos; \ + \ + struct SNAME##_entry **scan = \ + &(_map_->key_buffer[hash % _map_->capacity]); \ + \ + if (*scan == NULL) \ + { \ + *scan = entry; \ + \ + return scan; \ + } \ + else \ + { \ + while (true) \ + { \ + pos++; \ + scan = &(_map_->key_buffer[pos % _map_->capacity]); \ + \ + if (*scan == NULL || *scan == CMC_ENTRY_DELETED) \ + { \ + if (!to_return) \ + to_return = scan; \ + \ + *scan = entry; \ + entry->key_dist = pos - original_pos; \ + \ + return to_return; \ + } \ + else if ((*scan)->key_dist < pos - original_pos) \ + { \ + if (!to_return) \ + to_return = scan; \ + \ + size_t tmp_dist = (*scan)->key_dist; \ + entry->key_dist = pos - original_pos; \ + original_pos = pos - tmp_dist; \ + \ + struct SNAME##_entry *_tmp_ = *scan; \ + *scan = entry; \ + entry = _tmp_; \ + } \ + } \ + } \ + \ + return NULL; \ + } \ + \ + static struct SNAME##_entry **PFX##_impl_add_entry_to_val( \ + struct SNAME *_map_, struct SNAME##_entry *entry) \ + { \ + struct SNAME##_entry **to_return = NULL; \ + \ + size_t hash = _map_->val_hash(entry->value); \ + size_t original_pos = hash % _map_->capacity; \ + size_t pos = original_pos; \ + \ + struct SNAME##_entry **scan = \ + &(_map_->val_buffer[hash % _map_->capacity]); \ + \ + if (*scan == NULL) \ + { \ + *scan = entry; \ + \ + return scan; \ + } \ + else \ + { \ + while (true) \ + { \ + pos++; \ + scan = &(_map_->val_buffer[pos % _map_->capacity]); \ + \ + if (*scan == NULL || *scan == CMC_ENTRY_DELETED) \ + { \ + if (!to_return) \ + to_return = scan; \ + \ + *scan = entry; \ + entry->val_dist = pos - original_pos; \ + \ + return to_return; \ + } \ + else if ((*scan)->val_dist < pos - original_pos) \ + { \ + if (!to_return) \ + to_return = scan; \ + \ + size_t tmp_dist = (*scan)->val_dist; \ + entry->val_dist = pos - original_pos; \ + original_pos = pos - tmp_dist; \ + \ + struct SNAME##_entry *_tmp_ = *scan; \ + *scan = entry; \ + entry = _tmp_; \ + } \ + } \ + } \ + \ + 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 struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_map_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _map_); \ + \ + return iter; \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_map_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _map_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_BIDIMAP_H */ diff --git a/src/cmc/deque.h b/src/cmc/deque.h index 2800733..75c8917 100644 --- a/src/cmc/deque.h +++ b/src/cmc/deque.h @@ -33,13 +33,13 @@ #include #include -#include #include +#include #include -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Core functionalities of the C Macro Collections Library - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ #ifndef CMC_CORE_H #define CMC_CORE_H @@ -58,7 +58,8 @@ static const size_t cmc_string_len = 400; /** * struct cmc_alloc_node * - * Custom allocation node. Allows collections to use custom allocation functions. + * Custom allocation node. Allows collections to use custom allocation + * functions. */ struct cmc_alloc_node { @@ -68,13 +69,14 @@ struct cmc_alloc_node void (*free)(void *); }; -static struct cmc_alloc_node cmc_alloc_node_default = {malloc, calloc, realloc, free}; +static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, + free }; #endif /* CMC_CORE_H */ -/* ------------------------------------------------------------------------------------------------- - * Deque specific - ------------------------------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------- + * Deque Specific + * ------------------------------------------------------------------------- */ /* to_string format */ static const char *cmc_string_fmt_deque = "struct %s<%s> " "at %p { " @@ -111,651 +113,667 @@ struct cmc_callbacks_deque #define CMC_WRAPGEN_DEQUE_SOURCE(PFX, SNAME, K, V) \ CMC_GENERATE_DEQUE_SOURCE(PFX, SNAME, V) -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Header - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_DEQUE_HEADER(PFX, SNAME, V) \ - \ - /* Deque Structure */ \ - struct SNAME \ - { \ - /* 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 (*it_start)(struct SNAME *); \ - \ - /* Function that returns an iterator to the end of the deque */ \ - struct SNAME##_iter (*it_end)(struct SNAME *); \ - \ - /* Custom allocation functions */ \ - struct cmc_alloc_node *alloc; \ - \ - /* Custom callback functions */ \ - struct cmc_callbacks_deque *callbacks; \ - }; \ - \ - /* Deque Iterator */ \ - struct SNAME##_iter \ - { \ - /* Target deque */ \ - struct SNAME *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; \ - }; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - struct SNAME *PFX##_new(size_t capacity); \ - struct SNAME *PFX##_new_custom(size_t capacity, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_deque *callbacks); \ - void PFX##_clear(struct SNAME *_deque_, void (*deallocator)(V)); \ - void PFX##_free(struct SNAME *_deque_, void (*deallocator)(V)); \ - /* Customization of Allocation and Callbacks */ \ - void PFX##_customize(struct SNAME *_deque_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_deque *callbacks); \ - /* Collection Input and Output */ \ - bool PFX##_push_front(struct SNAME *_deque_, V element); \ - bool PFX##_push_back(struct SNAME *_deque_, V element); \ - bool PFX##_pop_front(struct SNAME *_deque_); \ - bool PFX##_pop_back(struct SNAME *_deque_); \ - /* Element Access */ \ - V PFX##_front(struct SNAME *_deque_); \ - V PFX##_back(struct SNAME *_deque_); \ - /* Collection State */ \ - bool PFX##_contains(struct SNAME *_deque_, V element, int (*comparator)(V, V)); \ - bool PFX##_empty(struct SNAME *_deque_); \ - bool PFX##_full(struct SNAME *_deque_); \ - size_t PFX##_count(struct SNAME *_deque_); \ - size_t PFX##_capacity(struct SNAME *_deque_); \ - /* Collection Utility */ \ - bool PFX##_resize(struct SNAME *_deque_, size_t capacity); \ - struct SNAME *PFX##_copy_of(struct SNAME *_deque_, V (*copy_func)(V)); \ - bool PFX##_equals(struct SNAME *_deque1_, struct SNAME *_deque2_, int (*comparator)(V, V)); \ - struct cmc_string PFX##_to_string(struct SNAME *_deque_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ - void PFX##_iter_free(struct SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(struct SNAME##_iter *iter); \ - bool PFX##_iter_end(struct SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(struct SNAME##_iter *iter); \ - void PFX##_iter_to_end(struct SNAME##_iter *iter); \ - bool PFX##_iter_next(struct SNAME##_iter *iter); \ - bool PFX##_iter_prev(struct SNAME##_iter *iter); \ - bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - V PFX##_iter_value(struct SNAME##_iter *iter); \ - V *PFX##_iter_rvalue(struct SNAME##_iter *iter); \ + * ------------------------------------------------------------------------- */ +#define CMC_GENERATE_DEQUE_HEADER(PFX, SNAME, V) \ + \ + /* Deque Structure */ \ + struct SNAME \ + { \ + /* 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 (*it_start)(struct SNAME *); \ + \ + /* Function that returns an iterator to the end of the deque */ \ + struct SNAME##_iter (*it_end)(struct SNAME *); \ + \ + /* Custom allocation functions */ \ + struct cmc_alloc_node *alloc; \ + \ + /* Custom callback functions */ \ + struct cmc_callbacks_deque *callbacks; \ + }; \ + \ + /* Deque Iterator */ \ + struct SNAME##_iter \ + { \ + /* Target deque */ \ + struct SNAME *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; \ + }; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + struct SNAME *PFX##_new(size_t capacity); \ + struct SNAME *PFX##_new_custom(size_t capacity, \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_deque *callbacks); \ + void PFX##_clear(struct SNAME *_deque_, void (*deallocator)(V)); \ + void PFX##_free(struct SNAME *_deque_, void (*deallocator)(V)); \ + /* Customization of Allocation and Callbacks */ \ + void PFX##_customize(struct SNAME *_deque_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_deque *callbacks); \ + /* Collection Input and Output */ \ + bool PFX##_push_front(struct SNAME *_deque_, V element); \ + bool PFX##_push_back(struct SNAME *_deque_, V element); \ + bool PFX##_pop_front(struct SNAME *_deque_); \ + bool PFX##_pop_back(struct SNAME *_deque_); \ + /* Element Access */ \ + V PFX##_front(struct SNAME *_deque_); \ + V PFX##_back(struct SNAME *_deque_); \ + /* Collection State */ \ + bool PFX##_contains(struct SNAME *_deque_, V element, \ + int (*comparator)(V, V)); \ + bool PFX##_empty(struct SNAME *_deque_); \ + bool PFX##_full(struct SNAME *_deque_); \ + size_t PFX##_count(struct SNAME *_deque_); \ + size_t PFX##_capacity(struct SNAME *_deque_); \ + /* Collection Utility */ \ + bool PFX##_resize(struct SNAME *_deque_, size_t capacity); \ + struct SNAME *PFX##_copy_of(struct SNAME *_deque_, V (*copy_func)(V)); \ + bool PFX##_equals(struct SNAME *_deque1_, struct SNAME *_deque2_, \ + int (*comparator)(V, V)); \ + struct cmc_string PFX##_to_string(struct SNAME *_deque_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ + void PFX##_iter_free(struct SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(struct SNAME##_iter *iter); \ + bool PFX##_iter_end(struct SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(struct SNAME##_iter *iter); \ + void PFX##_iter_to_end(struct SNAME##_iter *iter); \ + bool PFX##_iter_next(struct SNAME##_iter *iter); \ + bool PFX##_iter_prev(struct SNAME##_iter *iter); \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + V PFX##_iter_value(struct SNAME##_iter *iter); \ + V *PFX##_iter_rvalue(struct SNAME##_iter *iter); \ size_t PFX##_iter_index(struct SNAME##_iter *iter); -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Source - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_DEQUE_SOURCE(PFX, SNAME, V) \ - \ - /* Implementation Detail Functions */ \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_deque_); \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_deque_); \ - \ - struct SNAME *PFX##_new(size_t capacity) \ - { \ - struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ - \ - if (capacity < 1) \ - return NULL; \ - \ - struct SNAME *_deque_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_deque_) \ - return NULL; \ - \ - _deque_->buffer = alloc->calloc(capacity, sizeof(V)); \ - \ - if (!_deque_->buffer) \ - { \ - alloc->free(_deque_); \ - return NULL; \ - } \ - \ - _deque_->capacity = capacity; \ - _deque_->count = 0; \ - _deque_->front = 0; \ - _deque_->back = 0; \ - \ - _deque_->it_start = PFX##_impl_it_start; \ - _deque_->it_end = PFX##_impl_it_end; \ - \ - _deque_->alloc = alloc; \ - _deque_->callbacks = NULL; \ - \ - return _deque_; \ - } \ - \ - struct SNAME *PFX##_new_custom(size_t capacity, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_deque *callbacks) \ - { \ - if (capacity < 1) \ - return NULL; \ - \ - if (!alloc) \ - alloc = &cmc_alloc_node_default; \ - \ - struct SNAME *_deque_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_deque_) \ - return NULL; \ - \ - _deque_->buffer = alloc->calloc(capacity, sizeof(V)); \ - \ - if (!_deque_->buffer) \ - { \ - alloc->free(_deque_); \ - return NULL; \ - } \ - \ - _deque_->capacity = capacity; \ - _deque_->count = 0; \ - _deque_->front = 0; \ - _deque_->back = 0; \ - \ - _deque_->it_start = PFX##_impl_it_start; \ - _deque_->it_end = PFX##_impl_it_end; \ - \ - _deque_->alloc = alloc; \ - _deque_->callbacks = callbacks; \ - \ - return _deque_; \ - } \ - \ - void PFX##_clear(struct SNAME *_deque_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) \ - { \ - deallocator(_deque_->buffer[i]); \ - \ - i = (i + 1) % _deque_->capacity; \ - } \ - } \ - \ - memset(_deque_->buffer, 0, sizeof(V) * _deque_->capacity); \ - \ - _deque_->count = 0; \ - _deque_->front = 0; \ - _deque_->back = 0; \ - } \ - \ - void PFX##_free(struct SNAME *_deque_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) \ - { \ - deallocator(_deque_->buffer[i]); \ - \ - i = (i + 1) % _deque_->capacity; \ - } \ - } \ - \ - _deque_->alloc->free(_deque_->buffer); \ - _deque_->alloc->free(_deque_); \ - } \ - \ - void PFX##_customize(struct SNAME *_deque_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_deque *callbacks) \ - { \ - if (alloc) \ - _deque_->alloc = alloc; \ - \ - if (callbacks) \ - _deque_->callbacks = callbacks; \ - } \ - \ - bool PFX##_push_front(struct SNAME *_deque_, V element) \ - { \ - if (PFX##_full(_deque_)) \ - { \ - if (!PFX##_resize(_deque_, PFX##_capacity(_deque_) * 2)) \ - return false; \ - } \ - \ - _deque_->front = (_deque_->front == 0) ? _deque_->capacity - 1 : _deque_->front - 1; \ - \ - _deque_->buffer[_deque_->front] = element; \ - \ - _deque_->count++; \ - \ - return true; \ - } \ - \ - bool PFX##_push_back(struct SNAME *_deque_, V element) \ - { \ - if (PFX##_full(_deque_)) \ - { \ - if (!PFX##_resize(_deque_, PFX##_capacity(_deque_) * 2)) \ - return false; \ - } \ - \ - _deque_->buffer[_deque_->back] = element; \ - \ - _deque_->back = (_deque_->back == _deque_->capacity - 1) ? 0 : _deque_->back + 1; \ - \ - _deque_->count++; \ - \ - return true; \ - } \ - \ - bool PFX##_pop_front(struct SNAME *_deque_) \ - { \ - if (PFX##_empty(_deque_)) \ - return false; \ - \ - _deque_->buffer[_deque_->front] = (V){0}; \ - \ - _deque_->front = (_deque_->front == _deque_->capacity - 1) ? 0 : _deque_->front + 1; \ - \ - _deque_->count--; \ - \ - return true; \ - } \ - \ - bool PFX##_pop_back(struct SNAME *_deque_) \ - { \ - if (PFX##_empty(_deque_)) \ - return false; \ - \ - _deque_->back = (_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1; \ - \ - _deque_->buffer[_deque_->back] = (V){0}; \ - \ - _deque_->count--; \ - \ - return true; \ - } \ - \ - V PFX##_front(struct SNAME *_deque_) \ - { \ - if (PFX##_empty(_deque_)) \ - return (V){0}; \ - \ - return _deque_->buffer[_deque_->front]; \ - } \ - \ - V PFX##_back(struct SNAME *_deque_) \ - { \ - if (PFX##_empty(_deque_)) \ - return (V){0}; \ - \ - return _deque_->buffer[(_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1]; \ - } \ - \ - bool PFX##_contains(struct SNAME *_deque_, V element, int (*comparator)(V, V)) \ - { \ - for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) \ - { \ - if (comparator(_deque_->buffer[i], element) == 0) \ - return true; \ - \ - i = (i + 1) % _deque_->capacity; \ - } \ - \ - return false; \ - } \ - \ - bool PFX##_empty(struct SNAME *_deque_) \ - { \ - return _deque_->count == 0; \ - } \ - \ - bool PFX##_full(struct SNAME *_deque_) \ - { \ - return _deque_->count >= _deque_->capacity; \ - } \ - \ - size_t PFX##_count(struct SNAME *_deque_) \ - { \ - return _deque_->count; \ - } \ - \ - size_t PFX##_capacity(struct SNAME *_deque_) \ - { \ - return _deque_->capacity; \ - } \ - \ - bool PFX##_resize(struct SNAME *_deque_, size_t capacity) \ - { \ - if (PFX##_capacity(_deque_) == capacity) \ - return true; \ - \ - if (capacity < PFX##_count(_deque_)) \ - return false; \ - \ - V *new_buffer = _deque_->alloc->malloc(sizeof(V) * capacity); \ - \ - if (!new_buffer) \ - return false; \ - \ - for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) \ - { \ - new_buffer[j] = _deque_->buffer[i]; \ - \ - i = (i + 1) % PFX##_capacity(_deque_); \ - } \ - \ - _deque_->alloc->free(_deque_->buffer); \ - \ - _deque_->buffer = new_buffer; \ - _deque_->capacity = capacity; \ - _deque_->front = 0; \ - _deque_->back = _deque_->count; \ - \ - return true; \ - } \ - \ - struct SNAME *PFX##_copy_of(struct SNAME *_deque_, V (*copy_func)(V)) \ - { \ - struct SNAME *result = PFX##_new_custom(_deque_->capacity, _deque_->alloc, \ - _deque_->callbacks); \ - \ - if (!result) \ - return NULL; \ - \ - if (copy_func) \ - { \ - for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) \ - { \ - result->buffer[j] = copy_func(_deque_->buffer[i]); \ - \ - i = (i + 1) % _deque_->capacity; \ - } \ - } \ - else \ - { \ - for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) \ - { \ - result->buffer[j] = _deque_->buffer[i]; \ - \ - i = (i + 1) % _deque_->capacity; \ - } \ - } \ - \ - result->count = _deque_->count; \ - \ - return result; \ - } \ - \ - bool PFX##_equals(struct SNAME *_deque1_, struct SNAME *_deque2_, int (*comparator)(V, V)) \ - { \ - if (PFX##_count(_deque1_) != PFX##_count(_deque2_)) \ - return false; \ - \ - size_t i, j, k; \ - for (i = _deque1_->front, j = _deque2_->front, k = 0; k < PFX##_count(_deque1_); k++) \ - { \ - if (comparator(_deque1_->buffer[i], _deque2_->buffer[j]) != 0) \ - return false; \ - \ - i = (i + 1) % _deque1_->capacity; \ - j = (j + 1) % _deque2_->capacity; \ - } \ - \ - return true; \ - } \ - \ - struct cmc_string PFX##_to_string(struct SNAME *_deque_) \ - { \ - struct cmc_string str; \ - struct SNAME *d_ = _deque_; \ - \ - int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_deque, \ - #SNAME, #V, d_, d_->buffer, d_->capacity, d_->count, \ - d_->front, d_->back, d_->alloc, d_->callbacks); \ - \ - if (n < 0 || n == (int)cmc_string_len) \ - return (struct cmc_string){0}; \ - \ - str.s[n] = '\0'; \ - \ - return str; \ - } \ - \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ - { \ - struct SNAME##_iter *iter = target->alloc->malloc(sizeof(struct SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(struct SNAME##_iter *iter) \ - { \ - iter->target->alloc->free(iter); \ - } \ - \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ - { \ - iter->target = target; \ - iter->cursor = target->front; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - } \ - \ - bool PFX##_iter_start(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(struct SNAME##_iter *iter) \ - { \ - iter->cursor = iter->target->front; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - } \ - \ - void PFX##_iter_to_end(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - { \ - iter->cursor = 0; \ - iter->index = 0; \ - } \ - else \ - { \ - if (iter->target->back == 0) \ - iter->cursor = iter->target->capacity - 1; \ - else \ - iter->cursor = iter->target->back - 1; \ - \ - iter->index = PFX##_count(iter->target) - 1; \ - } \ - \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - } \ - \ - bool PFX##_iter_next(struct 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); \ - \ - iter->cursor = (iter->cursor + 1) % (iter->target->capacity); \ - iter->index++; \ - \ - return true; \ - } \ - \ - bool PFX##_iter_prev(struct SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->index == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; \ - iter->index--; \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool PFX##_iter_advance(struct 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; \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - iter->index += steps; \ - iter->cursor = (iter->cursor + steps) % iter->target->capacity; \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool PFX##_iter_rewind(struct 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; \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - iter->index -= steps; \ - \ - /* Prevent underflow */ \ - if (iter->cursor < steps) \ - iter->cursor += PFX##_capacity(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(struct 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(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){0}; \ - \ - return iter->target->buffer[iter->cursor]; \ - } \ - \ - V *PFX##_iter_rvalue(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->target->buffer[iter->cursor]); \ - } \ - \ - size_t PFX##_iter_index(struct SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_deque_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _deque_); \ - \ - return iter; \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_deque_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _deque_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ + * ------------------------------------------------------------------------- */ +#define CMC_GENERATE_DEQUE_SOURCE(PFX, SNAME, V) \ + \ + /* Implementation Detail Functions */ \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_deque_); \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_deque_); \ + \ + struct SNAME *PFX##_new(size_t capacity) \ + { \ + struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ + \ + if (capacity < 1) \ + return NULL; \ + \ + struct SNAME *_deque_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_deque_) \ + return NULL; \ + \ + _deque_->buffer = alloc->calloc(capacity, sizeof(V)); \ + \ + if (!_deque_->buffer) \ + { \ + alloc->free(_deque_); \ + return NULL; \ + } \ + \ + _deque_->capacity = capacity; \ + _deque_->count = 0; \ + _deque_->front = 0; \ + _deque_->back = 0; \ + \ + _deque_->it_start = PFX##_impl_it_start; \ + _deque_->it_end = PFX##_impl_it_end; \ + \ + _deque_->alloc = alloc; \ + _deque_->callbacks = NULL; \ + \ + return _deque_; \ + } \ + \ + struct SNAME *PFX##_new_custom(size_t capacity, \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_deque *callbacks) \ + { \ + if (capacity < 1) \ + return NULL; \ + \ + if (!alloc) \ + alloc = &cmc_alloc_node_default; \ + \ + struct SNAME *_deque_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_deque_) \ + return NULL; \ + \ + _deque_->buffer = alloc->calloc(capacity, sizeof(V)); \ + \ + if (!_deque_->buffer) \ + { \ + alloc->free(_deque_); \ + return NULL; \ + } \ + \ + _deque_->capacity = capacity; \ + _deque_->count = 0; \ + _deque_->front = 0; \ + _deque_->back = 0; \ + \ + _deque_->it_start = PFX##_impl_it_start; \ + _deque_->it_end = PFX##_impl_it_end; \ + \ + _deque_->alloc = alloc; \ + _deque_->callbacks = callbacks; \ + \ + return _deque_; \ + } \ + \ + void PFX##_clear(struct SNAME *_deque_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) \ + { \ + deallocator(_deque_->buffer[i]); \ + \ + i = (i + 1) % _deque_->capacity; \ + } \ + } \ + \ + memset(_deque_->buffer, 0, sizeof(V) * _deque_->capacity); \ + \ + _deque_->count = 0; \ + _deque_->front = 0; \ + _deque_->back = 0; \ + } \ + \ + void PFX##_free(struct SNAME *_deque_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) \ + { \ + deallocator(_deque_->buffer[i]); \ + \ + i = (i + 1) % _deque_->capacity; \ + } \ + } \ + \ + _deque_->alloc->free(_deque_->buffer); \ + _deque_->alloc->free(_deque_); \ + } \ + \ + void PFX##_customize(struct SNAME *_deque_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_deque *callbacks) \ + { \ + if (alloc) \ + _deque_->alloc = alloc; \ + \ + if (callbacks) \ + _deque_->callbacks = callbacks; \ + } \ + \ + bool PFX##_push_front(struct SNAME *_deque_, V element) \ + { \ + if (PFX##_full(_deque_)) \ + { \ + if (!PFX##_resize(_deque_, PFX##_capacity(_deque_) * 2)) \ + return false; \ + } \ + \ + _deque_->front = (_deque_->front == 0) ? _deque_->capacity - 1 \ + : _deque_->front - 1; \ + \ + _deque_->buffer[_deque_->front] = element; \ + \ + _deque_->count++; \ + \ + return true; \ + } \ + \ + bool PFX##_push_back(struct SNAME *_deque_, V element) \ + { \ + if (PFX##_full(_deque_)) \ + { \ + if (!PFX##_resize(_deque_, PFX##_capacity(_deque_) * 2)) \ + return false; \ + } \ + \ + _deque_->buffer[_deque_->back] = element; \ + \ + _deque_->back = \ + (_deque_->back == _deque_->capacity - 1) ? 0 : _deque_->back + 1; \ + \ + _deque_->count++; \ + \ + return true; \ + } \ + \ + bool PFX##_pop_front(struct SNAME *_deque_) \ + { \ + if (PFX##_empty(_deque_)) \ + return false; \ + \ + _deque_->buffer[_deque_->front] = (V){ 0 }; \ + \ + _deque_->front = (_deque_->front == _deque_->capacity - 1) \ + ? 0 \ + : _deque_->front + 1; \ + \ + _deque_->count--; \ + \ + return true; \ + } \ + \ + bool PFX##_pop_back(struct SNAME *_deque_) \ + { \ + if (PFX##_empty(_deque_)) \ + return false; \ + \ + _deque_->back = \ + (_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1; \ + \ + _deque_->buffer[_deque_->back] = (V){ 0 }; \ + \ + _deque_->count--; \ + \ + return true; \ + } \ + \ + V PFX##_front(struct SNAME *_deque_) \ + { \ + if (PFX##_empty(_deque_)) \ + return (V){ 0 }; \ + \ + return _deque_->buffer[_deque_->front]; \ + } \ + \ + V PFX##_back(struct SNAME *_deque_) \ + { \ + if (PFX##_empty(_deque_)) \ + return (V){ 0 }; \ + \ + return _deque_->buffer[(_deque_->back == 0) ? _deque_->capacity - 1 \ + : _deque_->back - 1]; \ + } \ + \ + bool PFX##_contains(struct SNAME *_deque_, V element, \ + int (*comparator)(V, V)) \ + { \ + for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) \ + { \ + if (comparator(_deque_->buffer[i], element) == 0) \ + return true; \ + \ + i = (i + 1) % _deque_->capacity; \ + } \ + \ + return false; \ + } \ + \ + bool PFX##_empty(struct SNAME *_deque_) \ + { \ + return _deque_->count == 0; \ + } \ + \ + bool PFX##_full(struct SNAME *_deque_) \ + { \ + return _deque_->count >= _deque_->capacity; \ + } \ + \ + size_t PFX##_count(struct SNAME *_deque_) \ + { \ + return _deque_->count; \ + } \ + \ + size_t PFX##_capacity(struct SNAME *_deque_) \ + { \ + return _deque_->capacity; \ + } \ + \ + bool PFX##_resize(struct SNAME *_deque_, size_t capacity) \ + { \ + if (PFX##_capacity(_deque_) == capacity) \ + return true; \ + \ + if (capacity < PFX##_count(_deque_)) \ + return false; \ + \ + V *new_buffer = _deque_->alloc->malloc(sizeof(V) * capacity); \ + \ + if (!new_buffer) \ + return false; \ + \ + for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) \ + { \ + new_buffer[j] = _deque_->buffer[i]; \ + \ + i = (i + 1) % PFX##_capacity(_deque_); \ + } \ + \ + _deque_->alloc->free(_deque_->buffer); \ + \ + _deque_->buffer = new_buffer; \ + _deque_->capacity = capacity; \ + _deque_->front = 0; \ + _deque_->back = _deque_->count; \ + \ + return true; \ + } \ + \ + struct SNAME *PFX##_copy_of(struct SNAME *_deque_, V (*copy_func)(V)) \ + { \ + struct SNAME *result = PFX##_new_custom( \ + _deque_->capacity, _deque_->alloc, _deque_->callbacks); \ + \ + if (!result) \ + return NULL; \ + \ + if (copy_func) \ + { \ + for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) \ + { \ + result->buffer[j] = copy_func(_deque_->buffer[i]); \ + \ + i = (i + 1) % _deque_->capacity; \ + } \ + } \ + else \ + { \ + for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) \ + { \ + result->buffer[j] = _deque_->buffer[i]; \ + \ + i = (i + 1) % _deque_->capacity; \ + } \ + } \ + \ + result->count = _deque_->count; \ + \ + return result; \ + } \ + \ + bool PFX##_equals(struct SNAME *_deque1_, struct SNAME *_deque2_, \ + int (*comparator)(V, V)) \ + { \ + if (PFX##_count(_deque1_) != PFX##_count(_deque2_)) \ + return false; \ + \ + size_t i, j, k; \ + for (i = _deque1_->front, j = _deque2_->front, k = 0; \ + k < PFX##_count(_deque1_); k++) \ + { \ + if (comparator(_deque1_->buffer[i], _deque2_->buffer[j]) != 0) \ + return false; \ + \ + i = (i + 1) % _deque1_->capacity; \ + j = (j + 1) % _deque2_->capacity; \ + } \ + \ + return true; \ + } \ + \ + struct cmc_string PFX##_to_string(struct SNAME *_deque_) \ + { \ + struct cmc_string str; \ + struct SNAME *d_ = _deque_; \ + \ + int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_deque, #SNAME, \ + #V, d_, d_->buffer, d_->capacity, d_->count, \ + d_->front, d_->back, d_->alloc, d_->callbacks); \ + \ + if (n < 0 || n == (int)cmc_string_len) \ + return (struct cmc_string){ 0 }; \ + \ + str.s[n] = '\0'; \ + \ + return str; \ + } \ + \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ + { \ + struct SNAME##_iter *iter = \ + target->alloc->malloc(sizeof(struct SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + void PFX##_iter_free(struct SNAME##_iter *iter) \ + { \ + iter->target->alloc->free(iter); \ + } \ + \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ + { \ + iter->target = target; \ + iter->cursor = target->front; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + } \ + \ + bool PFX##_iter_start(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + bool PFX##_iter_end(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + void PFX##_iter_to_start(struct SNAME##_iter *iter) \ + { \ + iter->cursor = iter->target->front; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ + \ + void PFX##_iter_to_end(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + { \ + iter->cursor = 0; \ + iter->index = 0; \ + } \ + else \ + { \ + if (iter->target->back == 0) \ + iter->cursor = iter->target->capacity - 1; \ + else \ + iter->cursor = iter->target->back - 1; \ + \ + iter->index = PFX##_count(iter->target) - 1; \ + } \ + \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + } \ + \ + bool PFX##_iter_next(struct 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); \ + \ + iter->cursor = (iter->cursor + 1) % (iter->target->capacity); \ + iter->index++; \ + \ + return true; \ + } \ + \ + bool PFX##_iter_prev(struct SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->index == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 \ + : iter->cursor - 1; \ + iter->index--; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool PFX##_iter_advance(struct 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; \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + iter->index += steps; \ + iter->cursor = (iter->cursor + steps) % iter->target->capacity; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool PFX##_iter_rewind(struct 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; \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->index -= steps; \ + \ + /* Prevent underflow */ \ + if (iter->cursor < steps) \ + iter->cursor += PFX##_capacity(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(struct 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(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return (V){ 0 }; \ + \ + return iter->target->buffer[iter->cursor]; \ + } \ + \ + V *PFX##_iter_rvalue(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return NULL; \ + \ + return &(iter->target->buffer[iter->cursor]); \ + } \ + \ + size_t PFX##_iter_index(struct SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_deque_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _deque_); \ + \ + return iter; \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_deque_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _deque_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_DEQUE_H */ diff --git a/src/cmc/hashmap.h b/src/cmc/hashmap.h index 6e23ee1..53562d8 100644 --- a/src/cmc/hashmap.h +++ b/src/cmc/hashmap.h @@ -21,13 +21,13 @@ #include #include -#include #include +#include #include -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Core functionalities of the C Macro Collections Library - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ #ifndef CMC_CORE_H #define CMC_CORE_H @@ -46,7 +46,8 @@ static const size_t cmc_string_len = 400; /** * struct cmc_alloc_node * - * Custom allocation node. Allows collections to use custom allocation functions. + * Custom allocation node. Allows collections to use custom allocation + * functions. */ struct cmc_alloc_node { @@ -56,13 +57,14 @@ struct cmc_alloc_node void (*free)(void *); }; -static struct cmc_alloc_node cmc_alloc_node_default = {malloc, calloc, realloc, free}; +static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, + free }; #endif /* CMC_CORE_H */ -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Hashtable Implementation - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ #ifndef CMC_IMPL_HASHTABLE_STATE #define CMC_IMPL_HASHTABLE_STATE @@ -78,22 +80,52 @@ enum cmc_entry_state #ifndef CMC_IMPL_HASHTABLE_PRIMES #define CMC_IMPL_HASHTABLE_PRIMES -static const size_t cmc_hashtable_primes[] = - {53, 97, 191, 383, 769, 1531, 3067, 6143, 12289, 24571, 49157, 98299, 196613, 393209, 786431, - 1572869, 3145721, 6291449, 12582917, 25165813, 50331653, 100663291, 201326611, 402653189, - 805306357, 1610612741, 3221225473, 6442450939, 12884901893, 25769803799, 51539607551, - 103079215111, 206158430209, 412316860441, 824633720831, 1649267441651, 3298534883309, - 6597069766657, 13194139533299, 26388279066623, 52776558133303, 105553116266489, - 211106232532969, 422212465066001, 844424930131963, 1688849860263953, 3377699720527861, - 6755399441055731, 13510798882111483, 27021597764222939, 54043195528445957, 108086391056891903, - 216172782113783773, 432345564227567621, 864691128455135207, 1729382256910270481, - 3458764513820540933, 6917529027641081903, 13835058055282163729llu}; +// clang-format off +static const size_t cmc_hashtable_primes[] = { + /* < 1e3 */ + 53, 97, 191, 383, 769, + /* < 1e4 */ + 1531, 3067, 6143, + /* < 1e5 */ + 12289, 24571, 49157, 98299, + /* < 1e6 */ + 196613, 393209, 786431, + /* < 1e7 */ + 1572869, 3145721, 6291449, + /* < 1e8 */ + 12582917, 25165813, 50331653, + /* < 1e9 */ + 100663291, 201326611, 402653189, 805306357, + /* < 1e10 */ + 1610612741, 3221225473, 6442450939, + /* < 1e11 */ + 12884901893, 25769803799, 51539607551, + /* < 1e12 */ + 103079215111, 206158430209, 412316860441, 824633720831, + /* < 1e13 */ + 1649267441651, 3298534883309, 6597069766657, + /* < 1e14 */ + 13194139533299, 26388279066623, 52776558133303, + /* < 1e15 */ + 105553116266489, 211106232532969, 422212465066001, 844424930131963, + /* < 1e16 */ + 1688849860263953, 3377699720527861, 6755399441055731, + /* < 1e17 */ + 13510798882111483, 27021597764222939, 54043195528445957, + /* < 1e18 */ + 108086391056891903, 216172782113783773, 432345564227567621, 864691128455135207, + /* < 1e19 */ + 1729382256910270481, 3458764513820540933, 6917529027641081903, + /* < 1e20 */ + 13835058055282163729llu, +}; +// clang-format on #endif /* CMC_IMPL_HASHTABLE_PRIMES */ -/* ------------------------------------------------------------------------------------------------- - * HashMap specific - ------------------------------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------- + * HashMap Specific + * ------------------------------------------------------------------------- */ /* to_string format */ static const char *cmc_string_fmt_hashmap = "struct %s<%s, %s> " "at %p { " @@ -131,922 +163,943 @@ struct cmc_callbacks_hashmap #define CMC_WRAPGEN_HASHMAP_SOURCE(PFX, SNAME, K, V) \ CMC_GENERATE_HASHMAP_SOURCE(PFX, SNAME, K, V) -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Header - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_HASHMAP_HEADER(PFX, SNAME, K, V) \ - \ - /* Hashmap Structure */ \ - struct SNAME \ - { \ - /* Array of Entries */ \ - struct SNAME##_entry *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 (*it_start)(struct SNAME *); \ - \ - /* Function that returns an iterator to the end of the hashmap */ \ - struct SNAME##_iter (*it_end)(struct SNAME *); \ - \ - /* Custom allocation functions */ \ - struct cmc_alloc_node *alloc; \ - \ - /* Custom callback functions */ \ - struct cmc_callbacks_hashmap *callbacks; \ - }; \ - \ - /* Hashmap Entry */ \ - struct SNAME##_entry \ - { \ - /* Entry Key */ \ - K key; \ - \ - /* Entry Value */ \ - V value; \ - \ - /* The distance of this node to its original position, used by */ \ - /* robin-hood hashing */ \ - size_t dist; \ - \ - /* The sate of this node (DELETED, EMPTY, FILLED) */ \ - enum cmc_entry_state state; \ - }; \ - \ - /* Hashmap Iterator */ \ - struct SNAME##_iter \ - { \ - /* Target hashmap */ \ - struct SNAME *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* The index of the first element */ \ - size_t first; \ - \ - /* The index of the last element */ \ - size_t last; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - }; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - struct SNAME *PFX##_new(size_t capacity, double load, int (*compare)(K, K), \ - size_t (*hash)(K)); \ - struct SNAME *PFX##_new_custom(size_t capacity, double load, int (*compare)(K, K), \ - size_t (*hash)(K), struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_hashmap *callbacks); \ - void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)); \ - void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)); \ - /* Customization of Allocation and Callbacks */ \ - void PFX##_customize(struct SNAME *_map_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_hashmap *callbacks); \ - /* Collection Input and Output */ \ - bool PFX##_insert(struct SNAME *_map_, K key, V value); \ - bool PFX##_update(struct SNAME *_map_, K key, V new_value, V *old_value); \ - bool PFX##_remove(struct SNAME *_map_, K key, V *out_value); \ - /* Element Access */ \ - bool PFX##_max(struct SNAME *_map_, K *key, V *value); \ - bool PFX##_min(struct SNAME *_map_, K *key, V *value); \ - V PFX##_get(struct SNAME *_map_, K key); \ - V *PFX##_get_ref(struct SNAME *_map_, K key); \ - /* Collection State */ \ - bool PFX##_contains(struct SNAME *_map_, K key); \ - bool PFX##_empty(struct SNAME *_map_); \ - bool PFX##_full(struct SNAME *_map_); \ - size_t PFX##_count(struct SNAME *_map_); \ - size_t PFX##_capacity(struct SNAME *_map_); \ - double PFX##_load(struct SNAME *_map_); \ - /* Collection Utility */ \ - bool PFX##_resize(struct SNAME *_map_, size_t capacity); \ - struct SNAME *PFX##_copy_of(struct SNAME *_map_, K (*key_copy_func)(K), \ - V (*value_copy_func)(V)); \ - bool PFX##_equals(struct SNAME *_map1_, struct SNAME *_map2_, \ - int (*value_comparator)(V, V)); \ - struct cmc_string PFX##_to_string(struct SNAME *_map_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ - void PFX##_iter_free(struct SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(struct SNAME##_iter *iter); \ - bool PFX##_iter_end(struct SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(struct SNAME##_iter *iter); \ - void PFX##_iter_to_end(struct SNAME##_iter *iter); \ - bool PFX##_iter_next(struct SNAME##_iter *iter); \ - bool PFX##_iter_prev(struct SNAME##_iter *iter); \ - bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - K PFX##_iter_key(struct SNAME##_iter *iter); \ - V PFX##_iter_value(struct SNAME##_iter *iter); \ - V *PFX##_iter_rvalue(struct SNAME##_iter *iter); \ + * ------------------------------------------------------------------------- */ +#define CMC_GENERATE_HASHMAP_HEADER(PFX, SNAME, K, V) \ + \ + /* Hashmap Structure */ \ + struct SNAME \ + { \ + /* Array of Entries */ \ + struct SNAME##_entry *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 (*it_start)(struct SNAME *); \ + \ + /* Function that returns an iterator to the end of the hashmap */ \ + struct SNAME##_iter (*it_end)(struct SNAME *); \ + \ + /* Custom allocation functions */ \ + struct cmc_alloc_node *alloc; \ + \ + /* Custom callback functions */ \ + struct cmc_callbacks_hashmap *callbacks; \ + }; \ + \ + /* Hashmap Entry */ \ + struct SNAME##_entry \ + { \ + /* Entry Key */ \ + K key; \ + \ + /* Entry Value */ \ + V value; \ + \ + /* The distance of this node to its original position, used by */ \ + /* robin-hood hashing */ \ + size_t dist; \ + \ + /* The sate of this node (DELETED, EMPTY, FILLED) */ \ + enum cmc_entry_state state; \ + }; \ + \ + /* Hashmap Iterator */ \ + struct SNAME##_iter \ + { \ + /* Target hashmap */ \ + struct SNAME *target; \ + \ + /* Cursor's position (index) */ \ + size_t cursor; \ + \ + /* Keeps track of relative index to the iteration of elements */ \ + size_t index; \ + \ + /* The index of the first element */ \ + size_t first; \ + \ + /* The index of the last element */ \ + size_t last; \ + \ + /* If the iterator has reached the start of the iteration */ \ + bool start; \ + \ + /* If the iterator has reached the end of the iteration */ \ + bool end; \ + }; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + struct SNAME *PFX##_new(size_t capacity, double load, \ + int (*compare)(K, K), size_t (*hash)(K)); \ + struct SNAME *PFX##_new_custom(size_t capacity, double load, \ + int (*compare)(K, K), size_t (*hash)(K), \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_hashmap *callbacks); \ + void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)); \ + void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)); \ + /* Customization of Allocation and Callbacks */ \ + void PFX##_customize(struct SNAME *_map_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_hashmap *callbacks); \ + /* Collection Input and Output */ \ + bool PFX##_insert(struct SNAME *_map_, K key, V value); \ + bool PFX##_update(struct SNAME *_map_, K key, V new_value, V *old_value); \ + bool PFX##_remove(struct SNAME *_map_, K key, V *out_value); \ + /* Element Access */ \ + bool PFX##_max(struct SNAME *_map_, K *key, V *value); \ + bool PFX##_min(struct SNAME *_map_, K *key, V *value); \ + V PFX##_get(struct SNAME *_map_, K key); \ + V *PFX##_get_ref(struct SNAME *_map_, K key); \ + /* Collection State */ \ + bool PFX##_contains(struct SNAME *_map_, K key); \ + bool PFX##_empty(struct SNAME *_map_); \ + bool PFX##_full(struct SNAME *_map_); \ + size_t PFX##_count(struct SNAME *_map_); \ + size_t PFX##_capacity(struct SNAME *_map_); \ + double PFX##_load(struct SNAME *_map_); \ + /* Collection Utility */ \ + bool PFX##_resize(struct SNAME *_map_, size_t capacity); \ + struct SNAME *PFX##_copy_of(struct SNAME *_map_, K (*key_copy_func)(K), \ + V (*value_copy_func)(V)); \ + bool PFX##_equals(struct SNAME *_map1_, struct SNAME *_map2_, \ + int (*value_comparator)(V, V)); \ + struct cmc_string PFX##_to_string(struct SNAME *_map_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ + void PFX##_iter_free(struct SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(struct SNAME##_iter *iter); \ + bool PFX##_iter_end(struct SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(struct SNAME##_iter *iter); \ + void PFX##_iter_to_end(struct SNAME##_iter *iter); \ + bool PFX##_iter_next(struct SNAME##_iter *iter); \ + bool PFX##_iter_prev(struct SNAME##_iter *iter); \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + K PFX##_iter_key(struct SNAME##_iter *iter); \ + V PFX##_iter_value(struct SNAME##_iter *iter); \ + V *PFX##_iter_rvalue(struct SNAME##_iter *iter); \ size_t PFX##_iter_index(struct SNAME##_iter *iter); -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Source - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_HASHMAP_SOURCE(PFX, SNAME, K, V) \ - \ - /* Implementation Detail Functions */ \ - static struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_map_, K key); \ - static size_t PFX##_impl_calculate_size(size_t required); \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_map_); \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_map_); \ - \ - struct SNAME *PFX##_new(size_t capacity, double load, int (*compare)(K, K), size_t (*hash)(K)) \ - { \ - struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ - \ - 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); \ - \ - struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_map_) \ - return NULL; \ - \ - _map_->buffer = alloc->calloc(real_capacity, sizeof(struct SNAME##_entry)); \ - \ - if (!_map_->buffer) \ - { \ - alloc->free(_map_); \ - return NULL; \ - } \ - \ - _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; \ - \ - _map_->alloc = alloc; \ - _map_->callbacks = NULL; \ - \ - return _map_; \ - } \ - \ - struct SNAME *PFX##_new_custom(size_t capacity, double load, \ - int (*compare)(K, K), size_t (*hash)(K), \ - struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_hashmap *callbacks) \ - { \ - 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); \ - \ - if (!alloc) \ - alloc = &cmc_alloc_node_default; \ - \ - struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_map_) \ - return NULL; \ - \ - _map_->buffer = alloc->calloc(real_capacity, sizeof(struct SNAME##_entry)); \ - \ - if (!_map_->buffer) \ - { \ - alloc->free(_map_); \ - return NULL; \ - } \ - \ - _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; \ - \ - _map_->alloc = alloc; \ - _map_->callbacks = callbacks; \ - \ - return _map_; \ - } \ - \ - void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _map_->capacity; i++) \ - { \ - struct SNAME##_entry *entry = &(_map_->buffer[i]); \ - \ - if (entry->state == CMC_ES_FILLED) \ - { \ - deallocator(entry->key, entry->value); \ - } \ - } \ - } \ - \ - memset(_map_->buffer, 0, sizeof(struct SNAME##_entry) * _map_->capacity); \ - \ - _map_->count = 0; \ - } \ - \ - void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _map_->capacity; i++) \ - { \ - struct SNAME##_entry *entry = &(_map_->buffer[i]); \ - \ - if (entry->state == CMC_ES_FILLED) \ - { \ - deallocator(entry->key, entry->value); \ - } \ - } \ - } \ - \ - _map_->alloc->free(_map_->buffer); \ - _map_->alloc->free(_map_); \ - } \ - \ - void PFX##_customize(struct SNAME *_map_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_hashmap *callbacks) \ - { \ - if (alloc) \ - _map_->alloc = alloc; \ - \ - if (callbacks) \ - _map_->callbacks = callbacks; \ - } \ - \ - bool PFX##_insert(struct SNAME *_map_, K key, V value) \ - { \ - if (PFX##_full(_map_)) \ - { \ - if (!PFX##_resize(_map_, PFX##_capacity(_map_) + 1)) \ - return false; \ - } \ - \ - size_t hash = _map_->hash(key); \ - size_t original_pos = hash % _map_->capacity; \ - size_t pos = original_pos; \ - \ - struct 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 < pos - original_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(struct SNAME *_map_, K key, V new_value, V *old_value) \ - { \ - struct 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(struct SNAME *_map_, K key, V *out_value) \ - { \ - struct SNAME##_entry *result = PFX##_impl_get_entry(_map_, key); \ - \ - if (result == NULL) \ - return false; \ - \ - if (out_value) \ - *out_value = result->value; \ - \ - result->key = (K){0}; \ - result->value = (V){0}; \ - result->dist = 0; \ - result->state = CMC_ES_DELETED; \ - \ - _map_->count--; \ - \ - return true; \ - } \ - \ - bool PFX##_max(struct SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - struct SNAME##_iter iter; \ - PFX##_iter_init(&iter, _map_); \ - \ - K max_key = PFX##_iter_key(&iter); \ - V max_val = PFX##_iter_value(&iter); \ - \ - PFX##_iter_next(&iter); \ - \ - for (; !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - K iter_key = PFX##_iter_key(&iter); \ - V iter_val = PFX##_iter_value(&iter); \ - \ - if (_map_->cmp(iter_key, max_key) > 0) \ - { \ - max_key = iter_key; \ - max_val = iter_val; \ - } \ - } \ - \ - if (key) \ - *key = max_key; \ - if (value) \ - *value = max_val; \ - \ - return true; \ - } \ - \ - bool PFX##_min(struct SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - struct SNAME##_iter iter; \ - PFX##_iter_init(&iter, _map_); \ - \ - K min_key = PFX##_iter_key(&iter); \ - V min_val = PFX##_iter_value(&iter); \ - \ - PFX##_iter_next(&iter); \ - \ - for (; !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - K iter_key = PFX##_iter_key(&iter); \ - V iter_val = PFX##_iter_value(&iter); \ - \ - if (_map_->cmp(iter_key, min_key) < 0) \ - { \ - min_key = iter_key; \ - min_val = iter_val; \ - } \ - } \ - \ - if (key) \ - *key = min_key; \ - if (value) \ - *value = min_val; \ - \ - return true; \ - } \ - \ - V PFX##_get(struct SNAME *_map_, K key) \ - { \ - struct SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ - \ - if (!entry) \ - return (V){0}; \ - \ - return entry->value; \ - } \ - \ - V *PFX##_get_ref(struct SNAME *_map_, K key) \ - { \ - struct SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ - \ - if (!entry) \ - return NULL; \ - \ - return &(entry->value); \ - } \ - \ - bool PFX##_contains(struct SNAME *_map_, K key) \ - { \ - return PFX##_impl_get_entry(_map_, key) != NULL; \ - } \ - \ - bool PFX##_empty(struct SNAME *_map_) \ - { \ - return _map_->count == 0; \ - } \ - \ - bool PFX##_full(struct SNAME *_map_) \ - { \ - return (double)PFX##_capacity(_map_) * PFX##_load(_map_) <= (double)PFX##_count(_map_); \ - } \ - \ - size_t PFX##_count(struct SNAME *_map_) \ - { \ - return _map_->count; \ - } \ - \ - size_t PFX##_capacity(struct SNAME *_map_) \ - { \ - return _map_->capacity; \ - } \ - \ - double PFX##_load(struct SNAME *_map_) \ - { \ - return _map_->load; \ - } \ - \ - bool PFX##_resize(struct SNAME *_map_, size_t capacity) \ - { \ - if (PFX##_capacity(_map_) == capacity) \ - return true; \ - \ - if (PFX##_capacity(_map_) > capacity / _map_->load) \ - return true; \ - \ - /* Prevent integer overflow */ \ - if (capacity >= UINTMAX_MAX * _map_->load) \ - return false; \ - \ - /* Calculate required capacity based on the prime numbers */ \ - size_t theoretical_size = PFX##_impl_calculate_size(capacity); \ - \ - /* Not possible to shrink with current available prime numbers */ \ - if (theoretical_size < _map_->count / _map_->load) \ - return false; \ - \ - struct SNAME *_new_map_ = PFX##_new_custom(capacity, _map_->load, _map_->cmp, _map_->hash, \ - _map_->alloc, _map_->callbacks); \ - \ - if (!_new_map_) \ - return false; \ - \ - struct 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 (PFX##_count(_map_) != PFX##_count(_new_map_)) \ - { \ - PFX##_free(_new_map_, NULL); \ - return false; \ - } \ - \ - struct 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; \ - } \ - \ - struct SNAME *PFX##_copy_of(struct SNAME *_map_, K (*key_copy_func)(K), \ - V (*value_copy_func)(V)) \ - { \ - struct SNAME *result = PFX##_new_custom(_map_->capacity, _map_->load, _map_->cmp, \ - _map_->hash, _map_->alloc, _map_->callbacks); \ - \ - if (!result) \ - return NULL; \ - \ - if (key_copy_func || value_copy_func) \ - { \ - for (size_t i = 0; i < _map_->capacity; i++) \ - { \ - struct SNAME##_entry *scan = &(_map_->buffer[i]); \ - \ - if (scan->state != CMC_ES_EMPTY) \ - { \ - struct 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(struct SNAME##_entry) * _map_->capacity); \ - \ - result->count = _map_->count; \ - \ - return result; \ - } \ - \ - bool PFX##_equals(struct SNAME *_map1_, struct SNAME *_map2_, int (*value_comparator)(V, V)) \ - { \ - if (PFX##_count(_map1_) != PFX##_count(_map2_)) \ - return false; \ - \ - struct SNAME##_iter iter; \ - PFX##_iter_init(&iter, _map1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - struct 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; \ - } \ - \ - struct cmc_string PFX##_to_string(struct SNAME *_map_) \ - { \ - struct cmc_string str; \ - struct SNAME *m_ = _map_; \ - \ - int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_hashmap, \ - #SNAME, #K, #V, m_, m_->buffer, m_->capacity, m_->count, \ - m_->load, m_->cmp, m_->hash, m_->alloc, m_->callbacks); \ - \ - if (n < 0 || n == (int)cmc_string_len) \ - return (struct cmc_string){0}; \ - \ - str.s[n] = '\0'; \ - \ - return str; \ - } \ - \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ - { \ - struct SNAME##_iter *iter = target->alloc->malloc(sizeof(struct SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(struct SNAME##_iter *iter) \ - { \ - iter->target->alloc->free(iter); \ - } \ - \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ - { \ - memset(iter, 0, sizeof(struct 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(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(struct 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(struct 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(struct 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); \ - \ - struct 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(struct SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->index == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - struct 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(struct 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(struct 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(struct 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(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (K){0}; \ - \ - return iter->target->buffer[iter->cursor].key; \ - } \ - \ - V PFX##_iter_value(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){0}; \ - \ - return iter->target->buffer[iter->cursor].value; \ - } \ - \ - V *PFX##_iter_rvalue(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->target->buffer[iter->cursor].value); \ - } \ - \ - size_t PFX##_iter_index(struct SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - static struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_map_, K key) \ - { \ - size_t hash = _map_->hash(key); \ - size_t pos = hash % _map_->capacity; \ - \ - struct 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 struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_map_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _map_); \ - \ - return iter; \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_map_) \ - { \ - struct 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 struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_map_, \ + K key); \ + static size_t PFX##_impl_calculate_size(size_t required); \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_map_); \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_map_); \ + \ + struct SNAME *PFX##_new(size_t capacity, double load, \ + int (*compare)(K, K), size_t (*hash)(K)) \ + { \ + struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ + \ + 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); \ + \ + struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_map_) \ + return NULL; \ + \ + _map_->buffer = \ + alloc->calloc(real_capacity, sizeof(struct SNAME##_entry)); \ + \ + if (!_map_->buffer) \ + { \ + alloc->free(_map_); \ + return NULL; \ + } \ + \ + _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; \ + \ + _map_->alloc = alloc; \ + _map_->callbacks = NULL; \ + \ + return _map_; \ + } \ + \ + struct SNAME *PFX##_new_custom( \ + size_t capacity, double load, int (*compare)(K, K), size_t (*hash)(K), \ + struct cmc_alloc_node *alloc, struct cmc_callbacks_hashmap *callbacks) \ + { \ + 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); \ + \ + if (!alloc) \ + alloc = &cmc_alloc_node_default; \ + \ + struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_map_) \ + return NULL; \ + \ + _map_->buffer = \ + alloc->calloc(real_capacity, sizeof(struct SNAME##_entry)); \ + \ + if (!_map_->buffer) \ + { \ + alloc->free(_map_); \ + return NULL; \ + } \ + \ + _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; \ + \ + _map_->alloc = alloc; \ + _map_->callbacks = callbacks; \ + \ + return _map_; \ + } \ + \ + void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _map_->capacity; i++) \ + { \ + struct SNAME##_entry *entry = &(_map_->buffer[i]); \ + \ + if (entry->state == CMC_ES_FILLED) \ + { \ + deallocator(entry->key, entry->value); \ + } \ + } \ + } \ + \ + memset(_map_->buffer, 0, \ + sizeof(struct SNAME##_entry) * _map_->capacity); \ + \ + _map_->count = 0; \ + } \ + \ + void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _map_->capacity; i++) \ + { \ + struct SNAME##_entry *entry = &(_map_->buffer[i]); \ + \ + if (entry->state == CMC_ES_FILLED) \ + { \ + deallocator(entry->key, entry->value); \ + } \ + } \ + } \ + \ + _map_->alloc->free(_map_->buffer); \ + _map_->alloc->free(_map_); \ + } \ + \ + void PFX##_customize(struct SNAME *_map_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_hashmap *callbacks) \ + { \ + if (alloc) \ + _map_->alloc = alloc; \ + \ + if (callbacks) \ + _map_->callbacks = callbacks; \ + } \ + \ + bool PFX##_insert(struct SNAME *_map_, K key, V value) \ + { \ + if (PFX##_full(_map_)) \ + { \ + if (!PFX##_resize(_map_, PFX##_capacity(_map_) + 1)) \ + return false; \ + } \ + \ + size_t hash = _map_->hash(key); \ + size_t original_pos = hash % _map_->capacity; \ + size_t pos = original_pos; \ + \ + struct 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 < pos - original_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(struct SNAME *_map_, K key, V new_value, V *old_value) \ + { \ + struct 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(struct SNAME *_map_, K key, V *out_value) \ + { \ + struct SNAME##_entry *result = PFX##_impl_get_entry(_map_, key); \ + \ + if (result == NULL) \ + return false; \ + \ + if (out_value) \ + *out_value = result->value; \ + \ + result->key = (K){ 0 }; \ + result->value = (V){ 0 }; \ + result->dist = 0; \ + result->state = CMC_ES_DELETED; \ + \ + _map_->count--; \ + \ + return true; \ + } \ + \ + bool PFX##_max(struct SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + struct SNAME##_iter iter; \ + PFX##_iter_init(&iter, _map_); \ + \ + K max_key = PFX##_iter_key(&iter); \ + V max_val = PFX##_iter_value(&iter); \ + \ + PFX##_iter_next(&iter); \ + \ + for (; !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + K iter_key = PFX##_iter_key(&iter); \ + V iter_val = PFX##_iter_value(&iter); \ + \ + if (_map_->cmp(iter_key, max_key) > 0) \ + { \ + max_key = iter_key; \ + max_val = iter_val; \ + } \ + } \ + \ + if (key) \ + *key = max_key; \ + if (value) \ + *value = max_val; \ + \ + return true; \ + } \ + \ + bool PFX##_min(struct SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + struct SNAME##_iter iter; \ + PFX##_iter_init(&iter, _map_); \ + \ + K min_key = PFX##_iter_key(&iter); \ + V min_val = PFX##_iter_value(&iter); \ + \ + PFX##_iter_next(&iter); \ + \ + for (; !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + K iter_key = PFX##_iter_key(&iter); \ + V iter_val = PFX##_iter_value(&iter); \ + \ + if (_map_->cmp(iter_key, min_key) < 0) \ + { \ + min_key = iter_key; \ + min_val = iter_val; \ + } \ + } \ + \ + if (key) \ + *key = min_key; \ + if (value) \ + *value = min_val; \ + \ + return true; \ + } \ + \ + V PFX##_get(struct SNAME *_map_, K key) \ + { \ + struct SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ + \ + if (!entry) \ + return (V){ 0 }; \ + \ + return entry->value; \ + } \ + \ + V *PFX##_get_ref(struct SNAME *_map_, K key) \ + { \ + struct SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ + \ + if (!entry) \ + return NULL; \ + \ + return &(entry->value); \ + } \ + \ + bool PFX##_contains(struct SNAME *_map_, K key) \ + { \ + return PFX##_impl_get_entry(_map_, key) != NULL; \ + } \ + \ + bool PFX##_empty(struct SNAME *_map_) \ + { \ + return _map_->count == 0; \ + } \ + \ + bool PFX##_full(struct SNAME *_map_) \ + { \ + return (double)PFX##_capacity(_map_) * PFX##_load(_map_) <= \ + (double)PFX##_count(_map_); \ + } \ + \ + size_t PFX##_count(struct SNAME *_map_) \ + { \ + return _map_->count; \ + } \ + \ + size_t PFX##_capacity(struct SNAME *_map_) \ + { \ + return _map_->capacity; \ + } \ + \ + double PFX##_load(struct SNAME *_map_) \ + { \ + return _map_->load; \ + } \ + \ + bool PFX##_resize(struct SNAME *_map_, size_t capacity) \ + { \ + if (PFX##_capacity(_map_) == capacity) \ + return true; \ + \ + if (PFX##_capacity(_map_) > capacity / _map_->load) \ + return true; \ + \ + /* Prevent integer overflow */ \ + if (capacity >= UINTMAX_MAX * _map_->load) \ + return false; \ + \ + /* Calculate required capacity based on the prime numbers */ \ + size_t theoretical_size = PFX##_impl_calculate_size(capacity); \ + \ + /* Not possible to shrink with current available prime numbers */ \ + if (theoretical_size < _map_->count / _map_->load) \ + return false; \ + \ + struct SNAME *_new_map_ = \ + PFX##_new_custom(capacity, _map_->load, _map_->cmp, _map_->hash, \ + _map_->alloc, _map_->callbacks); \ + \ + if (!_new_map_) \ + return false; \ + \ + struct 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 (PFX##_count(_map_) != PFX##_count(_new_map_)) \ + { \ + PFX##_free(_new_map_, NULL); \ + return false; \ + } \ + \ + struct 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; \ + } \ + \ + struct SNAME *PFX##_copy_of(struct SNAME *_map_, K (*key_copy_func)(K), \ + V (*value_copy_func)(V)) \ + { \ + struct SNAME *result = \ + PFX##_new_custom(_map_->capacity, _map_->load, _map_->cmp, \ + _map_->hash, _map_->alloc, _map_->callbacks); \ + \ + if (!result) \ + return NULL; \ + \ + if (key_copy_func || value_copy_func) \ + { \ + for (size_t i = 0; i < _map_->capacity; i++) \ + { \ + struct SNAME##_entry *scan = &(_map_->buffer[i]); \ + \ + if (scan->state != CMC_ES_EMPTY) \ + { \ + struct 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(struct SNAME##_entry) * _map_->capacity); \ + \ + result->count = _map_->count; \ + \ + return result; \ + } \ + \ + bool PFX##_equals(struct SNAME *_map1_, struct SNAME *_map2_, \ + int (*value_comparator)(V, V)) \ + { \ + if (PFX##_count(_map1_) != PFX##_count(_map2_)) \ + return false; \ + \ + struct SNAME##_iter iter; \ + PFX##_iter_init(&iter, _map1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); \ + PFX##_iter_next(&iter)) \ + { \ + struct 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; \ + } \ + \ + struct cmc_string PFX##_to_string(struct SNAME *_map_) \ + { \ + struct cmc_string str; \ + struct SNAME *m_ = _map_; \ + \ + int n = \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_hashmap, #SNAME, \ + #K, #V, m_, m_->buffer, m_->capacity, m_->count, \ + m_->load, m_->cmp, m_->hash, m_->alloc, m_->callbacks); \ + \ + if (n < 0 || n == (int)cmc_string_len) \ + return (struct cmc_string){ 0 }; \ + \ + str.s[n] = '\0'; \ + \ + return str; \ + } \ + \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ + { \ + struct SNAME##_iter *iter = \ + target->alloc->malloc(sizeof(struct SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + void PFX##_iter_free(struct SNAME##_iter *iter) \ + { \ + iter->target->alloc->free(iter); \ + } \ + \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ + { \ + memset(iter, 0, sizeof(struct 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(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + bool PFX##_iter_end(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + void PFX##_iter_to_start(struct 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(struct 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(struct 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); \ + \ + struct 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(struct SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->index == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + struct 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(struct 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(struct 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(struct 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(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return (K){ 0 }; \ + \ + return iter->target->buffer[iter->cursor].key; \ + } \ + \ + V PFX##_iter_value(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return (V){ 0 }; \ + \ + return iter->target->buffer[iter->cursor].value; \ + } \ + \ + V *PFX##_iter_rvalue(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return NULL; \ + \ + return &(iter->target->buffer[iter->cursor].value); \ + } \ + \ + size_t PFX##_iter_index(struct SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + static struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_map_, \ + K key) \ + { \ + size_t hash = _map_->hash(key); \ + size_t pos = hash % _map_->capacity; \ + \ + struct 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 struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_map_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _map_); \ + \ + return iter; \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_map_) \ + { \ + struct 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 e1b0c1a..87a6f4f 100644 --- a/src/cmc/hashset.h +++ b/src/cmc/hashset.h @@ -21,13 +21,13 @@ #include #include -#include #include +#include #include -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Core functionalities of the C Macro Collections Library - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ #ifndef CMC_CORE_H #define CMC_CORE_H @@ -46,7 +46,8 @@ static const size_t cmc_string_len = 400; /** * struct cmc_alloc_node * - * Custom allocation node. Allows collections to use custom allocation functions. + * Custom allocation node. Allows collections to use custom allocation + * functions. */ struct cmc_alloc_node { @@ -56,13 +57,14 @@ struct cmc_alloc_node void (*free)(void *); }; -static struct cmc_alloc_node cmc_alloc_node_default = {malloc, calloc, realloc, free}; +static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, + free }; #endif /* CMC_CORE_H */ -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Hashtable Implementation - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ #ifndef CMC_IMPL_HASHTABLE_STATE #define CMC_IMPL_HASHTABLE_STATE @@ -78,22 +80,52 @@ enum cmc_entry_state #ifndef CMC_IMPL_HASHTABLE_PRIMES #define CMC_IMPL_HASHTABLE_PRIMES -static const size_t cmc_hashtable_primes[] = - {53, 97, 191, 383, 769, 1531, 3067, 6143, 12289, 24571, 49157, 98299, 196613, 393209, 786431, - 1572869, 3145721, 6291449, 12582917, 25165813, 50331653, 100663291, 201326611, 402653189, - 805306357, 1610612741, 3221225473, 6442450939, 12884901893, 25769803799, 51539607551, - 103079215111, 206158430209, 412316860441, 824633720831, 1649267441651, 3298534883309, - 6597069766657, 13194139533299, 26388279066623, 52776558133303, 105553116266489, - 211106232532969, 422212465066001, 844424930131963, 1688849860263953, 3377699720527861, - 6755399441055731, 13510798882111483, 27021597764222939, 54043195528445957, 108086391056891903, - 216172782113783773, 432345564227567621, 864691128455135207, 1729382256910270481, - 3458764513820540933, 6917529027641081903, 13835058055282163729llu}; +// clang-format off +static const size_t cmc_hashtable_primes[] = { + /* < 1e3 */ + 53, 97, 191, 383, 769, + /* < 1e4 */ + 1531, 3067, 6143, + /* < 1e5 */ + 12289, 24571, 49157, 98299, + /* < 1e6 */ + 196613, 393209, 786431, + /* < 1e7 */ + 1572869, 3145721, 6291449, + /* < 1e8 */ + 12582917, 25165813, 50331653, + /* < 1e9 */ + 100663291, 201326611, 402653189, 805306357, + /* < 1e10 */ + 1610612741, 3221225473, 6442450939, + /* < 1e11 */ + 12884901893, 25769803799, 51539607551, + /* < 1e12 */ + 103079215111, 206158430209, 412316860441, 824633720831, + /* < 1e13 */ + 1649267441651, 3298534883309, 6597069766657, + /* < 1e14 */ + 13194139533299, 26388279066623, 52776558133303, + /* < 1e15 */ + 105553116266489, 211106232532969, 422212465066001, 844424930131963, + /* < 1e16 */ + 1688849860263953, 3377699720527861, 6755399441055731, + /* < 1e17 */ + 13510798882111483, 27021597764222939, 54043195528445957, + /* < 1e18 */ + 108086391056891903, 216172782113783773, 432345564227567621, 864691128455135207, + /* < 1e19 */ + 1729382256910270481, 3458764513820540933, 6917529027641081903, + /* < 1e20 */ + 13835058055282163729llu, +}; +// clang-format on #endif /* CMC_IMPL_HASHTABLE_PRIMES */ -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * HashSet specific - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ /* to_string format */ static const char *cmc_string_fmt_hashset = "struct %s<%s> " "at %p { " @@ -131,1028 +163,1068 @@ struct cmc_callbacks_hashset #define CMC_WRAPGEN_HASHSET_SOURCE(PFX, SNAME, K, V) \ CMC_GENERATE_HASHSET_SOURCE(PFX, SNAME, V) -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Header - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_HASHSET_HEADER(PFX, SNAME, V) \ - \ - /* Hashset Structure */ \ - struct SNAME \ - { \ - /* Array of Entries */ \ - struct SNAME##_entry *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 (*it_start)(struct SNAME *); \ - \ - /* Function that returns an iterator to the end of the hashset */ \ - struct SNAME##_iter (*it_end)(struct SNAME *); \ - \ - /* Custom allocation functions */ \ - struct cmc_alloc_node *alloc; \ - \ - /* Custom callback functions */ \ - struct cmc_callbacks_hashset *callbacks; \ - }; \ - \ - struct SNAME##_entry \ - { \ - /* 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 state; \ - }; \ - \ - /* Hashset Iterator */ \ - struct SNAME##_iter \ - { \ - /* Target Hashset */ \ - struct SNAME *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* The index of the first element */ \ - size_t first; \ - \ - /* The index of the last element */ \ - size_t last; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - }; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - struct SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), \ - size_t (*hash)(V)); \ - struct SNAME *PFX##_new_custom(size_t capacity, double load, int (*compare)(V, V), \ - size_t (*hash)(V), struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_hashset *callbacks); \ - void PFX##_clear(struct SNAME *_set_, void (*deallocator)(V)); \ - void PFX##_free(struct SNAME *_set_, void (*deallocator)(V)); \ - /* Customization of Allocation and Callbacks */ \ - void PFX##_customize(struct SNAME *_set_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_hashset *callbacks); \ - /* Collection Input and Output */ \ - bool PFX##_insert(struct SNAME *_set_, V element); \ - bool PFX##_remove(struct SNAME *_set_, V element); \ - /* Element Access */ \ - bool PFX##_max(struct SNAME *_set_, V *value); \ - bool PFX##_min(struct SNAME *_set_, V *value); \ - /* Collection State */ \ - bool PFX##_contains(struct SNAME *_set_, V element); \ - bool PFX##_empty(struct SNAME *_set_); \ - bool PFX##_full(struct SNAME *_set_); \ - size_t PFX##_count(struct SNAME *_set_); \ - size_t PFX##_capacity(struct SNAME *_set_); \ - double PFX##_load(struct SNAME *_set_); \ - /* Collection Utility */ \ - bool PFX##_resize(struct SNAME *_set_, size_t capacity); \ - struct SNAME *PFX##_copy_of(struct SNAME *_set_, V (*copy_func)(V)); \ - bool PFX##_equals(struct SNAME *_set1_, struct SNAME *_set2_); \ - struct cmc_string PFX##_to_string(struct SNAME *_set_); \ - \ - /* Set Operations */ \ - struct SNAME *PFX##_union(struct SNAME *_set1_, struct SNAME *_set2_); \ - struct SNAME *PFX##_intersection(struct SNAME *_set1_, struct SNAME *_set2_); \ - struct SNAME *PFX##_difference(struct SNAME *_set1_, struct SNAME *_set2_); \ - struct SNAME *PFX##_symmetric_difference(struct SNAME *_set1_, struct SNAME *_set2_); \ - bool PFX##_is_subset(struct SNAME *_set1_, struct SNAME *_set2_); \ - bool PFX##_is_superset(struct SNAME *_set1_, struct SNAME *_set2_); \ - bool PFX##_is_proper_subset(struct SNAME *_set1_, struct SNAME *_set2_); \ - bool PFX##_is_proper_superset(struct SNAME *_set1_, struct SNAME *_set2_); \ - bool PFX##_is_disjointset(struct SNAME *_set1_, struct SNAME *_set2_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ - void PFX##_iter_free(struct SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(struct SNAME##_iter *iter); \ - bool PFX##_iter_end(struct SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(struct SNAME##_iter *iter); \ - void PFX##_iter_to_end(struct SNAME##_iter *iter); \ - bool PFX##_iter_next(struct SNAME##_iter *iter); \ - bool PFX##_iter_prev(struct SNAME##_iter *iter); \ - bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - V PFX##_iter_value(struct SNAME##_iter *iter); \ + * ------------------------------------------------------------------------- */ +#define CMC_GENERATE_HASHSET_HEADER(PFX, SNAME, V) \ + \ + /* Hashset Structure */ \ + struct SNAME \ + { \ + /* Array of Entries */ \ + struct SNAME##_entry *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 (*it_start)(struct SNAME *); \ + \ + /* Function that returns an iterator to the end of the hashset */ \ + struct SNAME##_iter (*it_end)(struct SNAME *); \ + \ + /* Custom allocation functions */ \ + struct cmc_alloc_node *alloc; \ + \ + /* Custom callback functions */ \ + struct cmc_callbacks_hashset *callbacks; \ + }; \ + \ + struct SNAME##_entry \ + { \ + /* 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 state; \ + }; \ + \ + /* Hashset Iterator */ \ + struct SNAME##_iter \ + { \ + /* Target Hashset */ \ + struct SNAME *target; \ + \ + /* Cursor's position (index) */ \ + size_t cursor; \ + \ + /* Keeps track of relative index to the iteration of elements */ \ + size_t index; \ + \ + /* The index of the first element */ \ + size_t first; \ + \ + /* The index of the last element */ \ + size_t last; \ + \ + /* If the iterator has reached the start of the iteration */ \ + bool start; \ + \ + /* If the iterator has reached the end of the iteration */ \ + bool end; \ + }; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + struct SNAME *PFX##_new(size_t capacity, double load, \ + int (*compare)(V, V), size_t (*hash)(V)); \ + struct SNAME *PFX##_new_custom(size_t capacity, double load, \ + int (*compare)(V, V), size_t (*hash)(V), \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_hashset *callbacks); \ + void PFX##_clear(struct SNAME *_set_, void (*deallocator)(V)); \ + void PFX##_free(struct SNAME *_set_, void (*deallocator)(V)); \ + /* Customization of Allocation and Callbacks */ \ + void PFX##_customize(struct SNAME *_set_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_hashset *callbacks); \ + /* Collection Input and Output */ \ + bool PFX##_insert(struct SNAME *_set_, V element); \ + bool PFX##_remove(struct SNAME *_set_, V element); \ + /* Element Access */ \ + bool PFX##_max(struct SNAME *_set_, V *value); \ + bool PFX##_min(struct SNAME *_set_, V *value); \ + /* Collection State */ \ + bool PFX##_contains(struct SNAME *_set_, V element); \ + bool PFX##_empty(struct SNAME *_set_); \ + bool PFX##_full(struct SNAME *_set_); \ + size_t PFX##_count(struct SNAME *_set_); \ + size_t PFX##_capacity(struct SNAME *_set_); \ + double PFX##_load(struct SNAME *_set_); \ + /* Collection Utility */ \ + bool PFX##_resize(struct SNAME *_set_, size_t capacity); \ + struct SNAME *PFX##_copy_of(struct SNAME *_set_, V (*copy_func)(V)); \ + bool PFX##_equals(struct SNAME *_set1_, struct SNAME *_set2_); \ + struct cmc_string PFX##_to_string(struct SNAME *_set_); \ + \ + /* Set Operations */ \ + struct SNAME *PFX##_union(struct SNAME *_set1_, struct SNAME *_set2_); \ + struct SNAME *PFX##_intersection(struct SNAME *_set1_, \ + struct SNAME *_set2_); \ + struct SNAME *PFX##_difference(struct SNAME *_set1_, \ + struct SNAME *_set2_); \ + struct SNAME *PFX##_symmetric_difference(struct SNAME *_set1_, \ + struct SNAME *_set2_); \ + bool PFX##_is_subset(struct SNAME *_set1_, struct SNAME *_set2_); \ + bool PFX##_is_superset(struct SNAME *_set1_, struct SNAME *_set2_); \ + bool PFX##_is_proper_subset(struct SNAME *_set1_, struct SNAME *_set2_); \ + bool PFX##_is_proper_superset(struct SNAME *_set1_, struct SNAME *_set2_); \ + bool PFX##_is_disjointset(struct SNAME *_set1_, struct SNAME *_set2_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ + void PFX##_iter_free(struct SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(struct SNAME##_iter *iter); \ + bool PFX##_iter_end(struct SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(struct SNAME##_iter *iter); \ + void PFX##_iter_to_end(struct SNAME##_iter *iter); \ + bool PFX##_iter_next(struct SNAME##_iter *iter); \ + bool PFX##_iter_prev(struct SNAME##_iter *iter); \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + V PFX##_iter_value(struct SNAME##_iter *iter); \ size_t PFX##_iter_index(struct SNAME##_iter *iter); -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Source - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_HASHSET_SOURCE(PFX, SNAME, V) \ - \ - /* Implementation Detail Functions */ \ - static struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_set_, V element); \ - static size_t PFX##_impl_calculate_size(size_t required); \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_set_); \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_set_); \ - \ - struct SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), size_t (*hash)(V)) \ - { \ - struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ - \ - 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); \ - \ - struct SNAME *_set_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_set_) \ - return NULL; \ - \ - _set_->buffer = alloc->calloc(real_capacity, sizeof(struct SNAME##_entry)); \ - \ - if (!_set_->buffer) \ - { \ - alloc->free(_set_); \ - return NULL; \ - } \ - \ - _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; \ - \ - _set_->alloc = alloc; \ - _set_->callbacks = NULL; \ - \ - return _set_; \ - } \ - \ - struct SNAME *PFX##_new_custom(size_t capacity, double load, int (*compare)(V, V), \ - size_t (*hash)(V), struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_hashset *callbacks) \ - { \ - 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); \ - \ - if (!alloc) \ - alloc = &cmc_alloc_node_default; \ - \ - struct SNAME *_set_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_set_) \ - return NULL; \ - \ - _set_->buffer = alloc->calloc(real_capacity, sizeof(struct SNAME##_entry)); \ - \ - if (!_set_->buffer) \ - { \ - alloc->free(_set_); \ - return NULL; \ - } \ - \ - _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; \ - \ - _set_->alloc = alloc; \ - _set_->callbacks = callbacks; \ - \ - return _set_; \ - } \ - \ - void PFX##_clear(struct SNAME *_set_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _set_->capacity; i++) \ - { \ - struct SNAME##_entry *entry = &(_set_->buffer[i]); \ - \ - if (entry->state == CMC_ES_FILLED) \ - { \ - deallocator(entry->value); \ - } \ - } \ - } \ - \ - memset(_set_->buffer, 0, sizeof(struct SNAME##_entry) * _set_->capacity); \ - \ - _set_->count = 0; \ - } \ - \ - void PFX##_free(struct SNAME *_set_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _set_->capacity; i++) \ - { \ - struct SNAME##_entry *entry = &(_set_->buffer[i]); \ - \ - if (entry->state == CMC_ES_FILLED) \ - { \ - deallocator(entry->value); \ - } \ - } \ - } \ - \ - _set_->alloc->free(_set_->buffer); \ - _set_->alloc->free(_set_); \ - } \ - \ - void PFX##_customize(struct SNAME *_set_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_hashset *callbacks) \ - { \ - if (alloc) \ - _set_->alloc = alloc; \ - \ - if (callbacks) \ - _set_->callbacks = callbacks; \ - } \ - \ - bool PFX##_insert(struct SNAME *_set_, V element) \ - { \ - if (PFX##_full(_set_)) \ - { \ - if (!PFX##_resize(_set_, PFX##_capacity(_set_) + 1)) \ - return false; \ - } \ - \ - size_t hash = _set_->hash(element); \ - size_t original_pos = hash % _set_->capacity; \ - size_t pos = original_pos; \ - \ - struct 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(struct SNAME *_set_, V element) \ - { \ - struct SNAME##_entry *result = PFX##_impl_get_entry(_set_, element); \ - \ - if (result == NULL) \ - return false; \ - \ - result->value = (V){0}; \ - result->dist = 0; \ - result->state = CMC_ES_DELETED; \ - \ - _set_->count--; \ - \ - return true; \ - } \ - \ - bool PFX##_max(struct SNAME *_set_, V *value) \ - { \ - if (PFX##_empty(_set_)) \ - return false; \ - \ - struct 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(struct SNAME *_set_, V *value) \ - { \ - if (PFX##_empty(_set_)) \ - return false; \ - \ - struct 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(struct SNAME *_set_, V element) \ - { \ - return PFX##_impl_get_entry(_set_, element) != NULL; \ - } \ - \ - bool PFX##_empty(struct SNAME *_set_) \ - { \ - return _set_->count == 0; \ - } \ - \ - bool PFX##_full(struct SNAME *_set_) \ - { \ - return (double)PFX##_capacity(_set_) * PFX##_load(_set_) <= (double)PFX##_count(_set_); \ - } \ - \ - size_t PFX##_count(struct SNAME *_set_) \ - { \ - return _set_->count; \ - } \ - \ - size_t PFX##_capacity(struct SNAME *_set_) \ - { \ - return _set_->capacity; \ - } \ - \ - double PFX##_load(struct SNAME *_set_) \ - { \ - return _set_->load; \ - } \ - \ - bool PFX##_resize(struct SNAME *_set_, size_t capacity) \ - { \ - if (PFX##_capacity(_set_) == capacity) \ - return true; \ - \ - if (PFX##_capacity(_set_) > capacity / PFX##_load(_set_)) \ - return true; \ - \ - /* Prevent integer overflow */ \ - if (capacity >= UINTMAX_MAX * PFX##_load(_set_)) \ - return false; \ - \ - /* Calculate required capacity based on the prime numbers */ \ - size_t theoretical_size = PFX##_impl_calculate_size(capacity); \ - \ - /* Not possible to shrink with current available prime numbers */ \ - if (theoretical_size < PFX##_count(_set_) / PFX##_load(_set_)) \ - return false; \ - \ - struct SNAME *_new_set_ = PFX##_new(capacity, PFX##_load(_set_), _set_->cmp, _set_->hash); \ - \ - if (!_new_set_) \ - return false; \ - \ - struct SNAME##_iter iter; \ - \ - for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - V value = PFX##_iter_value(&iter); \ - \ - PFX##_insert(_new_set_, value); \ - } \ - \ - if (PFX##_count(_set_) != PFX##_count(_new_set_)) \ - { \ - PFX##_free(_new_set_, NULL); \ - return false; \ - } \ - \ - struct 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; \ - } \ - \ - struct SNAME *PFX##_copy_of(struct SNAME *_set_, V (*copy_func)(V)) \ - { \ - struct SNAME *result = PFX##_new_custom(_set_->capacity, _set_->load, _set_->cmp, \ - _set_->hash, _set_->alloc, _set_->callbacks); \ - \ - if (!result) \ - return NULL; \ - \ - if (copy_func) \ - { \ - for (size_t i = 0; i < _set_->capacity; i++) \ - { \ - struct SNAME##_entry *scan = &(_set_->buffer[i]); \ - \ - if (scan->state != CMC_ES_EMPTY) \ - { \ - struct 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(struct SNAME##_entry) * _set_->capacity); \ - \ - result->count = _set_->count; \ - \ - return result; \ - } \ - \ - bool PFX##_equals(struct SNAME *_set1_, struct SNAME *_set2_) \ - { \ - if (PFX##_count(_set1_) != PFX##_count(_set2_)) \ - return false; \ - \ - if (PFX##_count(_set1_) == 0) \ - return true; \ - \ - struct 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; \ - } \ - \ - struct cmc_string PFX##_to_string(struct SNAME *_set_) \ - { \ - struct cmc_string str; \ - struct SNAME *s_ = _set_; \ - \ - int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_hashset, \ - #SNAME, #V, s_, s_->buffer, s_->capacity, s_->count, \ - s_->load, s_->cmp, s_->hash, s_->alloc, s_->callbacks); \ - \ - if (n < 0 || n == (int)cmc_string_len) \ - return (struct cmc_string){0}; \ - \ - str.s[n] = '\0'; \ - \ - return str; \ - } \ - \ - struct SNAME *PFX##_union(struct SNAME *_set1_, struct SNAME *_set2_) \ - { \ - struct SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, \ - _set1_->hash); \ - \ - if (!_set_r_) \ - return NULL; \ - \ - struct 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_; \ - } \ - \ - struct SNAME *PFX##_intersection(struct SNAME *_set1_, struct SNAME *_set2_) \ - { \ - struct SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, \ - _set1_->hash); \ - \ - if (!_set_r_) \ - return NULL; \ - \ - struct SNAME *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; \ - struct SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \ - \ - struct 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_; \ - } \ - \ - struct SNAME *PFX##_difference(struct SNAME *_set1_, struct SNAME *_set2_) \ - { \ - struct SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, \ - _set1_->hash); \ - \ - if (!_set_r_) \ - return NULL; \ - \ - struct 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_; \ - } \ - \ - struct SNAME *PFX##_symmetric_difference(struct SNAME *_set1_, struct SNAME *_set2_) \ - { \ - struct SNAME##_iter iter1, iter2; \ - \ - struct 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(struct SNAME *_set1_, struct 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; \ - \ - struct 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(struct SNAME *_set1_, struct 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(struct SNAME *_set1_, struct 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; \ - } \ - \ - struct 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(struct SNAME *_set1_, struct 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(struct SNAME *_set1_, struct SNAME *_set2_) \ - { \ - /* The intersection of an empty set with any other set will result in an empty set */ \ - if (PFX##_empty(_set1_)) \ - return true; \ - \ - struct 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; \ - } \ - \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ - { \ - struct SNAME##_iter *iter = target->alloc->malloc(sizeof(struct SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(struct SNAME##_iter *iter) \ - { \ - iter->target->alloc->free(iter); \ - } \ - \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ - { \ - memset(iter, 0, sizeof(struct 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(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(struct 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(struct 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(struct 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); \ - \ - struct 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(struct SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->index == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - struct 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(struct 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(struct 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(struct 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(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){0}; \ - \ - return iter->target->buffer[iter->cursor].value; \ - } \ - \ - size_t PFX##_iter_index(struct SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - static struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_set_, V element) \ - { \ - size_t hash = _set_->hash(element); \ - size_t pos = hash % _set_->capacity; \ - \ - struct 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 struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_set_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _set_); \ - \ - return iter; \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_set_) \ - { \ - struct 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 struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_set_, \ + V element); \ + static size_t PFX##_impl_calculate_size(size_t required); \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_set_); \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_set_); \ + \ + struct SNAME *PFX##_new(size_t capacity, double load, \ + int (*compare)(V, V), size_t (*hash)(V)) \ + { \ + struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ + \ + 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); \ + \ + struct SNAME *_set_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_set_) \ + return NULL; \ + \ + _set_->buffer = \ + alloc->calloc(real_capacity, sizeof(struct SNAME##_entry)); \ + \ + if (!_set_->buffer) \ + { \ + alloc->free(_set_); \ + return NULL; \ + } \ + \ + _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; \ + \ + _set_->alloc = alloc; \ + _set_->callbacks = NULL; \ + \ + return _set_; \ + } \ + \ + struct SNAME *PFX##_new_custom( \ + size_t capacity, double load, int (*compare)(V, V), size_t (*hash)(V), \ + struct cmc_alloc_node *alloc, struct cmc_callbacks_hashset *callbacks) \ + { \ + 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); \ + \ + if (!alloc) \ + alloc = &cmc_alloc_node_default; \ + \ + struct SNAME *_set_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_set_) \ + return NULL; \ + \ + _set_->buffer = \ + alloc->calloc(real_capacity, sizeof(struct SNAME##_entry)); \ + \ + if (!_set_->buffer) \ + { \ + alloc->free(_set_); \ + return NULL; \ + } \ + \ + _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; \ + \ + _set_->alloc = alloc; \ + _set_->callbacks = callbacks; \ + \ + return _set_; \ + } \ + \ + void PFX##_clear(struct SNAME *_set_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _set_->capacity; i++) \ + { \ + struct SNAME##_entry *entry = &(_set_->buffer[i]); \ + \ + if (entry->state == CMC_ES_FILLED) \ + { \ + deallocator(entry->value); \ + } \ + } \ + } \ + \ + memset(_set_->buffer, 0, \ + sizeof(struct SNAME##_entry) * _set_->capacity); \ + \ + _set_->count = 0; \ + } \ + \ + void PFX##_free(struct SNAME *_set_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _set_->capacity; i++) \ + { \ + struct SNAME##_entry *entry = &(_set_->buffer[i]); \ + \ + if (entry->state == CMC_ES_FILLED) \ + { \ + deallocator(entry->value); \ + } \ + } \ + } \ + \ + _set_->alloc->free(_set_->buffer); \ + _set_->alloc->free(_set_); \ + } \ + \ + void PFX##_customize(struct SNAME *_set_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_hashset *callbacks) \ + { \ + if (alloc) \ + _set_->alloc = alloc; \ + \ + if (callbacks) \ + _set_->callbacks = callbacks; \ + } \ + \ + bool PFX##_insert(struct SNAME *_set_, V element) \ + { \ + if (PFX##_full(_set_)) \ + { \ + if (!PFX##_resize(_set_, PFX##_capacity(_set_) + 1)) \ + return false; \ + } \ + \ + size_t hash = _set_->hash(element); \ + size_t original_pos = hash % _set_->capacity; \ + size_t pos = original_pos; \ + \ + struct 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(struct SNAME *_set_, V element) \ + { \ + struct SNAME##_entry *result = PFX##_impl_get_entry(_set_, element); \ + \ + if (result == NULL) \ + return false; \ + \ + result->value = (V){ 0 }; \ + result->dist = 0; \ + result->state = CMC_ES_DELETED; \ + \ + _set_->count--; \ + \ + return true; \ + } \ + \ + bool PFX##_max(struct SNAME *_set_, V *value) \ + { \ + if (PFX##_empty(_set_)) \ + return false; \ + \ + struct 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(struct SNAME *_set_, V *value) \ + { \ + if (PFX##_empty(_set_)) \ + return false; \ + \ + struct 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(struct SNAME *_set_, V element) \ + { \ + return PFX##_impl_get_entry(_set_, element) != NULL; \ + } \ + \ + bool PFX##_empty(struct SNAME *_set_) \ + { \ + return _set_->count == 0; \ + } \ + \ + bool PFX##_full(struct SNAME *_set_) \ + { \ + return (double)PFX##_capacity(_set_) * PFX##_load(_set_) <= \ + (double)PFX##_count(_set_); \ + } \ + \ + size_t PFX##_count(struct SNAME *_set_) \ + { \ + return _set_->count; \ + } \ + \ + size_t PFX##_capacity(struct SNAME *_set_) \ + { \ + return _set_->capacity; \ + } \ + \ + double PFX##_load(struct SNAME *_set_) \ + { \ + return _set_->load; \ + } \ + \ + bool PFX##_resize(struct SNAME *_set_, size_t capacity) \ + { \ + if (PFX##_capacity(_set_) == capacity) \ + return true; \ + \ + if (PFX##_capacity(_set_) > capacity / PFX##_load(_set_)) \ + return true; \ + \ + /* Prevent integer overflow */ \ + if (capacity >= UINTMAX_MAX * PFX##_load(_set_)) \ + return false; \ + \ + /* Calculate required capacity based on the prime numbers */ \ + size_t theoretical_size = PFX##_impl_calculate_size(capacity); \ + \ + /* Not possible to shrink with current available prime numbers */ \ + if (theoretical_size < PFX##_count(_set_) / PFX##_load(_set_)) \ + return false; \ + \ + struct SNAME *_new_set_ = \ + PFX##_new(capacity, PFX##_load(_set_), _set_->cmp, _set_->hash); \ + \ + if (!_new_set_) \ + return false; \ + \ + struct SNAME##_iter iter; \ + \ + for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); \ + PFX##_iter_next(&iter)) \ + { \ + V value = PFX##_iter_value(&iter); \ + \ + PFX##_insert(_new_set_, value); \ + } \ + \ + if (PFX##_count(_set_) != PFX##_count(_new_set_)) \ + { \ + PFX##_free(_new_set_, NULL); \ + return false; \ + } \ + \ + struct 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; \ + } \ + \ + struct SNAME *PFX##_copy_of(struct SNAME *_set_, V (*copy_func)(V)) \ + { \ + struct SNAME *result = \ + PFX##_new_custom(_set_->capacity, _set_->load, _set_->cmp, \ + _set_->hash, _set_->alloc, _set_->callbacks); \ + \ + if (!result) \ + return NULL; \ + \ + if (copy_func) \ + { \ + for (size_t i = 0; i < _set_->capacity; i++) \ + { \ + struct SNAME##_entry *scan = &(_set_->buffer[i]); \ + \ + if (scan->state != CMC_ES_EMPTY) \ + { \ + struct 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(struct SNAME##_entry) * _set_->capacity); \ + \ + result->count = _set_->count; \ + \ + return result; \ + } \ + \ + bool PFX##_equals(struct SNAME *_set1_, struct SNAME *_set2_) \ + { \ + if (PFX##_count(_set1_) != PFX##_count(_set2_)) \ + return false; \ + \ + if (PFX##_count(_set1_) == 0) \ + return true; \ + \ + struct 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; \ + } \ + \ + struct cmc_string PFX##_to_string(struct SNAME *_set_) \ + { \ + struct cmc_string str; \ + struct SNAME *s_ = _set_; \ + \ + int n = \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_hashset, #SNAME, \ + #V, s_, s_->buffer, s_->capacity, s_->count, s_->load, \ + s_->cmp, s_->hash, s_->alloc, s_->callbacks); \ + \ + if (n < 0 || n == (int)cmc_string_len) \ + return (struct cmc_string){ 0 }; \ + \ + str.s[n] = '\0'; \ + \ + return str; \ + } \ + \ + struct SNAME *PFX##_union(struct SNAME *_set1_, struct SNAME *_set2_) \ + { \ + struct SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, \ + _set1_->cmp, _set1_->hash); \ + \ + if (!_set_r_) \ + return NULL; \ + \ + struct 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_; \ + } \ + \ + struct SNAME *PFX##_intersection(struct SNAME *_set1_, \ + struct SNAME *_set2_) \ + { \ + struct SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, \ + _set1_->cmp, _set1_->hash); \ + \ + if (!_set_r_) \ + return NULL; \ + \ + struct SNAME *_set_A_ = \ + _set1_->count < _set2_->count ? _set1_ : _set2_; \ + struct SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \ + \ + struct 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_; \ + } \ + \ + struct SNAME *PFX##_difference(struct SNAME *_set1_, struct SNAME *_set2_) \ + { \ + struct SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, \ + _set1_->cmp, _set1_->hash); \ + \ + if (!_set_r_) \ + return NULL; \ + \ + struct 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_; \ + } \ + \ + struct SNAME *PFX##_symmetric_difference(struct SNAME *_set1_, \ + struct SNAME *_set2_) \ + { \ + struct SNAME##_iter iter1, iter2; \ + \ + struct 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(struct SNAME *_set1_, struct 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; \ + \ + struct 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(struct SNAME *_set1_, struct 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(struct SNAME *_set1_, struct 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; \ + } \ + \ + struct 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(struct SNAME *_set1_, struct 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(struct SNAME *_set1_, struct SNAME *_set2_) \ + { \ + /* The intersection of an empty set with any other set will result */ \ + /* in an empty set */ \ + if (PFX##_empty(_set1_)) \ + return true; \ + \ + struct 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; \ + } \ + \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ + { \ + struct SNAME##_iter *iter = \ + target->alloc->malloc(sizeof(struct SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + void PFX##_iter_free(struct SNAME##_iter *iter) \ + { \ + iter->target->alloc->free(iter); \ + } \ + \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ + { \ + memset(iter, 0, sizeof(struct 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(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + bool PFX##_iter_end(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + void PFX##_iter_to_start(struct 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(struct 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(struct 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); \ + \ + struct 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(struct SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->index == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + struct 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(struct 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(struct 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(struct 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(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return (V){ 0 }; \ + \ + return iter->target->buffer[iter->cursor].value; \ + } \ + \ + size_t PFX##_iter_index(struct SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + static struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_set_, \ + V element) \ + { \ + size_t hash = _set_->hash(element); \ + size_t pos = hash % _set_->capacity; \ + \ + struct 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 struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_set_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _set_); \ + \ + return iter; \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_set_) \ + { \ + struct 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 7d3cc06..a5d2a5d 100644 --- a/src/cmc/heap.h +++ b/src/cmc/heap.h @@ -32,13 +32,13 @@ #include #include -#include #include +#include #include -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Core functionalities of the C Macro Collections Library - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ #ifndef CMC_CORE_H #define CMC_CORE_H @@ -57,7 +57,8 @@ static const size_t cmc_string_len = 400; /** * struct cmc_alloc_node * - * Custom allocation node. Allows collections to use custom allocation functions. + * Custom allocation node. Allows collections to use custom allocation + * functions. */ struct cmc_alloc_node { @@ -67,13 +68,14 @@ struct cmc_alloc_node void (*free)(void *); }; -static struct cmc_alloc_node cmc_alloc_node_default = {malloc, calloc, realloc, free}; +static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, + free }; #endif /* CMC_CORE_H */ -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Heap Implementation - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ #ifndef CMC_IMPL_HEAP_ORDER #define CMC_IMPL_HEAP_ORDER @@ -85,9 +87,9 @@ enum cmc_heap_order #endif /* CMC_IMPL_HEAP_ORDER */ -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Heap specific - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ /* to_string format */ static const char *cmc_string_fmt_heap = "struct %s<%s> " "at %p { " @@ -124,630 +126,638 @@ struct cmc_callbacks_heap #define CMC_WRAPGEN_HEAP_SOURCE(PFX, SNAME, K, V) \ CMC_GENERATE_HEAP_SOURCE(PFX, SNAME, V) -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Header - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_HEAP_HEADER(PFX, SNAME, V) \ - \ - /* Heap Structure */ \ - struct SNAME \ - { \ - /* 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 HO; \ - \ - /* Element comparison function */ \ - int (*cmp)(V, V); \ - \ - /* Function that returns an iterator to the start of the heap */ \ - struct SNAME##_iter (*it_start)(struct SNAME *); \ - \ - /* Function that returns an iterator to the end of the heap */ \ - struct SNAME##_iter (*it_end)(struct SNAME *); \ - \ - /* Custom allocation functions */ \ - struct cmc_alloc_node *alloc; \ - \ - /* Custom callback functions */ \ - struct cmc_callbacks_heap *callbacks; \ - }; \ - \ - /* Heap Iterator */ \ - struct SNAME##_iter \ - { \ - /* Target heap */ \ - struct SNAME *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; \ - }; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - struct SNAME *PFX##_new(size_t capacity, enum cmc_heap_order HO, int (*compare)(V, V)); \ - struct SNAME *PFX##_new_custom(size_t capacity, enum cmc_heap_order HO, int (*compare)(V, V), \ - struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_heap *callbacks); \ - void PFX##_clear(struct SNAME *_heap_, void (*deallocator)(V)); \ - void PFX##_free(struct SNAME *_heap_, void (*deallocator)(V)); \ - /* Customization of Allocation and Callbacks */ \ - void PFX##_customize(struct SNAME *_heap_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_heap *callbacks); \ - /* Collection Input and Output */ \ - bool PFX##_insert(struct SNAME *_heap_, V element); \ - bool PFX##_remove(struct SNAME *_heap_, V *result); \ - /* Element Access */ \ - V PFX##_peek(struct SNAME *_heap_); \ - /* Collection State */ \ - bool PFX##_contains(struct SNAME *_heap_, V element); \ - bool PFX##_empty(struct SNAME *_heap_); \ - bool PFX##_full(struct SNAME *_heap_); \ - size_t PFX##_count(struct SNAME *_heap_); \ - size_t PFX##_capacity(struct SNAME *_heap_); \ - /* Collection Utility */ \ - bool PFX##_resize(struct SNAME *_heap_, size_t capacity); \ - struct SNAME *PFX##_copy_of(struct SNAME *_heap_, V (*copy_func)(V)); \ - bool PFX##_equals(struct SNAME *_heap1_, struct SNAME *_heap2_); \ - struct cmc_string PFX##_to_string(struct SNAME *_heap_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ - void PFX##_iter_free(struct SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(struct SNAME##_iter *iter); \ - bool PFX##_iter_end(struct SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(struct SNAME##_iter *iter); \ - void PFX##_iter_to_end(struct SNAME##_iter *iter); \ - bool PFX##_iter_next(struct SNAME##_iter *iter); \ - bool PFX##_iter_prev(struct SNAME##_iter *iter); \ - bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - V PFX##_iter_value(struct SNAME##_iter *iter); \ + * ------------------------------------------------------------------------- */ +#define CMC_GENERATE_HEAP_HEADER(PFX, SNAME, V) \ + \ + /* Heap Structure */ \ + struct SNAME \ + { \ + /* 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 HO; \ + \ + /* Element comparison function */ \ + int (*cmp)(V, V); \ + \ + /* Function that returns an iterator to the start of the heap */ \ + struct SNAME##_iter (*it_start)(struct SNAME *); \ + \ + /* Function that returns an iterator to the end of the heap */ \ + struct SNAME##_iter (*it_end)(struct SNAME *); \ + \ + /* Custom allocation functions */ \ + struct cmc_alloc_node *alloc; \ + \ + /* Custom callback functions */ \ + struct cmc_callbacks_heap *callbacks; \ + }; \ + \ + /* Heap Iterator */ \ + struct SNAME##_iter \ + { \ + /* Target heap */ \ + struct SNAME *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; \ + }; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + struct SNAME *PFX##_new(size_t capacity, enum cmc_heap_order HO, \ + int (*compare)(V, V)); \ + struct SNAME *PFX##_new_custom( \ + size_t capacity, enum cmc_heap_order HO, int (*compare)(V, V), \ + struct cmc_alloc_node *alloc, struct cmc_callbacks_heap *callbacks); \ + void PFX##_clear(struct SNAME *_heap_, void (*deallocator)(V)); \ + void PFX##_free(struct SNAME *_heap_, void (*deallocator)(V)); \ + /* Customization of Allocation and Callbacks */ \ + void PFX##_customize(struct SNAME *_heap_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_heap *callbacks); \ + /* Collection Input and Output */ \ + bool PFX##_insert(struct SNAME *_heap_, V element); \ + bool PFX##_remove(struct SNAME *_heap_, V *result); \ + /* Element Access */ \ + V PFX##_peek(struct SNAME *_heap_); \ + /* Collection State */ \ + bool PFX##_contains(struct SNAME *_heap_, V element); \ + bool PFX##_empty(struct SNAME *_heap_); \ + bool PFX##_full(struct SNAME *_heap_); \ + size_t PFX##_count(struct SNAME *_heap_); \ + size_t PFX##_capacity(struct SNAME *_heap_); \ + /* Collection Utility */ \ + bool PFX##_resize(struct SNAME *_heap_, size_t capacity); \ + struct SNAME *PFX##_copy_of(struct SNAME *_heap_, V (*copy_func)(V)); \ + bool PFX##_equals(struct SNAME *_heap1_, struct SNAME *_heap2_); \ + struct cmc_string PFX##_to_string(struct SNAME *_heap_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ + void PFX##_iter_free(struct SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(struct SNAME##_iter *iter); \ + bool PFX##_iter_end(struct SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(struct SNAME##_iter *iter); \ + void PFX##_iter_to_end(struct SNAME##_iter *iter); \ + bool PFX##_iter_next(struct SNAME##_iter *iter); \ + bool PFX##_iter_prev(struct SNAME##_iter *iter); \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + V PFX##_iter_value(struct SNAME##_iter *iter); \ size_t PFX##_iter_index(struct SNAME##_iter *iter); -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Source - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_HEAP_SOURCE(PFX, SNAME, V) \ - \ - /* Implementation Detail Functions */ \ - static bool PFX##_impl_float_up(struct SNAME *_heap_, size_t index); \ - static bool PFX##_impl_float_down(struct SNAME *_heap_, size_t index); \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_heap_); \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_heap_); \ - \ - struct SNAME *PFX##_new(size_t capacity, enum cmc_heap_order HO, int (*compare)(V, V)) \ - { \ - struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ - \ - if (capacity < 1) \ - return NULL; \ - \ - if (HO != cmc_min_heap && HO != cmc_max_heap) \ - return NULL; \ - \ - struct SNAME *_heap_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_heap_) \ - return NULL; \ - \ - _heap_->buffer = alloc->calloc(capacity, sizeof(V)); \ - \ - if (!_heap_->buffer) \ - { \ - alloc->free(_heap_); \ - return NULL; \ - } \ - \ - _heap_->capacity = capacity; \ - _heap_->count = 0; \ - _heap_->HO = HO; \ - _heap_->cmp = compare; \ - \ - _heap_->it_start = PFX##_impl_it_start; \ - _heap_->it_end = PFX##_impl_it_end; \ - \ - _heap_->alloc = alloc; \ - _heap_->callbacks = NULL; \ - \ - return _heap_; \ - } \ - \ - struct SNAME *PFX##_new_custom(size_t capacity, enum cmc_heap_order HO, int (*compare)(V, V), \ - struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_heap *callbacks) \ - { \ - if (capacity < 1) \ - return NULL; \ - \ - if (HO != cmc_min_heap && HO != cmc_max_heap) \ - return NULL; \ - \ - if (!alloc) \ - alloc = &cmc_alloc_node_default; \ - \ - struct SNAME *_heap_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_heap_) \ - return NULL; \ - \ - _heap_->buffer = alloc->calloc(capacity, sizeof(V)); \ - \ - if (!_heap_->buffer) \ - { \ - alloc->free(_heap_); \ - return NULL; \ - } \ - \ - _heap_->capacity = capacity; \ - _heap_->count = 0; \ - _heap_->HO = HO; \ - _heap_->cmp = compare; \ - \ - _heap_->it_start = PFX##_impl_it_start; \ - _heap_->it_end = PFX##_impl_it_end; \ - \ - _heap_->alloc = alloc; \ - _heap_->callbacks = callbacks; \ - \ - return _heap_; \ - } \ - \ - void PFX##_clear(struct SNAME *_heap_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _heap_->count; i++) \ - { \ - deallocator(_heap_->buffer[i]); \ - } \ - } \ - \ - memset(_heap_->buffer, 0, sizeof(V) * _heap_->capacity); \ - \ - _heap_->count = 0; \ - } \ - \ - void PFX##_free(struct SNAME *_heap_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _heap_->count; i++) \ - { \ - deallocator(_heap_->buffer[i]); \ - } \ - } \ - \ - _heap_->alloc->free(_heap_->buffer); \ - _heap_->alloc->free(_heap_); \ - } \ - \ - void PFX##_customize(struct SNAME *_heap_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_heap *callbacks) \ - { \ - if (alloc) \ - _heap_->alloc = alloc; \ - \ - if (callbacks) \ - _heap_->callbacks = callbacks; \ - } \ - \ - bool PFX##_insert(struct SNAME *_heap_, V element) \ - { \ - if (PFX##_full(_heap_)) \ - { \ - if (!PFX##_resize(_heap_, PFX##_count(_heap_) * 2)) \ - return false; \ - } \ - \ - if (PFX##_empty(_heap_)) \ - { \ - _heap_->buffer[_heap_->count++] = element; \ - return true; \ - } \ - \ - _heap_->buffer[_heap_->count++] = element; \ - \ - if (!PFX##_impl_float_up(_heap_, _heap_->count - 1)) \ - return false; \ - \ - return true; \ - } \ - \ - bool PFX##_remove(struct SNAME *_heap_, V *result) \ - { \ - if (PFX##_empty(_heap_)) \ - return false; \ - \ - *result = _heap_->buffer[0]; \ - _heap_->buffer[0] = _heap_->buffer[_heap_->count - 1]; \ - _heap_->buffer[_heap_->count - 1] = (V){0}; \ - \ - _heap_->count--; \ - \ - if (!PFX##_impl_float_down(_heap_, 0)) \ - return false; \ - \ - return true; \ - } \ - \ - V PFX##_peek(struct SNAME *_heap_) \ - { \ - if (PFX##_empty(_heap_)) \ - return (V){0}; \ - \ - return _heap_->buffer[0]; \ - } \ - \ - bool PFX##_contains(struct SNAME *_heap_, V element) \ - { \ - for (size_t i = 0; i < _heap_->count; i++) \ - { \ - if (_heap_->cmp(_heap_->buffer[i], element) == 0) \ - return true; \ - } \ - \ - return false; \ - } \ - \ - bool PFX##_empty(struct SNAME *_heap_) \ - { \ - return _heap_->count == 0; \ - } \ - \ - bool PFX##_full(struct SNAME *_heap_) \ - { \ - return _heap_->count >= _heap_->capacity; \ - } \ - \ - size_t PFX##_count(struct SNAME *_heap_) \ - { \ - return _heap_->count; \ - } \ - \ - size_t PFX##_capacity(struct SNAME *_heap_) \ - { \ - return _heap_->capacity; \ - } \ - \ - bool PFX##_resize(struct SNAME *_heap_, size_t capacity) \ - { \ - if (PFX##_capacity(_heap_) == capacity) \ - return true; \ - \ - if (capacity < PFX##_count(_heap_)) \ - return false; \ - \ - V *new_buffer = _heap_->alloc->realloc(_heap_->buffer, sizeof(V) * capacity); \ - \ - if (!new_buffer) \ - return false; \ - \ - _heap_->buffer = new_buffer; \ - _heap_->capacity = capacity; \ - \ - return true; \ - } \ - \ - struct SNAME *PFX##_copy_of(struct SNAME *_heap_, V (*copy_func)(V)) \ - { \ - struct SNAME *result = PFX##_new_custom(_heap_->capacity, _heap_->HO, _heap_->cmp, \ - _heap_->alloc, _heap_->callbacks); \ - \ - if (!result) \ - return NULL; \ - \ - if (copy_func) \ - { \ - for (size_t i = 0; i < _heap_->count; i++) \ - result->buffer[i] = copy_func(_heap_->buffer[i]); \ - } \ - else \ - memcpy(result->buffer, _heap_->buffer, sizeof(V) * _heap_->count); \ - \ - result->count = _heap_->count; \ - \ - return result; \ - } \ - \ - bool PFX##_equals(struct SNAME *_heap1_, struct SNAME *_heap2_) \ - { \ - if (PFX##_count(_heap1_) != PFX##_count(_heap2_)) \ - return false; \ - \ - for (size_t i = 0; i < PFX##_count(_heap1_); i++) \ - { \ - if (_heap1_->cmp(_heap1_->buffer[i], _heap2_->buffer[i]) != 0) \ - return false; \ - } \ - \ - return true; \ - } \ - \ - struct cmc_string PFX##_to_string(struct SNAME *_heap_) \ - { \ - struct cmc_string str; \ - struct SNAME *h_ = _heap_; \ - const char *t = h_->HO == 1 ? "MaxHeap" : "MinHeap"; \ - \ - int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_heap, \ - #SNAME, #V, h_, h_->buffer, h_->capacity, h_->count, \ - t, h_->cmp, h_->alloc, h_->callbacks); \ - \ - if (n < 0 || n == (int)cmc_string_len) \ - return (struct cmc_string){0}; \ - \ - str.s[n] = '\0'; \ - \ - return str; \ - } \ - \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ - { \ - struct SNAME##_iter *iter = target->alloc->malloc(sizeof(struct SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(struct SNAME##_iter *iter) \ - { \ - iter->target->alloc->free(iter); \ - } \ - \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ - { \ - iter->target = target; \ - iter->cursor = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - } \ - \ - bool PFX##_iter_start(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(struct SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - } \ - } \ - \ - void PFX##_iter_to_end(struct SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = PFX##_count(iter->target) - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - } \ - } \ - \ - bool PFX##_iter_next(struct SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->cursor + 1 == PFX##_count(iter->target)) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - iter->cursor++; \ - \ - return true; \ - } \ - \ - bool PFX##_iter_prev(struct SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->cursor == 0) \ - { \ - 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(struct SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->cursor + 1 == PFX##_count(iter->target)) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->cursor + steps >= PFX##_count(iter->target)) \ - return false; \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - if (iter->end) \ - return false; \ - \ - iter->cursor += steps; \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->cursor == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->cursor < steps) \ - 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(struct 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(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){0}; \ - \ - return iter->target->buffer[iter->cursor]; \ - } \ - \ - size_t PFX##_iter_index(struct SNAME##_iter *iter) \ - { \ - return iter->cursor; \ - } \ - \ - static bool PFX##_impl_float_up(struct SNAME *_heap_, size_t index) \ - { \ - /* Current index */ \ - size_t C = index; \ - V child = _heap_->buffer[C]; \ - V parent = _heap_->buffer[(index - 1) / 2]; \ - \ - int mod = _heap_->HO; \ - \ - while (C > 0 && _heap_->cmp(child, parent) * mod > 0) \ - { \ - /* Swap between C (current element) and its parent */ \ - V tmp = _heap_->buffer[C]; \ - _heap_->buffer[C] = _heap_->buffer[(C - 1) / 2]; \ - _heap_->buffer[(C - 1) / 2] = tmp; \ - \ - /* Go to parent */ \ - C = (C - 1) / 2; \ - \ - child = _heap_->buffer[C]; \ - parent = _heap_->buffer[(C - 1) / 2]; \ - } \ - \ - return true; \ - } \ - \ - static bool PFX##_impl_float_down(struct SNAME *_heap_, size_t index) \ - { \ - int mod = _heap_->HO; \ - \ - while (index < _heap_->count) \ - { \ - size_t L = 2 * index + 1; \ - size_t R = 2 * index + 2; \ - size_t C = index; \ - \ - /* Determine if we swap with the left or right element */ \ - if (L < _heap_->count && _heap_->cmp(_heap_->buffer[L], _heap_->buffer[C]) * mod > 0) \ - { \ - C = L; \ - } \ - \ - if (R < _heap_->count && _heap_->cmp(_heap_->buffer[R], _heap_->buffer[C]) * mod > 0) \ - { \ - C = R; \ - } \ - \ - /* Swap only if either left or right was picked, otherwise done */ \ - if (C != index) \ - { \ - V tmp = _heap_->buffer[index]; \ - _heap_->buffer[index] = _heap_->buffer[C]; \ - _heap_->buffer[C] = tmp; \ - \ - index = C; \ - } \ - else \ - break; \ - } \ - \ - return true; \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_heap_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _heap_); \ - PFX##_iter_to_start(&iter); \ - \ - return iter; \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_heap_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _heap_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ + * ------------------------------------------------------------------------- */ +#define CMC_GENERATE_HEAP_SOURCE(PFX, SNAME, V) \ + \ + /* Implementation Detail Functions */ \ + static bool PFX##_impl_float_up(struct SNAME *_heap_, size_t index); \ + static bool PFX##_impl_float_down(struct SNAME *_heap_, size_t index); \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_heap_); \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_heap_); \ + \ + struct SNAME *PFX##_new(size_t capacity, enum cmc_heap_order HO, \ + int (*compare)(V, V)) \ + { \ + struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ + \ + if (capacity < 1) \ + return NULL; \ + \ + if (HO != cmc_min_heap && HO != cmc_max_heap) \ + return NULL; \ + \ + struct SNAME *_heap_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_heap_) \ + return NULL; \ + \ + _heap_->buffer = alloc->calloc(capacity, sizeof(V)); \ + \ + if (!_heap_->buffer) \ + { \ + alloc->free(_heap_); \ + return NULL; \ + } \ + \ + _heap_->capacity = capacity; \ + _heap_->count = 0; \ + _heap_->HO = HO; \ + _heap_->cmp = compare; \ + \ + _heap_->it_start = PFX##_impl_it_start; \ + _heap_->it_end = PFX##_impl_it_end; \ + \ + _heap_->alloc = alloc; \ + _heap_->callbacks = NULL; \ + \ + return _heap_; \ + } \ + \ + struct SNAME *PFX##_new_custom( \ + size_t capacity, enum cmc_heap_order HO, int (*compare)(V, V), \ + struct cmc_alloc_node *alloc, struct cmc_callbacks_heap *callbacks) \ + { \ + if (capacity < 1) \ + return NULL; \ + \ + if (HO != cmc_min_heap && HO != cmc_max_heap) \ + return NULL; \ + \ + if (!alloc) \ + alloc = &cmc_alloc_node_default; \ + \ + struct SNAME *_heap_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_heap_) \ + return NULL; \ + \ + _heap_->buffer = alloc->calloc(capacity, sizeof(V)); \ + \ + if (!_heap_->buffer) \ + { \ + alloc->free(_heap_); \ + return NULL; \ + } \ + \ + _heap_->capacity = capacity; \ + _heap_->count = 0; \ + _heap_->HO = HO; \ + _heap_->cmp = compare; \ + \ + _heap_->it_start = PFX##_impl_it_start; \ + _heap_->it_end = PFX##_impl_it_end; \ + \ + _heap_->alloc = alloc; \ + _heap_->callbacks = callbacks; \ + \ + return _heap_; \ + } \ + \ + void PFX##_clear(struct SNAME *_heap_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _heap_->count; i++) \ + { \ + deallocator(_heap_->buffer[i]); \ + } \ + } \ + \ + memset(_heap_->buffer, 0, sizeof(V) * _heap_->capacity); \ + \ + _heap_->count = 0; \ + } \ + \ + void PFX##_free(struct SNAME *_heap_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _heap_->count; i++) \ + { \ + deallocator(_heap_->buffer[i]); \ + } \ + } \ + \ + _heap_->alloc->free(_heap_->buffer); \ + _heap_->alloc->free(_heap_); \ + } \ + \ + void PFX##_customize(struct SNAME *_heap_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_heap *callbacks) \ + { \ + if (alloc) \ + _heap_->alloc = alloc; \ + \ + if (callbacks) \ + _heap_->callbacks = callbacks; \ + } \ + \ + bool PFX##_insert(struct SNAME *_heap_, V element) \ + { \ + if (PFX##_full(_heap_)) \ + { \ + if (!PFX##_resize(_heap_, PFX##_count(_heap_) * 2)) \ + return false; \ + } \ + \ + if (PFX##_empty(_heap_)) \ + { \ + _heap_->buffer[_heap_->count++] = element; \ + return true; \ + } \ + \ + _heap_->buffer[_heap_->count++] = element; \ + \ + if (!PFX##_impl_float_up(_heap_, _heap_->count - 1)) \ + return false; \ + \ + return true; \ + } \ + \ + bool PFX##_remove(struct SNAME *_heap_, V *result) \ + { \ + if (PFX##_empty(_heap_)) \ + return false; \ + \ + *result = _heap_->buffer[0]; \ + _heap_->buffer[0] = _heap_->buffer[_heap_->count - 1]; \ + _heap_->buffer[_heap_->count - 1] = (V){ 0 }; \ + \ + _heap_->count--; \ + \ + if (!PFX##_impl_float_down(_heap_, 0)) \ + return false; \ + \ + return true; \ + } \ + \ + V PFX##_peek(struct SNAME *_heap_) \ + { \ + if (PFX##_empty(_heap_)) \ + return (V){ 0 }; \ + \ + return _heap_->buffer[0]; \ + } \ + \ + bool PFX##_contains(struct SNAME *_heap_, V element) \ + { \ + for (size_t i = 0; i < _heap_->count; i++) \ + { \ + if (_heap_->cmp(_heap_->buffer[i], element) == 0) \ + return true; \ + } \ + \ + return false; \ + } \ + \ + bool PFX##_empty(struct SNAME *_heap_) \ + { \ + return _heap_->count == 0; \ + } \ + \ + bool PFX##_full(struct SNAME *_heap_) \ + { \ + return _heap_->count >= _heap_->capacity; \ + } \ + \ + size_t PFX##_count(struct SNAME *_heap_) \ + { \ + return _heap_->count; \ + } \ + \ + size_t PFX##_capacity(struct SNAME *_heap_) \ + { \ + return _heap_->capacity; \ + } \ + \ + bool PFX##_resize(struct SNAME *_heap_, size_t capacity) \ + { \ + if (PFX##_capacity(_heap_) == capacity) \ + return true; \ + \ + if (capacity < PFX##_count(_heap_)) \ + return false; \ + \ + V *new_buffer = \ + _heap_->alloc->realloc(_heap_->buffer, sizeof(V) * capacity); \ + \ + if (!new_buffer) \ + return false; \ + \ + _heap_->buffer = new_buffer; \ + _heap_->capacity = capacity; \ + \ + return true; \ + } \ + \ + struct SNAME *PFX##_copy_of(struct SNAME *_heap_, V (*copy_func)(V)) \ + { \ + struct SNAME *result = \ + PFX##_new_custom(_heap_->capacity, _heap_->HO, _heap_->cmp, \ + _heap_->alloc, _heap_->callbacks); \ + \ + if (!result) \ + return NULL; \ + \ + if (copy_func) \ + { \ + for (size_t i = 0; i < _heap_->count; i++) \ + result->buffer[i] = copy_func(_heap_->buffer[i]); \ + } \ + else \ + memcpy(result->buffer, _heap_->buffer, sizeof(V) * _heap_->count); \ + \ + result->count = _heap_->count; \ + \ + return result; \ + } \ + \ + bool PFX##_equals(struct SNAME *_heap1_, struct SNAME *_heap2_) \ + { \ + if (PFX##_count(_heap1_) != PFX##_count(_heap2_)) \ + return false; \ + \ + for (size_t i = 0; i < PFX##_count(_heap1_); i++) \ + { \ + if (_heap1_->cmp(_heap1_->buffer[i], _heap2_->buffer[i]) != 0) \ + return false; \ + } \ + \ + return true; \ + } \ + \ + struct cmc_string PFX##_to_string(struct SNAME *_heap_) \ + { \ + struct cmc_string str; \ + struct SNAME *h_ = _heap_; \ + const char *t = h_->HO == 1 ? "MaxHeap" : "MinHeap"; \ + \ + int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_heap, #SNAME, \ + #V, h_, h_->buffer, h_->capacity, h_->count, t, \ + h_->cmp, h_->alloc, h_->callbacks); \ + \ + if (n < 0 || n == (int)cmc_string_len) \ + return (struct cmc_string){ 0 }; \ + \ + str.s[n] = '\0'; \ + \ + return str; \ + } \ + \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ + { \ + struct SNAME##_iter *iter = \ + target->alloc->malloc(sizeof(struct SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + void PFX##_iter_free(struct SNAME##_iter *iter) \ + { \ + iter->target->alloc->free(iter); \ + } \ + \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ + { \ + iter->target = target; \ + iter->cursor = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + } \ + \ + bool PFX##_iter_start(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + bool PFX##_iter_end(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + void PFX##_iter_to_start(struct SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ + } \ + \ + void PFX##_iter_to_end(struct SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = PFX##_count(iter->target) - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + } \ + } \ + \ + bool PFX##_iter_next(struct SNAME##_iter *iter) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->cursor + 1 == PFX##_count(iter->target)) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + iter->cursor++; \ + \ + return true; \ + } \ + \ + bool PFX##_iter_prev(struct SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor == 0) \ + { \ + 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(struct SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor + 1 == PFX##_count(iter->target)) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->cursor + steps >= PFX##_count(iter->target)) \ + return false; \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + if (iter->end) \ + return false; \ + \ + iter->cursor += steps; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->cursor < steps) \ + 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(struct 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(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return (V){ 0 }; \ + \ + return iter->target->buffer[iter->cursor]; \ + } \ + \ + size_t PFX##_iter_index(struct SNAME##_iter *iter) \ + { \ + return iter->cursor; \ + } \ + \ + static bool PFX##_impl_float_up(struct SNAME *_heap_, size_t index) \ + { \ + /* Current index */ \ + size_t C = index; \ + V child = _heap_->buffer[C]; \ + V parent = _heap_->buffer[(index - 1) / 2]; \ + \ + int mod = _heap_->HO; \ + \ + while (C > 0 && _heap_->cmp(child, parent) * mod > 0) \ + { \ + /* Swap between C (current element) and its parent */ \ + V tmp = _heap_->buffer[C]; \ + _heap_->buffer[C] = _heap_->buffer[(C - 1) / 2]; \ + _heap_->buffer[(C - 1) / 2] = tmp; \ + \ + /* Go to parent */ \ + C = (C - 1) / 2; \ + \ + child = _heap_->buffer[C]; \ + parent = _heap_->buffer[(C - 1) / 2]; \ + } \ + \ + return true; \ + } \ + \ + static bool PFX##_impl_float_down(struct SNAME *_heap_, size_t index) \ + { \ + int mod = _heap_->HO; \ + \ + while (index < _heap_->count) \ + { \ + size_t L = 2 * index + 1; \ + size_t R = 2 * index + 2; \ + size_t C = index; \ + \ + /* Determine if we swap with the left or right element */ \ + if (L < _heap_->count && \ + _heap_->cmp(_heap_->buffer[L], _heap_->buffer[C]) * mod > 0) \ + { \ + C = L; \ + } \ + \ + if (R < _heap_->count && \ + _heap_->cmp(_heap_->buffer[R], _heap_->buffer[C]) * mod > 0) \ + { \ + C = R; \ + } \ + \ + /* Swap only if either left or right was picked, otherwise done */ \ + if (C != index) \ + { \ + V tmp = _heap_->buffer[index]; \ + _heap_->buffer[index] = _heap_->buffer[C]; \ + _heap_->buffer[C] = tmp; \ + \ + index = C; \ + } \ + else \ + break; \ + } \ + \ + return true; \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_heap_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _heap_); \ + PFX##_iter_to_start(&iter); \ + \ + return iter; \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_heap_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _heap_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_HEAP_H */ diff --git a/src/cmc/intervalheap.h b/src/cmc/intervalheap.h index 2e8dc4d..4377696 100644 --- a/src/cmc/intervalheap.h +++ b/src/cmc/intervalheap.h @@ -23,13 +23,13 @@ #include #include -#include #include +#include #include -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Core functionalities of the C Macro Collections Library - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ #ifndef CMC_CORE_H #define CMC_CORE_H @@ -48,7 +48,8 @@ static const size_t cmc_string_len = 400; /** * struct cmc_alloc_node * - * Custom allocation node. Allows collections to use custom allocation functions. + * Custom allocation node. Allows collections to use custom allocation + * functions. */ struct cmc_alloc_node { @@ -58,13 +59,14 @@ struct cmc_alloc_node void (*free)(void *); }; -static struct cmc_alloc_node cmc_alloc_node_default = {malloc, calloc, realloc, free}; +static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, + free }; #endif /* CMC_CORE_H */ -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * IntervalHeap specific - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ /* to_string format */ static const char *cmc_string_fmt_intervalheap = "struct %s<%s> " "at %p { " @@ -101,989 +103,1012 @@ struct cmc_callbacks_intervalheap #define CMC_WRAPGEN_INTERVALHEAP_SOURCE(PFX, SNAME, K, V) \ CMC_GENERATE_INTERVALHEAP_SOURCE(PFX, SNAME, V) -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Header - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_INTERVALHEAP_HEADER(PFX, SNAME, V) \ - \ - /* Heap Structure */ \ - struct SNAME \ - { \ - /* Dynamic array of nodes */ \ - struct SNAME##_node *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 (*it_start)(struct SNAME *); \ - \ - /* Function that returns an iterator to the end of the heap */ \ - struct SNAME##_iter (*it_end)(struct SNAME *); \ - \ - /* Custom allocation functions */ \ - struct cmc_alloc_node *alloc; \ - \ - /* Custom callback functions */ \ - struct cmc_callbacks_intervalheap *callbacks; \ - }; \ - \ - /* Heap Node */ \ - struct SNAME##_node \ - { \ - /* 0 - Value belonging to the MinHeap */ \ - /* 1 - Value belonging to the MaxHeap */ \ - V data[2]; \ - }; \ - \ - /* Heap Iterator */ \ - struct SNAME##_iter \ - { \ - /* Target heap */ \ - struct SNAME *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; \ - }; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - struct SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)); \ - struct SNAME *PFX##_new_custom(size_t capacity, int (*compare)(V, V), \ - struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_intervalheap *callbacks); \ - void PFX##_clear(struct SNAME *_heap_, void (*deallocator)(V)); \ - void PFX##_free(struct SNAME *_heap_, void (*deallocator)(V)); \ - /* Customization of Allocation and Callbacks */ \ - void PFX##_customize(struct SNAME *_heap_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_intervalheap *callbacks); \ - /* Collection Input and Output */ \ - bool PFX##_insert(struct SNAME *_heap_, V element); \ - bool PFX##_remove_max(struct SNAME *_heap_, V *result); \ - bool PFX##_remove_min(struct SNAME *_heap_, V *result); \ - /* Collection Update */ \ - bool PFX##_update_max(struct SNAME *_heap_, V element); \ - bool PFX##_update_min(struct SNAME *_heap_, V element); \ - /* Element Access */ \ - bool PFX##_max(struct SNAME *_heap_, V *value); \ - bool PFX##_min(struct SNAME *_heap_, V *value); \ - /* Collection State */ \ - bool PFX##_contains(struct SNAME *_heap_, V element); \ - bool PFX##_empty(struct SNAME *_heap_); \ - bool PFX##_full(struct SNAME *_heap_); \ - size_t PFX##_count(struct SNAME *_heap_); \ - size_t PFX##_capacity(struct SNAME *_heap_); \ - /* Collection Utility */ \ - bool PFX##_resize(struct SNAME *_heap_, size_t capacity); \ - struct SNAME *PFX##_copy_of(struct SNAME *_set_, V (*copy_func)(V)); \ - bool PFX##_equals(struct SNAME *_heap1_, struct SNAME *_heap2_); \ - struct cmc_string PFX##_to_string(struct SNAME *_heap_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ - void PFX##_iter_free(struct SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(struct SNAME##_iter *iter); \ - bool PFX##_iter_end(struct SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(struct SNAME##_iter *iter); \ - void PFX##_iter_to_end(struct SNAME##_iter *iter); \ - bool PFX##_iter_next(struct SNAME##_iter *iter); \ - bool PFX##_iter_prev(struct SNAME##_iter *iter); \ - bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - V PFX##_iter_value(struct SNAME##_iter *iter); \ + * ------------------------------------------------------------------------- */ +#define CMC_GENERATE_INTERVALHEAP_HEADER(PFX, SNAME, V) \ + \ + /* Heap Structure */ \ + struct SNAME \ + { \ + /* Dynamic array of nodes */ \ + struct SNAME##_node *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 (*it_start)(struct SNAME *); \ + \ + /* Function that returns an iterator to the end of the heap */ \ + struct SNAME##_iter (*it_end)(struct SNAME *); \ + \ + /* Custom allocation functions */ \ + struct cmc_alloc_node *alloc; \ + \ + /* Custom callback functions */ \ + struct cmc_callbacks_intervalheap *callbacks; \ + }; \ + \ + /* Heap Node */ \ + struct SNAME##_node \ + { \ + /* 0 - Value belonging to the MinHeap */ \ + /* 1 - Value belonging to the MaxHeap */ \ + V data[2]; \ + }; \ + \ + /* Heap Iterator */ \ + struct SNAME##_iter \ + { \ + /* Target heap */ \ + struct SNAME *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; \ + }; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + struct SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)); \ + struct SNAME *PFX##_new_custom( \ + size_t capacity, int (*compare)(V, V), struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_intervalheap *callbacks); \ + void PFX##_clear(struct SNAME *_heap_, void (*deallocator)(V)); \ + void PFX##_free(struct SNAME *_heap_, void (*deallocator)(V)); \ + /* Customization of Allocation and Callbacks */ \ + void PFX##_customize(struct SNAME *_heap_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_intervalheap *callbacks); \ + /* Collection Input and Output */ \ + bool PFX##_insert(struct SNAME *_heap_, V element); \ + bool PFX##_remove_max(struct SNAME *_heap_, V *result); \ + bool PFX##_remove_min(struct SNAME *_heap_, V *result); \ + /* Collection Update */ \ + bool PFX##_update_max(struct SNAME *_heap_, V element); \ + bool PFX##_update_min(struct SNAME *_heap_, V element); \ + /* Element Access */ \ + bool PFX##_max(struct SNAME *_heap_, V *value); \ + bool PFX##_min(struct SNAME *_heap_, V *value); \ + /* Collection State */ \ + bool PFX##_contains(struct SNAME *_heap_, V element); \ + bool PFX##_empty(struct SNAME *_heap_); \ + bool PFX##_full(struct SNAME *_heap_); \ + size_t PFX##_count(struct SNAME *_heap_); \ + size_t PFX##_capacity(struct SNAME *_heap_); \ + /* Collection Utility */ \ + bool PFX##_resize(struct SNAME *_heap_, size_t capacity); \ + struct SNAME *PFX##_copy_of(struct SNAME *_set_, V (*copy_func)(V)); \ + bool PFX##_equals(struct SNAME *_heap1_, struct SNAME *_heap2_); \ + struct cmc_string PFX##_to_string(struct SNAME *_heap_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ + void PFX##_iter_free(struct SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(struct SNAME##_iter *iter); \ + bool PFX##_iter_end(struct SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(struct SNAME##_iter *iter); \ + void PFX##_iter_to_end(struct SNAME##_iter *iter); \ + bool PFX##_iter_next(struct SNAME##_iter *iter); \ + bool PFX##_iter_prev(struct SNAME##_iter *iter); \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + V PFX##_iter_value(struct SNAME##_iter *iter); \ size_t PFX##_iter_index(struct SNAME##_iter *iter); -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Source - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_INTERVALHEAP_SOURCE(PFX, SNAME, V) \ - \ - /* Implementation Detail Functions */ \ - static void PFX##_impl_float_up_max(struct SNAME *_heap_); \ - static void PFX##_impl_float_up_min(struct SNAME *_heap_); \ - static void PFX##_impl_float_down_max(struct SNAME *_heap_); \ - static void PFX##_impl_float_down_min(struct SNAME *_heap_); \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_heap_); \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_heap_); \ - \ - struct SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)) \ - { \ - struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ - \ - if (capacity == 0 || capacity == UINT64_MAX) \ - return NULL; \ - \ - struct SNAME *_heap_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_heap_) \ - return NULL; \ - \ - /* Since each node can store two elements, divide the actual capacity by 2 */ \ - /* Round the capacity of nodes up */ \ - capacity = capacity % 2 == 0 ? capacity / 2 : (capacity + 1) / 2; \ - \ - _heap_->buffer = alloc->calloc(capacity, sizeof(struct SNAME##_node)); \ - \ - if (!_heap_->buffer) \ - { \ - alloc->free(_heap_); \ - return NULL; \ - } \ - \ - _heap_->capacity = capacity; \ - _heap_->size = 0; \ - _heap_->count = 0; \ - _heap_->cmp = compare; \ - \ - _heap_->it_start = PFX##_impl_it_start; \ - _heap_->it_end = PFX##_impl_it_end; \ - \ - _heap_->alloc = alloc; \ - _heap_->callbacks = NULL; \ - \ - return _heap_; \ - } \ - \ - struct SNAME *PFX##_new_custom(size_t capacity, int (*compare)(V, V), \ - struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_intervalheap *callbacks) \ - { \ - if (capacity == 0 || capacity == UINT64_MAX) \ - return NULL; \ - \ - if (!alloc) \ - alloc = &cmc_alloc_node_default; \ - \ - struct SNAME *_heap_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_heap_) \ - return NULL; \ - \ - /* Since each node can store two elements, divide the actual capacity by 2 */ \ - /* Round the capacity of nodes up */ \ - capacity = capacity % 2 == 0 ? capacity / 2 : (capacity + 1) / 2; \ - \ - _heap_->buffer = alloc->calloc(capacity, sizeof(struct SNAME##_node)); \ - \ - if (!_heap_->buffer) \ - { \ - alloc->free(_heap_); \ - return NULL; \ - } \ - \ - _heap_->capacity = capacity; \ - _heap_->size = 0; \ - _heap_->count = 0; \ - _heap_->cmp = compare; \ - \ - _heap_->it_start = PFX##_impl_it_start; \ - _heap_->it_end = PFX##_impl_it_end; \ - \ - _heap_->alloc = alloc; \ - _heap_->callbacks = callbacks; \ - \ - return _heap_; \ - } \ - \ - void PFX##_clear(struct SNAME *_heap_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _heap_->count; i++) \ - { \ - deallocator(_heap_->buffer[i / 2].data[i % 2]); \ - } \ - } \ - \ - memset(_heap_->buffer, 0, sizeof(V) * _heap_->capacity); \ - \ - _heap_->size = 0; \ - _heap_->count = 0; \ - } \ - \ - void PFX##_free(struct SNAME *_heap_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _heap_->count; i++) \ - { \ - deallocator(_heap_->buffer[i / 2].data[i % 2]); \ - } \ - } \ - \ - _heap_->alloc->free(_heap_->buffer); \ - \ - _heap_->alloc->free(_heap_); \ - } \ - \ - void PFX##_customize(struct SNAME *_heap_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_intervalheap *callbacks) \ - { \ - if (alloc) \ - _heap_->alloc = alloc; \ - \ - if (callbacks) \ - _heap_->callbacks = callbacks; \ - } \ - \ - bool PFX##_insert(struct SNAME *_heap_, V element) \ - { \ - if (PFX##_full(_heap_)) \ - { \ - if (!PFX##_resize(_heap_, PFX##_capacity(_heap_) * 4)) \ - return false; \ - } \ - \ - if (PFX##_count(_heap_) % 2 == 0) \ - { \ - /* Occupying a new node */ \ - _heap_->buffer[_heap_->size].data[0] = element; \ - _heap_->buffer[_heap_->size].data[1] = (V){0}; \ - \ - _heap_->size++; \ - } \ - else \ - { \ - struct SNAME##_node *curr_node = &(_heap_->buffer[_heap_->size - 1]); \ - \ - /* Decide if the new element goes into the MinHeap or MaxHeap */ \ - if (_heap_->cmp(curr_node->data[0], element) > 0) \ - { \ - /* Swap current value and add new element to the MinHeap */ \ - curr_node->data[1] = curr_node->data[0]; \ - curr_node->data[0] = element; \ - } \ - else \ - { \ - /* No need to swap and add the new element to the MaxHeap */ \ - curr_node->data[1] = element; \ - } \ - } \ - \ - _heap_->count++; \ - \ - if (PFX##_count(_heap_) <= 2) \ - return true; \ - \ - /* Determine wheather to do a MaxHeap insert or a MinHeap insert */ \ - struct SNAME##_node *parent = &(_heap_->buffer[(_heap_->size - 1) / 2]); \ - \ - if (_heap_->cmp(parent->data[0], element) > 0) \ - PFX##_impl_float_up_min(_heap_); \ - else if (_heap_->cmp(parent->data[1], element) < 0) \ - PFX##_impl_float_up_max(_heap_); \ - /* else no float up required */ \ - \ - return true; \ - } \ - \ - bool PFX##_remove_max(struct SNAME *_heap_, V *result) \ - { \ - if (PFX##_empty(_heap_)) \ - return false; \ - \ - if (PFX##_count(_heap_) == 1) \ - { \ - *result = _heap_->buffer[0].data[0]; \ - \ - _heap_->buffer[0].data[0] = (V){0}; \ - \ - _heap_->count--; \ - \ - return true; \ - } \ - else \ - *result = _heap_->buffer[0].data[1]; \ - \ - /* Swap the result with the last element in the MaxHeap and float it down */ \ - struct SNAME##_node *last_node = &(_heap_->buffer[_heap_->size - 1]); \ - \ - if (PFX##_count(_heap_) % 2 == 1) \ - { \ - /* Grab from MinHeap and discard last node */ \ - _heap_->buffer[0].data[1] = last_node->data[0]; \ - \ - last_node->data[0] = (V){0}; \ - \ - _heap_->size--; \ - } \ - else \ - { \ - _heap_->buffer[0].data[1] = last_node->data[1]; \ - \ - last_node->data[1] = (V){0}; \ - } \ - \ - _heap_->count--; \ - \ - /* FLoat Down on the MaxHeap */ \ - PFX##_impl_float_down_max(_heap_); \ - \ - return true; \ - } \ - \ - bool PFX##_remove_min(struct SNAME *_heap_, V *result) \ - { \ - if (PFX##_empty(_heap_)) \ - return false; \ - \ - *result = _heap_->buffer[0].data[0]; \ - \ - if (PFX##_count(_heap_) == 1) \ - { \ - _heap_->buffer[0].data[0] = (V){0}; \ - \ - _heap_->count--; \ - \ - return true; \ - } \ - \ - /* Swap the result with the last element in the MinHeap and float it down */ \ - struct SNAME##_node *last_node = &(_heap_->buffer[_heap_->size - 1]); \ - \ - _heap_->buffer[0].data[0] = last_node->data[0]; \ - \ - if (PFX##_count(_heap_) % 2 == 1) \ - { \ - /* Discard last node */ \ - last_node->data[0] = (V){0}; \ - \ - _heap_->size--; \ - } \ - else \ - { \ - /* Place the MaxHeap value in the MinHeap value spot */ \ - last_node->data[0] = last_node->data[1]; \ - last_node->data[1] = (V){0}; \ - } \ - \ - _heap_->count--; \ - \ - /* FLoat Down on the MinHeap */ \ - PFX##_impl_float_down_min(_heap_); \ - \ - return true; \ - } \ - \ - bool PFX##_update_max(struct SNAME *_heap_, V element) \ - { \ - if (PFX##_empty(_heap_)) \ - return false; \ - \ - if (PFX##_count(_heap_) == 1) \ - { \ - _heap_->buffer[0].data[0] = element; \ - } \ - else if (_heap_->cmp(element, _heap_->buffer[0].data[0]) < 0) \ - { \ - /* Corner case: we are updating the Max value but it is less than */ \ - /* the Min value */ \ - _heap_->buffer[0].data[1] = _heap_->buffer[0].data[0]; \ - _heap_->buffer[0].data[0] = element; \ - \ - PFX##_impl_float_down_max(_heap_); \ - } \ - else \ - { \ - /* Update Max element and float it down */ \ - _heap_->buffer[0].data[1] = element; \ - \ - PFX##_impl_float_down_max(_heap_); \ - } \ - \ - return true; \ - } \ - \ - bool PFX##_update_min(struct SNAME *_heap_, V element) \ - { \ - if (PFX##_empty(_heap_)) \ - return false; \ - \ - if (PFX##_count(_heap_) == 1) \ - { \ - _heap_->buffer[0].data[0] = element; \ - } \ - else if (_heap_->cmp(element, _heap_->buffer[0].data[1]) > 0) \ - { \ - /* Corner case: we are updating the Min value but it is greater */ \ - /* than the Max value. */ \ - _heap_->buffer[0].data[0] = _heap_->buffer[0].data[1]; \ - _heap_->buffer[0].data[1] = element; \ - \ - PFX##_impl_float_down_min(_heap_); \ - } \ - else \ - { \ - /* Update Min element and float it down */ \ - _heap_->buffer[0].data[0] = element; \ - \ - PFX##_impl_float_down_min(_heap_); \ - } \ - \ - return true; \ - } \ - \ - bool PFX##_max(struct SNAME *_heap_, V *value) \ - { \ - if (PFX##_empty(_heap_)) \ - return false; \ - \ - /* If there is only one element, then the maximum element is the same */ \ - /* as the one in the MinHeap */ \ - if (PFX##_count(_heap_) == 1) \ - *value = _heap_->buffer[0].data[0]; \ - else \ - *value = _heap_->buffer[0].data[1]; \ - \ - return true; \ - } \ - \ - bool PFX##_min(struct SNAME *_heap_, V *value) \ - { \ - if (PFX##_empty(_heap_)) \ - return false; \ - \ - *value = _heap_->buffer[0].data[0]; \ - \ - return true; \ - } \ - \ - bool PFX##_contains(struct SNAME *_heap_, V element) \ - { \ - for (size_t i = 0; i < _heap_->count; i++) \ - { \ - if (_heap_->cmp(_heap_->buffer[i / 2].data[i % 2], element) == 0) \ - return true; \ - } \ - \ - return false; \ - } \ - \ - bool PFX##_empty(struct SNAME *_heap_) \ - { \ - return _heap_->count == 0; \ - } \ - \ - bool PFX##_full(struct SNAME *_heap_) \ - { \ - /* The heap is full if all nodes are completely filled */ \ - return _heap_->size >= _heap_->capacity && _heap_->count % 2 == 0; \ - } \ - \ - size_t PFX##_count(struct SNAME *_heap_) \ - { \ - return _heap_->count; \ - } \ - \ - size_t PFX##_capacity(struct SNAME *_heap_) \ - { \ - return _heap_->capacity; \ - } \ - \ - bool PFX##_resize(struct SNAME *_heap_, size_t capacity) \ - { \ - if (PFX##_capacity(_heap_) == capacity) \ - return true; \ - \ - if (capacity < PFX##_count(_heap_)) \ - return false; \ - \ - capacity = capacity % 2 == 0 ? capacity / 2 : (capacity + 1) / 2; \ - \ - struct SNAME##_node *new_buffer = _heap_->alloc->realloc( \ - _heap_->buffer, sizeof(struct SNAME##_node) * capacity); \ - \ - if (!new_buffer) \ - return false; \ - \ - memset(new_buffer + _heap_->capacity, 0, sizeof(struct SNAME##_node) * _heap_->capacity); \ - \ - _heap_->buffer = new_buffer; \ - _heap_->capacity = capacity; \ - \ - return true; \ - } \ - \ - struct SNAME *PFX##_copy_of(struct SNAME *_heap_, V (*copy_func)(V)) \ - { \ - struct SNAME *result = _heap_->alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!result) \ - return NULL; \ - \ - memcpy(result, _heap_, sizeof(struct SNAME)); \ - \ - result->buffer = _heap_->alloc->malloc(sizeof(struct SNAME##_node) * _heap_->capacity); \ - \ - if (!result->buffer) \ - { \ - _heap_->alloc->free(result); \ - return NULL; \ - } \ - \ - if (copy_func) \ - { \ - for (size_t i = 0; i < _heap_->count; i++) \ - result->buffer[i / 2].data[i % 2] = copy_func(_heap_->buffer[i / 2].data[i % 2]); \ - } \ - else \ - memcpy(result->buffer, _heap_->buffer, \ - sizeof(struct SNAME##_node) * _heap_->capacity); \ - \ - result->alloc = _heap_->alloc; \ - result->callbacks = _heap_->callbacks; \ - \ - return result; \ - } \ - \ - bool PFX##_equals(struct SNAME *_heap1_, struct SNAME *_heap2_) \ - { \ - if (PFX##_count(_heap1_) != PFX##_count(_heap2_)) \ - return false; \ - \ - for (size_t i = 0; i < _heap1_->count; i++) \ - { \ - V element1 = _heap1_->buffer[i / 2].data[i % 2]; \ - V element2 = _heap2_->buffer[i / 2].data[i % 2]; \ - \ - if (_heap1_->cmp(element1, element2) == 0) \ - return true; \ - } \ - \ - return false; \ - } \ - \ - struct cmc_string PFX##_to_string(struct SNAME *_heap_) \ - { \ - struct cmc_string str; \ - struct SNAME *h_ = _heap_; \ - \ - int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_intervalheap, \ - #SNAME, #V, h_, h_->buffer, h_->capacity, h_->size, \ - h_->count, h_->cmp, h_->alloc, h_->callbacks); \ - \ - if (n < 0 || n == (int)cmc_string_len) \ - return (struct cmc_string){0}; \ - \ - str.s[n] = '\0'; \ - \ - return str; \ - } \ - \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ - { \ - struct SNAME##_iter *iter = target->alloc->malloc(sizeof(struct SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(struct SNAME##_iter *iter) \ - { \ - iter->target->alloc->free(iter); \ - } \ - \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ - { \ - iter->target = target; \ - iter->cursor = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - } \ - \ - bool PFX##_iter_start(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(struct SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - } \ - } \ - \ - void PFX##_iter_to_end(struct SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - } \ - } \ - \ - bool PFX##_iter_next(struct SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->cursor + 1 == PFX##_count(iter->target)) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - iter->cursor++; \ - \ - return true; \ - } \ - \ - bool PFX##_iter_prev(struct SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->cursor == 0) \ - { \ - 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(struct SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->cursor == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->cursor + steps >= PFX##_count(iter->target)) \ - return false; \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - iter->cursor += steps; \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->cursor == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->cursor < steps) \ - 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(struct 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(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){0}; \ - \ - return iter->target->buffer[iter->cursor / 2].data[iter->cursor % 2]; \ - } \ - \ - size_t PFX##_iter_index(struct SNAME##_iter *iter) \ - { \ - return iter->cursor; \ - } \ - \ - static void PFX##_impl_float_up_max(struct SNAME *_heap_) \ - { \ - size_t index = _heap_->size - 1; \ - \ - struct SNAME##_node *curr_node = &(_heap_->buffer[index]); \ - \ - /* FLoat Up on the MaxHeap */ \ - while (index > 0) \ - { \ - /* Parent index */ \ - size_t P_index = (index - 1) / 2; \ - \ - struct SNAME##_node *parent = &(_heap_->buffer[P_index]); \ - \ - if (index == _heap_->size - 1 && PFX##_count(_heap_) % 2 != 0) \ - { \ - /* In this case, the current node has no MaxHeap value so we */ \ - /* instead compare with the MinHeap value */ \ - if (_heap_->cmp(curr_node->data[0], parent->data[1]) < 0) \ - break; \ - \ - /* Since the comparison above passed now we need to swap the */ \ - /* current node with the parent but it will have to be done */ \ - /* with the node's MinHeap value since the MaxHeap value */ \ - /* doesn't exist */ \ - V tmp = curr_node->data[0]; \ - curr_node->data[0] = parent->data[1]; \ - parent->data[1] = tmp; \ - } \ - else \ - { \ - /* Usual case, just compare both MaxHeap values */ \ - if (_heap_->cmp(curr_node->data[1], parent->data[1]) < 0) \ - break; \ - \ - /* Swap with parent and repeat */ \ - V tmp = curr_node->data[1]; \ - curr_node->data[1] = parent->data[1]; \ - parent->data[1] = tmp; \ - } \ - \ - /* Update indexe and node */ \ - index = P_index; \ - curr_node = parent; \ - } \ - } \ - \ - static void PFX##_impl_float_up_min(struct SNAME *_heap_) \ - { \ - size_t index = _heap_->size - 1; \ - \ - struct SNAME##_node *curr_node = &(_heap_->buffer[index]); \ - \ - /* FLoat Up on the MinHeap */ \ - while (index > 0) \ - { \ - /* Parent index */ \ - size_t P_index = (index - 1) / 2; \ - \ - struct SNAME##_node *parent = &(_heap_->buffer[P_index]); \ - \ - if (_heap_->cmp(curr_node->data[0], parent->data[0]) >= 0) \ - break; \ - \ - /* Swap with parent and repeat */ \ - V tmp = curr_node->data[0]; \ - curr_node->data[0] = parent->data[0]; \ - parent->data[0] = tmp; \ - \ - /* Update indexe and node */ \ - index = P_index; \ - curr_node = parent; \ - } \ - } \ - \ - static void PFX##_impl_float_down_max(struct SNAME *_heap_) \ - { \ - /* Floats Down from the MinHeap */ \ - size_t index = 0; \ - \ - struct SNAME##_node *curr_node = &(_heap_->buffer[index]); \ - \ - while (true) \ - { \ - /* If there are no children it is done */ \ - if (2 * index + 1 >= _heap_->size) \ - break; \ - \ - /* Child index to be compared with current value */ \ - size_t child; \ - size_t L_index = index * 2 + 1; \ - size_t R_index = index * 2 + 2; \ - \ - /* If there are two children, pick the smallest one */ \ - if (R_index < _heap_->size) \ - { \ - struct SNAME##_node *L = &(_heap_->buffer[L_index]); \ - struct SNAME##_node *R = &(_heap_->buffer[R_index]); \ - \ - /* If the right child is the last node and there is no MaxHeap value */ \ - /* then do the comparison with the MinHeap value */ \ - if (R_index == _heap_->size - 1 && PFX##_count(_heap_) % 2 != 0) \ - child = _heap_->cmp(L->data[1], R->data[0]) > 0 ? L_index : R_index; \ - else \ - child = _heap_->cmp(L->data[1], R->data[1]) > 0 ? L_index : R_index; \ - } \ - /* Pick the only one available */ \ - else \ - child = L_index; \ - \ - struct SNAME##_node *child_node = &(_heap_->buffer[child]); \ - \ - /* Again, check if the child node is the last one and has no MaxHeap value */ \ - if (child == _heap_->size - 1 && PFX##_count(_heap_) % 2 != 0) \ - { \ - /* Odd case, compare with MinHeap value */ \ - /* If current value is not less than the child node's value, it is done */ \ - if (_heap_->cmp(curr_node->data[1], child_node->data[0]) >= 0) \ - break; \ - \ - /* Otherwise swap and continue */ \ - V tmp = child_node->data[0]; \ - child_node->data[0] = curr_node->data[1]; \ - curr_node->data[1] = tmp; \ - } \ - else \ - { \ - /* If current value is not less than the child node's value, it is done */ \ - if (_heap_->cmp(curr_node->data[1], child_node->data[1]) >= 0) \ - break; \ - \ - /* Otherwise swap and continue */ \ - V tmp = child_node->data[1]; \ - child_node->data[1] = curr_node->data[1]; \ - curr_node->data[1] = tmp; \ - \ - /* Check if the MinHeap and MaxHeap values need to be swapped */ \ - if (_heap_->cmp(child_node->data[0], child_node->data[1]) > 0) \ - { \ - /* Swap because the MinHeap value is greater than the MaxHeap value */ \ - tmp = child_node->data[0]; \ - child_node->data[0] = child_node->data[1]; \ - child_node->data[1] = tmp; \ - } \ - } \ - \ - /* Update index and node */ \ - index = child; \ - curr_node = child_node; \ - } \ - } \ - \ - static void PFX##_impl_float_down_min(struct SNAME *_heap_) \ - { \ - /* Floats Down from the MinHeap */ \ - size_t index = 0; \ - \ - struct SNAME##_node *curr_node = &(_heap_->buffer[index]); \ - \ - while (true) \ - { \ - /* If there are no children it is done */ \ - if (2 * index + 1 >= _heap_->size) \ - break; \ - \ - /* Child index to be compared with current value */ \ - size_t child; \ - size_t L_index = index * 2 + 1; \ - size_t R_index = index * 2 + 2; \ - \ - /* If there are two children, pick the smallest one */ \ - if (R_index < _heap_->size) \ - { \ - struct SNAME##_node *L = &(_heap_->buffer[L_index]); \ - struct SNAME##_node *R = &(_heap_->buffer[R_index]); \ - \ - child = _heap_->cmp(L->data[0], R->data[0]) < 0 ? L_index : R_index; \ - } \ - /* Pick the only one available */ \ - else \ - child = L_index; \ - \ - struct SNAME##_node *child_node = &(_heap_->buffer[child]); \ - \ - /* If current value is smaller than the child node's value, it is done */ \ - if (_heap_->cmp(curr_node->data[0], child_node->data[0]) < 0) \ - break; \ - \ - /* Otherwise swap and continue */ \ - V tmp = child_node->data[0]; \ - child_node->data[0] = curr_node->data[0]; \ - curr_node->data[0] = tmp; \ - \ - /* If the child node is the last node check if the MinHeap and */ \ - /* MaxHeap values need to be swapped */ \ - if (child != _heap_->size - 1 || PFX##_count(_heap_) % 2 == 0) \ - { \ - if (_heap_->cmp(child_node->data[0], child_node->data[1]) > 0) \ - { \ - /* Swap because the MinHeap value is greater than the MaxHeap value */ \ - tmp = child_node->data[0]; \ - child_node->data[0] = child_node->data[1]; \ - child_node->data[1] = tmp; \ - } \ - } \ - \ - /* Update index and node */ \ - index = child; \ - curr_node = child_node; \ - } \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_heap_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _heap_); \ - PFX##_iter_to_start(&iter); \ - \ - return iter; \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_heap_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _heap_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ + * ------------------------------------------------------------------------- */ +#define CMC_GENERATE_INTERVALHEAP_SOURCE(PFX, SNAME, V) \ + \ + /* Implementation Detail Functions */ \ + static void PFX##_impl_float_up_max(struct SNAME *_heap_); \ + static void PFX##_impl_float_up_min(struct SNAME *_heap_); \ + static void PFX##_impl_float_down_max(struct SNAME *_heap_); \ + static void PFX##_impl_float_down_min(struct SNAME *_heap_); \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_heap_); \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_heap_); \ + \ + struct SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)) \ + { \ + struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ + \ + if (capacity == 0 || capacity == UINT64_MAX) \ + return NULL; \ + \ + struct SNAME *_heap_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_heap_) \ + return NULL; \ + \ + /* Since each node can store two elements, divide the actual */ \ + /* capacity by 2 */ \ + /* Round the capacity of nodes up */ \ + capacity = capacity % 2 == 0 ? capacity / 2 : (capacity + 1) / 2; \ + \ + _heap_->buffer = alloc->calloc(capacity, sizeof(struct SNAME##_node)); \ + \ + if (!_heap_->buffer) \ + { \ + alloc->free(_heap_); \ + return NULL; \ + } \ + \ + _heap_->capacity = capacity; \ + _heap_->size = 0; \ + _heap_->count = 0; \ + _heap_->cmp = compare; \ + \ + _heap_->it_start = PFX##_impl_it_start; \ + _heap_->it_end = PFX##_impl_it_end; \ + \ + _heap_->alloc = alloc; \ + _heap_->callbacks = NULL; \ + \ + return _heap_; \ + } \ + \ + struct SNAME *PFX##_new_custom( \ + size_t capacity, int (*compare)(V, V), struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_intervalheap *callbacks) \ + { \ + if (capacity == 0 || capacity == UINT64_MAX) \ + return NULL; \ + \ + if (!alloc) \ + alloc = &cmc_alloc_node_default; \ + \ + struct SNAME *_heap_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_heap_) \ + return NULL; \ + \ + /* Since each node can store two elements, divide the actual */ \ + /* capacity by 2 */ \ + /* Round the capacity of nodes up */ \ + capacity = capacity % 2 == 0 ? capacity / 2 : (capacity + 1) / 2; \ + \ + _heap_->buffer = alloc->calloc(capacity, sizeof(struct SNAME##_node)); \ + \ + if (!_heap_->buffer) \ + { \ + alloc->free(_heap_); \ + return NULL; \ + } \ + \ + _heap_->capacity = capacity; \ + _heap_->size = 0; \ + _heap_->count = 0; \ + _heap_->cmp = compare; \ + \ + _heap_->it_start = PFX##_impl_it_start; \ + _heap_->it_end = PFX##_impl_it_end; \ + \ + _heap_->alloc = alloc; \ + _heap_->callbacks = callbacks; \ + \ + return _heap_; \ + } \ + \ + void PFX##_clear(struct SNAME *_heap_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _heap_->count; i++) \ + { \ + deallocator(_heap_->buffer[i / 2].data[i % 2]); \ + } \ + } \ + \ + memset(_heap_->buffer, 0, sizeof(V) * _heap_->capacity); \ + \ + _heap_->size = 0; \ + _heap_->count = 0; \ + } \ + \ + void PFX##_free(struct SNAME *_heap_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _heap_->count; i++) \ + { \ + deallocator(_heap_->buffer[i / 2].data[i % 2]); \ + } \ + } \ + \ + _heap_->alloc->free(_heap_->buffer); \ + \ + _heap_->alloc->free(_heap_); \ + } \ + \ + void PFX##_customize(struct SNAME *_heap_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_intervalheap *callbacks) \ + { \ + if (alloc) \ + _heap_->alloc = alloc; \ + \ + if (callbacks) \ + _heap_->callbacks = callbacks; \ + } \ + \ + bool PFX##_insert(struct SNAME *_heap_, V element) \ + { \ + if (PFX##_full(_heap_)) \ + { \ + if (!PFX##_resize(_heap_, PFX##_capacity(_heap_) * 4)) \ + return false; \ + } \ + \ + if (PFX##_count(_heap_) % 2 == 0) \ + { \ + /* Occupying a new node */ \ + _heap_->buffer[_heap_->size].data[0] = element; \ + _heap_->buffer[_heap_->size].data[1] = (V){ 0 }; \ + \ + _heap_->size++; \ + } \ + else \ + { \ + struct SNAME##_node *curr_node = \ + &(_heap_->buffer[_heap_->size - 1]); \ + \ + /* Decide if the new element goes into the MinHeap or MaxHeap */ \ + if (_heap_->cmp(curr_node->data[0], element) > 0) \ + { \ + /* Swap current value and add new element to the MinHeap */ \ + curr_node->data[1] = curr_node->data[0]; \ + curr_node->data[0] = element; \ + } \ + else \ + { \ + /* No need to swap and add the new element to the MaxHeap */ \ + curr_node->data[1] = element; \ + } \ + } \ + \ + _heap_->count++; \ + \ + if (PFX##_count(_heap_) <= 2) \ + return true; \ + \ + /* Determine wheather to do a MaxHeap insert or a MinHeap insert */ \ + struct SNAME##_node *parent = \ + &(_heap_->buffer[(_heap_->size - 1) / 2]); \ + \ + if (_heap_->cmp(parent->data[0], element) > 0) \ + PFX##_impl_float_up_min(_heap_); \ + else if (_heap_->cmp(parent->data[1], element) < 0) \ + PFX##_impl_float_up_max(_heap_); \ + /* else no float up required */ \ + \ + return true; \ + } \ + \ + bool PFX##_remove_max(struct SNAME *_heap_, V *result) \ + { \ + if (PFX##_empty(_heap_)) \ + return false; \ + \ + if (PFX##_count(_heap_) == 1) \ + { \ + *result = _heap_->buffer[0].data[0]; \ + \ + _heap_->buffer[0].data[0] = (V){ 0 }; \ + \ + _heap_->count--; \ + \ + return true; \ + } \ + else \ + *result = _heap_->buffer[0].data[1]; \ + \ + /* Swap the result with the last element in the MaxHeap and float */ \ + /* it down */ \ + struct SNAME##_node *last_node = &(_heap_->buffer[_heap_->size - 1]); \ + \ + if (PFX##_count(_heap_) % 2 == 1) \ + { \ + /* Grab from MinHeap and discard last node */ \ + _heap_->buffer[0].data[1] = last_node->data[0]; \ + \ + last_node->data[0] = (V){ 0 }; \ + \ + _heap_->size--; \ + } \ + else \ + { \ + _heap_->buffer[0].data[1] = last_node->data[1]; \ + \ + last_node->data[1] = (V){ 0 }; \ + } \ + \ + _heap_->count--; \ + \ + /* FLoat Down on the MaxHeap */ \ + PFX##_impl_float_down_max(_heap_); \ + \ + return true; \ + } \ + \ + bool PFX##_remove_min(struct SNAME *_heap_, V *result) \ + { \ + if (PFX##_empty(_heap_)) \ + return false; \ + \ + *result = _heap_->buffer[0].data[0]; \ + \ + if (PFX##_count(_heap_) == 1) \ + { \ + _heap_->buffer[0].data[0] = (V){ 0 }; \ + \ + _heap_->count--; \ + \ + return true; \ + } \ + \ + /* Swap the result with the last element in the MinHeap and float */ \ + /* it down */ \ + struct SNAME##_node *last_node = &(_heap_->buffer[_heap_->size - 1]); \ + \ + _heap_->buffer[0].data[0] = last_node->data[0]; \ + \ + if (PFX##_count(_heap_) % 2 == 1) \ + { \ + /* Discard last node */ \ + last_node->data[0] = (V){ 0 }; \ + \ + _heap_->size--; \ + } \ + else \ + { \ + /* Place the MaxHeap value in the MinHeap value spot */ \ + last_node->data[0] = last_node->data[1]; \ + last_node->data[1] = (V){ 0 }; \ + } \ + \ + _heap_->count--; \ + \ + /* FLoat Down on the MinHeap */ \ + PFX##_impl_float_down_min(_heap_); \ + \ + return true; \ + } \ + \ + bool PFX##_update_max(struct SNAME *_heap_, V element) \ + { \ + if (PFX##_empty(_heap_)) \ + return false; \ + \ + if (PFX##_count(_heap_) == 1) \ + { \ + _heap_->buffer[0].data[0] = element; \ + } \ + else if (_heap_->cmp(element, _heap_->buffer[0].data[0]) < 0) \ + { \ + /* Corner case: we are updating the Max value but it is less */ \ + /* than the Min value */ \ + _heap_->buffer[0].data[1] = _heap_->buffer[0].data[0]; \ + _heap_->buffer[0].data[0] = element; \ + \ + PFX##_impl_float_down_max(_heap_); \ + } \ + else \ + { \ + /* Update Max element and float it down */ \ + _heap_->buffer[0].data[1] = element; \ + \ + PFX##_impl_float_down_max(_heap_); \ + } \ + \ + return true; \ + } \ + \ + bool PFX##_update_min(struct SNAME *_heap_, V element) \ + { \ + if (PFX##_empty(_heap_)) \ + return false; \ + \ + if (PFX##_count(_heap_) == 1) \ + { \ + _heap_->buffer[0].data[0] = element; \ + } \ + else if (_heap_->cmp(element, _heap_->buffer[0].data[1]) > 0) \ + { \ + /* Corner case: we are updating the Min value but it is greater */ \ + /* than the Max value. */ \ + _heap_->buffer[0].data[0] = _heap_->buffer[0].data[1]; \ + _heap_->buffer[0].data[1] = element; \ + \ + PFX##_impl_float_down_min(_heap_); \ + } \ + else \ + { \ + /* Update Min element and float it down */ \ + _heap_->buffer[0].data[0] = element; \ + \ + PFX##_impl_float_down_min(_heap_); \ + } \ + \ + return true; \ + } \ + \ + bool PFX##_max(struct SNAME *_heap_, V *value) \ + { \ + if (PFX##_empty(_heap_)) \ + return false; \ + \ + /* If there is only one element, then the maximum element is the */ \ + /* same as the one in the MinHeap */ \ + if (PFX##_count(_heap_) == 1) \ + *value = _heap_->buffer[0].data[0]; \ + else \ + *value = _heap_->buffer[0].data[1]; \ + \ + return true; \ + } \ + \ + bool PFX##_min(struct SNAME *_heap_, V *value) \ + { \ + if (PFX##_empty(_heap_)) \ + return false; \ + \ + *value = _heap_->buffer[0].data[0]; \ + \ + return true; \ + } \ + \ + bool PFX##_contains(struct SNAME *_heap_, V element) \ + { \ + for (size_t i = 0; i < _heap_->count; i++) \ + { \ + if (_heap_->cmp(_heap_->buffer[i / 2].data[i % 2], element) == 0) \ + return true; \ + } \ + \ + return false; \ + } \ + \ + bool PFX##_empty(struct SNAME *_heap_) \ + { \ + return _heap_->count == 0; \ + } \ + \ + bool PFX##_full(struct SNAME *_heap_) \ + { \ + /* The heap is full if all nodes are completely filled */ \ + return _heap_->size >= _heap_->capacity && _heap_->count % 2 == 0; \ + } \ + \ + size_t PFX##_count(struct SNAME *_heap_) \ + { \ + return _heap_->count; \ + } \ + \ + size_t PFX##_capacity(struct SNAME *_heap_) \ + { \ + return _heap_->capacity; \ + } \ + \ + bool PFX##_resize(struct SNAME *_heap_, size_t capacity) \ + { \ + if (PFX##_capacity(_heap_) == capacity) \ + return true; \ + \ + if (capacity < PFX##_count(_heap_)) \ + return false; \ + \ + capacity = capacity % 2 == 0 ? capacity / 2 : (capacity + 1) / 2; \ + \ + struct SNAME##_node *new_buffer = _heap_->alloc->realloc( \ + _heap_->buffer, sizeof(struct SNAME##_node) * capacity); \ + \ + if (!new_buffer) \ + return false; \ + \ + memset(new_buffer + _heap_->capacity, 0, \ + sizeof(struct SNAME##_node) * _heap_->capacity); \ + \ + _heap_->buffer = new_buffer; \ + _heap_->capacity = capacity; \ + \ + return true; \ + } \ + \ + struct SNAME *PFX##_copy_of(struct SNAME *_heap_, V (*copy_func)(V)) \ + { \ + struct SNAME *result = _heap_->alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!result) \ + return NULL; \ + \ + memcpy(result, _heap_, sizeof(struct SNAME)); \ + \ + result->buffer = _heap_->alloc->malloc(sizeof(struct SNAME##_node) * \ + _heap_->capacity); \ + \ + if (!result->buffer) \ + { \ + _heap_->alloc->free(result); \ + return NULL; \ + } \ + \ + if (copy_func) \ + { \ + for (size_t i = 0; i < _heap_->count; i++) \ + result->buffer[i / 2].data[i % 2] = \ + copy_func(_heap_->buffer[i / 2].data[i % 2]); \ + } \ + else \ + memcpy(result->buffer, _heap_->buffer, \ + sizeof(struct SNAME##_node) * _heap_->capacity); \ + \ + result->alloc = _heap_->alloc; \ + result->callbacks = _heap_->callbacks; \ + \ + return result; \ + } \ + \ + bool PFX##_equals(struct SNAME *_heap1_, struct SNAME *_heap2_) \ + { \ + if (PFX##_count(_heap1_) != PFX##_count(_heap2_)) \ + return false; \ + \ + for (size_t i = 0; i < _heap1_->count; i++) \ + { \ + V element1 = _heap1_->buffer[i / 2].data[i % 2]; \ + V element2 = _heap2_->buffer[i / 2].data[i % 2]; \ + \ + if (_heap1_->cmp(element1, element2) == 0) \ + return true; \ + } \ + \ + return false; \ + } \ + \ + struct cmc_string PFX##_to_string(struct SNAME *_heap_) \ + { \ + struct cmc_string str; \ + struct SNAME *h_ = _heap_; \ + \ + int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_intervalheap, \ + #SNAME, #V, h_, h_->buffer, h_->capacity, h_->size, \ + h_->count, h_->cmp, h_->alloc, h_->callbacks); \ + \ + if (n < 0 || n == (int)cmc_string_len) \ + return (struct cmc_string){ 0 }; \ + \ + str.s[n] = '\0'; \ + \ + return str; \ + } \ + \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ + { \ + struct SNAME##_iter *iter = \ + target->alloc->malloc(sizeof(struct SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + void PFX##_iter_free(struct SNAME##_iter *iter) \ + { \ + iter->target->alloc->free(iter); \ + } \ + \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ + { \ + iter->target = target; \ + iter->cursor = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + } \ + \ + bool PFX##_iter_start(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + bool PFX##_iter_end(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + void PFX##_iter_to_start(struct SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ + } \ + \ + void PFX##_iter_to_end(struct SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + } \ + } \ + \ + bool PFX##_iter_next(struct SNAME##_iter *iter) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->cursor + 1 == PFX##_count(iter->target)) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + iter->cursor++; \ + \ + return true; \ + } \ + \ + bool PFX##_iter_prev(struct SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor == 0) \ + { \ + 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(struct SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->cursor + steps >= PFX##_count(iter->target)) \ + return false; \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + iter->cursor += steps; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->cursor < steps) \ + 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(struct 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(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return (V){ 0 }; \ + \ + return iter->target->buffer[iter->cursor / 2].data[iter->cursor % 2]; \ + } \ + \ + size_t PFX##_iter_index(struct SNAME##_iter *iter) \ + { \ + return iter->cursor; \ + } \ + \ + static void PFX##_impl_float_up_max(struct SNAME *_heap_) \ + { \ + size_t index = _heap_->size - 1; \ + \ + struct SNAME##_node *curr_node = &(_heap_->buffer[index]); \ + \ + /* FLoat Up on the MaxHeap */ \ + while (index > 0) \ + { \ + /* Parent index */ \ + size_t P_index = (index - 1) / 2; \ + \ + struct SNAME##_node *parent = &(_heap_->buffer[P_index]); \ + \ + if (index == _heap_->size - 1 && PFX##_count(_heap_) % 2 != 0) \ + { \ + /* In this case, the current node has no MaxHeap value so */ \ + /* we instead compare with the MinHeap value */ \ + if (_heap_->cmp(curr_node->data[0], parent->data[1]) < 0) \ + break; \ + \ + /* Since the comparison above passed now we need to swap */ \ + /* the current node with the parent but it will have to be */ \ + /* done with the node's MinHeap value since the MaxHeap */ \ + /* value doesn't exist */ \ + V tmp = curr_node->data[0]; \ + curr_node->data[0] = parent->data[1]; \ + parent->data[1] = tmp; \ + } \ + else \ + { \ + /* Usual case, just compare both MaxHeap values */ \ + if (_heap_->cmp(curr_node->data[1], parent->data[1]) < 0) \ + break; \ + \ + /* Swap with parent and repeat */ \ + V tmp = curr_node->data[1]; \ + curr_node->data[1] = parent->data[1]; \ + parent->data[1] = tmp; \ + } \ + \ + /* Update indexe and node */ \ + index = P_index; \ + curr_node = parent; \ + } \ + } \ + \ + static void PFX##_impl_float_up_min(struct SNAME *_heap_) \ + { \ + size_t index = _heap_->size - 1; \ + \ + struct SNAME##_node *curr_node = &(_heap_->buffer[index]); \ + \ + /* FLoat Up on the MinHeap */ \ + while (index > 0) \ + { \ + /* Parent index */ \ + size_t P_index = (index - 1) / 2; \ + \ + struct SNAME##_node *parent = &(_heap_->buffer[P_index]); \ + \ + if (_heap_->cmp(curr_node->data[0], parent->data[0]) >= 0) \ + break; \ + \ + /* Swap with parent and repeat */ \ + V tmp = curr_node->data[0]; \ + curr_node->data[0] = parent->data[0]; \ + parent->data[0] = tmp; \ + \ + /* Update indexe and node */ \ + index = P_index; \ + curr_node = parent; \ + } \ + } \ + \ + static void PFX##_impl_float_down_max(struct SNAME *_heap_) \ + { \ + /* Floats Down from the MinHeap */ \ + size_t index = 0; \ + \ + struct SNAME##_node *curr_node = &(_heap_->buffer[index]); \ + \ + while (true) \ + { \ + /* If there are no children it is done */ \ + if (2 * index + 1 >= _heap_->size) \ + break; \ + \ + /* Child index to be compared with current value */ \ + size_t child; \ + size_t L_index = index * 2 + 1; \ + size_t R_index = index * 2 + 2; \ + \ + /* If there are two children, pick the smallest one */ \ + if (R_index < _heap_->size) \ + { \ + struct SNAME##_node *L = &(_heap_->buffer[L_index]); \ + struct SNAME##_node *R = &(_heap_->buffer[R_index]); \ + \ + /* If the right child is the last node and there is no */ \ + /* MaxHeap value */ \ + /* then do the comparison with the MinHeap value */ \ + if (R_index == _heap_->size - 1 && \ + PFX##_count(_heap_) % 2 != 0) \ + child = _heap_->cmp(L->data[1], R->data[0]) > 0 ? L_index \ + : R_index; \ + else \ + child = _heap_->cmp(L->data[1], R->data[1]) > 0 ? L_index \ + : R_index; \ + } \ + /* Pick the only one available */ \ + else \ + child = L_index; \ + \ + struct SNAME##_node *child_node = &(_heap_->buffer[child]); \ + \ + /* Again, check if the child node is the last one and has no */ \ + /* MaxHeap value */ \ + if (child == _heap_->size - 1 && PFX##_count(_heap_) % 2 != 0) \ + { \ + /* Odd case, compare with MinHeap value */ \ + /* If current value is not less than the child node's */ \ + /* value it is done */ \ + if (_heap_->cmp(curr_node->data[1], child_node->data[0]) >= 0) \ + break; \ + \ + /* Otherwise swap and continue */ \ + V tmp = child_node->data[0]; \ + child_node->data[0] = curr_node->data[1]; \ + curr_node->data[1] = tmp; \ + } \ + else \ + { \ + /* If current value is not less than the child node's */ \ + /* value it is done */ \ + if (_heap_->cmp(curr_node->data[1], child_node->data[1]) >= 0) \ + break; \ + \ + /* Otherwise swap and continue */ \ + V tmp = child_node->data[1]; \ + child_node->data[1] = curr_node->data[1]; \ + curr_node->data[1] = tmp; \ + \ + /* Check if the MinHeap and MaxHeap values need to be */ \ + /* swapped */ \ + if (_heap_->cmp(child_node->data[0], child_node->data[1]) > 0) \ + { \ + /* Swap because the MinHeap value is greater than the */ \ + /* MaxHeap value */ \ + tmp = child_node->data[0]; \ + child_node->data[0] = child_node->data[1]; \ + child_node->data[1] = tmp; \ + } \ + } \ + \ + /* Update index and node */ \ + index = child; \ + curr_node = child_node; \ + } \ + } \ + \ + static void PFX##_impl_float_down_min(struct SNAME *_heap_) \ + { \ + /* Floats Down from the MinHeap */ \ + size_t index = 0; \ + \ + struct SNAME##_node *curr_node = &(_heap_->buffer[index]); \ + \ + while (true) \ + { \ + /* If there are no children it is done */ \ + if (2 * index + 1 >= _heap_->size) \ + break; \ + \ + /* Child index to be compared with current value */ \ + size_t child; \ + size_t L_index = index * 2 + 1; \ + size_t R_index = index * 2 + 2; \ + \ + /* If there are two children, pick the smallest one */ \ + if (R_index < _heap_->size) \ + { \ + struct SNAME##_node *L = &(_heap_->buffer[L_index]); \ + struct SNAME##_node *R = &(_heap_->buffer[R_index]); \ + \ + child = _heap_->cmp(L->data[0], R->data[0]) < 0 ? L_index \ + : R_index; \ + } \ + /* Pick the only one available */ \ + else \ + child = L_index; \ + \ + struct SNAME##_node *child_node = &(_heap_->buffer[child]); \ + \ + /* If current value is smaller than the child node's value, it */ \ + /* is done */ \ + if (_heap_->cmp(curr_node->data[0], child_node->data[0]) < 0) \ + break; \ + \ + /* Otherwise swap and continue */ \ + V tmp = child_node->data[0]; \ + child_node->data[0] = curr_node->data[0]; \ + curr_node->data[0] = tmp; \ + \ + /* If the child node is the last node check if the MinHeap and */ \ + /* MaxHeap values need to be swapped */ \ + if (child != _heap_->size - 1 || PFX##_count(_heap_) % 2 == 0) \ + { \ + if (_heap_->cmp(child_node->data[0], child_node->data[1]) > 0) \ + { \ + /* Swap because the MinHeap value is greater than the */ \ + /* MaxHeap value */ \ + tmp = child_node->data[0]; \ + child_node->data[0] = child_node->data[1]; \ + child_node->data[1] = tmp; \ + } \ + } \ + \ + /* Update index and node */ \ + index = child; \ + curr_node = child_node; \ + } \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_heap_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _heap_); \ + PFX##_iter_to_start(&iter); \ + \ + return iter; \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_heap_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _heap_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_INTERVALHEAP_H */ diff --git a/src/cmc/linkedlist.h b/src/cmc/linkedlist.h index da060a5..2c0f630 100644 --- a/src/cmc/linkedlist.h +++ b/src/cmc/linkedlist.h @@ -30,13 +30,13 @@ #include #include -#include #include +#include #include -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Core functionalities of the C Macro Collections Library - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ #ifndef CMC_CORE_H #define CMC_CORE_H @@ -55,7 +55,8 @@ static const size_t cmc_string_len = 400; /** * struct cmc_alloc_node * - * Custom allocation node. Allows collections to use custom allocation functions. + * Custom allocation node. Allows collections to use custom allocation + * functions. */ struct cmc_alloc_node { @@ -65,13 +66,14 @@ struct cmc_alloc_node void (*free)(void *); }; -static struct cmc_alloc_node cmc_alloc_node_default = {malloc, calloc, realloc, free}; +static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, + free }; #endif /* CMC_CORE_H */ -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * LinkedList specific - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ /* to_string format */ static const char *cmc_string_fmt_linkedlist = "struct %s<%s> " "at %p { " @@ -106,914 +108,932 @@ struct cmc_callbacks_linkedlist #define CMC_WRAPGEN_LINKEDLIST_SOURCE(PFX, SNAME, K, V) \ CMC_GENERATE_LINKEDLIST_SOURCE(PFX, SNAME, V) -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Header - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_LINKEDLIST_HEADER(PFX, SNAME, V) \ - \ - /* Linked List Structure */ \ - struct SNAME \ - { \ - /* First node in the list */ \ - struct SNAME##_node *head; \ - \ - /* Last node in the list */ \ - struct SNAME##_node *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 (*it_start)(struct SNAME *); \ - \ - /* Function that returns an iterator to the end of the list */ \ - struct SNAME##_iter (*it_end)(struct SNAME *); \ - \ - /* Custom allocation functions */ \ - struct cmc_alloc_node *alloc; \ - \ - /* Custom callback functions */ \ - struct cmc_callbacks_linkedlist *callbacks; \ - }; \ - \ - /* Doubly-linked list node */ \ - struct SNAME##_node \ - { \ - /* Node's data */ \ - V data; \ - \ - /* Pointer to the next node on the linked list */ \ - struct SNAME##_node *next; \ - \ - /* Pointer to the previous node on the linked list */ \ - struct SNAME##_node *prev; \ - }; \ - \ - /* Linked List Iterator */ \ - struct SNAME##_iter \ - { \ - /* Target Linked List */ \ - struct SNAME *target; \ - \ - /* Cursor's current node */ \ - struct SNAME##_node *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; \ - }; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - struct SNAME *PFX##_new(void); \ - struct SNAME *PFX##_new_custom(struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_linkedlist *callbacks); \ - void PFX##_clear(struct SNAME *_list_, void (*deallocator)(V)); \ - void PFX##_free(struct SNAME *_list_, void (*deallocator)(V)); \ - /* Customization of Allocation and Callbacks */ \ - void PFX##_customize(struct SNAME *_list_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_linkedlist *callbacks); \ - /* Collection Input and Output */ \ - bool PFX##_push_front(struct SNAME *_list_, V element); \ - bool PFX##_push_at(struct SNAME *_list_, V element, size_t index); \ - bool PFX##_push_back(struct SNAME *_list_, V element); \ - bool PFX##_pop_front(struct SNAME *_list_); \ - bool PFX##_pop_at(struct SNAME *_list_, size_t index); \ - bool PFX##_pop_back(struct SNAME *_list_); \ - /* Element Access */ \ - V PFX##_front(struct SNAME *_list_); \ - V PFX##_get(struct SNAME *_list_, size_t index); \ - V *PFX##_get_ref(struct SNAME *_list_, size_t index); \ - V PFX##_back(struct SNAME *_list_); \ - /* Collection State */ \ - bool PFX##_contains(struct SNAME *_list_, V element, int (*comparator)(V, V)); \ - bool PFX##_empty(struct SNAME *_list_); \ - size_t PFX##_count(struct SNAME *_list_); \ - /* Collection Utility */ \ - struct SNAME *PFX##_copy_of(struct SNAME *_list_, V (*copy_func)(V)); \ - bool PFX##_equals(struct SNAME *_list1_, struct SNAME *_list2_, int (*comparator)(V, V)); \ - struct cmc_string PFX##_to_string(struct SNAME *_list_); \ - \ - /* Node Related Functions */ \ - /* Node Allocation and Deallocation */ \ - struct SNAME##_node *PFX##_new_node(struct SNAME *_list_, V element); \ - void PFX##_free_node(struct SNAME *_list_, struct SNAME##_node *_node_); \ - /* Node Access Relative to a Linked List */ \ - struct SNAME##_node *PFX##_head(struct SNAME *_list_); \ - struct SNAME##_node *PFX##_get_node(struct SNAME *_list_, size_t index); \ - struct SNAME##_node *PFX##_tail(struct SNAME *_list_); \ - /* Input and Output Relative to a Node */ \ - bool PFX##_insert_after(struct SNAME *_owner_, struct SNAME##_node *_node_, V element); \ - bool PFX##_insert_before(struct SNAME *_owner_, struct SNAME##_node *_node_, V element); \ - bool PFX##_remove_after(struct SNAME *_owner_, struct SNAME##_node *_node_); \ - bool PFX##_remove_current(struct SNAME *_owner_, struct SNAME##_node *_node_); \ - bool PFX##_remove_before(struct SNAME *_owner_, struct SNAME##_node *_node_); \ - /* Node Access Relative to a Linked List Node */ \ - struct SNAME##_node *PFX##_next_node(struct SNAME##_node *_node_); \ - struct SNAME##_node *PFX##_prev_node(struct SNAME##_node *_node_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ - void PFX##_iter_free(struct SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(struct SNAME##_iter *iter); \ - bool PFX##_iter_end(struct SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(struct SNAME##_iter *iter); \ - void PFX##_iter_to_end(struct SNAME##_iter *iter); \ - bool PFX##_iter_next(struct SNAME##_iter *iter); \ - bool PFX##_iter_prev(struct SNAME##_iter *iter); \ - bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - V PFX##_iter_value(struct SNAME##_iter *iter); \ - V *PFX##_iter_rvalue(struct SNAME##_iter *iter); \ - size_t PFX##_iter_index(struct SNAME##_iter *iter); \ + * ------------------------------------------------------------------------- */ +#define CMC_GENERATE_LINKEDLIST_HEADER(PFX, SNAME, V) \ + \ + /* Linked List Structure */ \ + struct SNAME \ + { \ + /* First node in the list */ \ + struct SNAME##_node *head; \ + \ + /* Last node in the list */ \ + struct SNAME##_node *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 (*it_start)(struct SNAME *); \ + \ + /* Function that returns an iterator to the end of the list */ \ + struct SNAME##_iter (*it_end)(struct SNAME *); \ + \ + /* Custom allocation functions */ \ + struct cmc_alloc_node *alloc; \ + \ + /* Custom callback functions */ \ + struct cmc_callbacks_linkedlist *callbacks; \ + }; \ + \ + /* Doubly-linked list node */ \ + struct SNAME##_node \ + { \ + /* Node's data */ \ + V data; \ + \ + /* Pointer to the next node on the linked list */ \ + struct SNAME##_node *next; \ + \ + /* Pointer to the previous node on the linked list */ \ + struct SNAME##_node *prev; \ + }; \ + \ + /* Linked List Iterator */ \ + struct SNAME##_iter \ + { \ + /* Target Linked List */ \ + struct SNAME *target; \ + \ + /* Cursor's current node */ \ + struct SNAME##_node *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; \ + }; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + struct SNAME *PFX##_new(void); \ + struct SNAME *PFX##_new_custom( \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_linkedlist *callbacks); \ + void PFX##_clear(struct SNAME *_list_, void (*deallocator)(V)); \ + void PFX##_free(struct SNAME *_list_, void (*deallocator)(V)); \ + /* Customization of Allocation and Callbacks */ \ + void PFX##_customize(struct SNAME *_list_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_linkedlist *callbacks); \ + /* Collection Input and Output */ \ + bool PFX##_push_front(struct SNAME *_list_, V element); \ + bool PFX##_push_at(struct SNAME *_list_, V element, size_t index); \ + bool PFX##_push_back(struct SNAME *_list_, V element); \ + bool PFX##_pop_front(struct SNAME *_list_); \ + bool PFX##_pop_at(struct SNAME *_list_, size_t index); \ + bool PFX##_pop_back(struct SNAME *_list_); \ + /* Element Access */ \ + V PFX##_front(struct SNAME *_list_); \ + V PFX##_get(struct SNAME *_list_, size_t index); \ + V *PFX##_get_ref(struct SNAME *_list_, size_t index); \ + V PFX##_back(struct SNAME *_list_); \ + /* Collection State */ \ + bool PFX##_contains(struct SNAME *_list_, V element, \ + int (*comparator)(V, V)); \ + bool PFX##_empty(struct SNAME *_list_); \ + size_t PFX##_count(struct SNAME *_list_); \ + /* Collection Utility */ \ + struct SNAME *PFX##_copy_of(struct SNAME *_list_, V (*copy_func)(V)); \ + bool PFX##_equals(struct SNAME *_list1_, struct SNAME *_list2_, \ + int (*comparator)(V, V)); \ + struct cmc_string PFX##_to_string(struct SNAME *_list_); \ + \ + /* Node Related Functions */ \ + /* Node Allocation and Deallocation */ \ + struct SNAME##_node *PFX##_new_node(struct SNAME *_list_, V element); \ + void PFX##_free_node(struct SNAME *_list_, struct SNAME##_node *_node_); \ + /* Node Access Relative to a Linked List */ \ + struct SNAME##_node *PFX##_head(struct SNAME *_list_); \ + struct SNAME##_node *PFX##_get_node(struct SNAME *_list_, size_t index); \ + struct SNAME##_node *PFX##_tail(struct SNAME *_list_); \ + /* Input and Output Relative to a Node */ \ + bool PFX##_insert_after(struct SNAME *_owner_, \ + struct SNAME##_node *_node_, V element); \ + bool PFX##_insert_before(struct SNAME *_owner_, \ + struct SNAME##_node *_node_, V element); \ + bool PFX##_remove_after(struct SNAME *_owner_, \ + struct SNAME##_node *_node_); \ + bool PFX##_remove_current(struct SNAME *_owner_, \ + struct SNAME##_node *_node_); \ + bool PFX##_remove_before(struct SNAME *_owner_, \ + struct SNAME##_node *_node_); \ + /* Node Access Relative to a Linked List Node */ \ + struct SNAME##_node *PFX##_next_node(struct SNAME##_node *_node_); \ + struct SNAME##_node *PFX##_prev_node(struct SNAME##_node *_node_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ + void PFX##_iter_free(struct SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(struct SNAME##_iter *iter); \ + bool PFX##_iter_end(struct SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(struct SNAME##_iter *iter); \ + void PFX##_iter_to_end(struct SNAME##_iter *iter); \ + bool PFX##_iter_next(struct SNAME##_iter *iter); \ + bool PFX##_iter_prev(struct SNAME##_iter *iter); \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + V PFX##_iter_value(struct SNAME##_iter *iter); \ + V *PFX##_iter_rvalue(struct SNAME##_iter *iter); \ + size_t PFX##_iter_index(struct SNAME##_iter *iter); \ struct SNAME##_node *PFX##_iter_node(struct SNAME##_iter *iter); -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Source - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_LINKEDLIST_SOURCE(PFX, SNAME, V) \ - \ - /* Implementation Detail Functions */ \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_list_); \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_list_); \ - \ - struct SNAME *PFX##_new(void) \ - { \ - struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ - \ - struct SNAME *_list_ = alloc->malloc(sizeof(struct 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; \ - \ - _list_->alloc = alloc; \ - _list_->callbacks = NULL; \ - \ - return _list_; \ - } \ - \ - struct SNAME *PFX##_new_custom(struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_linkedlist *callbacks) \ - { \ - if (!alloc) \ - alloc = &cmc_alloc_node_default; \ - \ - struct SNAME *_list_ = alloc->malloc(sizeof(struct 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; \ - \ - _list_->alloc = alloc; \ - _list_->callbacks = callbacks; \ - \ - return _list_; \ - } \ - \ - void PFX##_clear(struct SNAME *_list_, void (*deallocator)(V)) \ - { \ - struct SNAME##_node *scan = _list_->head; \ - \ - while (_list_->head != NULL) \ - { \ - _list_->head = _list_->head->next; \ - \ - if (deallocator) \ - { \ - deallocator(scan->data); \ - } \ - \ - _list_->alloc->free(scan); \ - \ - scan = _list_->head; \ - } \ - \ - _list_->count = 0; \ - _list_->head = NULL; \ - _list_->tail = NULL; \ - } \ - \ - void PFX##_free(struct SNAME *_list_, void (*deallocator)(V)) \ - { \ - PFX##_clear(_list_, deallocator); \ - \ - _list_->alloc->free(_list_); \ - } \ - \ - void PFX##_customize(struct SNAME *_list_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_linkedlist *callbacks) \ - { \ - if (alloc) \ - _list_->alloc = alloc; \ - \ - if (callbacks) \ - _list_->callbacks = callbacks; \ - } \ - \ - bool PFX##_push_front(struct SNAME *_list_, V element) \ - { \ - struct SNAME##_node *_node_ = PFX##_new_node(_list_, 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_at(struct 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); \ - } \ - \ - struct SNAME##_node *_node_ = PFX##_new_node(_list_, element); \ - \ - if (!_node_) \ - return false; \ - \ - struct 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(struct SNAME *_list_, V element) \ - { \ - struct SNAME##_node *_node_ = PFX##_new_node(_list_, 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(struct SNAME *_list_) \ - { \ - if (PFX##_empty(_list_)) \ - return false; \ - \ - struct SNAME##_node *_node_ = _list_->head; \ - _list_->head = _list_->head->next; \ - \ - _list_->alloc->free(_node_); \ - \ - if (_list_->head == NULL) \ - _list_->tail = NULL; \ - else \ - _list_->head->prev = NULL; \ - \ - _list_->count--; \ - \ - return true; \ - } \ - \ - bool PFX##_pop_at(struct 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_); \ - } \ - \ - struct SNAME##_node *_node_ = PFX##_get_node(_list_, index); \ - \ - if (!_node_) \ - return false; \ - \ - _node_->next->prev = _node_->prev; \ - _node_->prev->next = _node_->next; \ - \ - _list_->alloc->free(_node_); \ - \ - _list_->count--; \ - \ - return true; \ - } \ - \ - bool PFX##_pop_back(struct SNAME *_list_) \ - { \ - if (PFX##_empty(_list_)) \ - return false; \ - \ - struct SNAME##_node *_node_ = _list_->tail; \ - _list_->tail = _list_->tail->prev; \ - \ - _list_->alloc->free(_node_); \ - \ - if (_list_->tail == NULL) \ - _list_->head = NULL; \ - else \ - _list_->tail->next = NULL; \ - \ - _list_->count--; \ - \ - return true; \ - } \ - \ - V PFX##_front(struct SNAME *_list_) \ - { \ - if (PFX##_empty(_list_)) \ - return (V){0}; \ - \ - return _list_->head->data; \ - } \ - \ - V PFX##_get(struct SNAME *_list_, size_t index) \ - { \ - if (index >= _list_->count || PFX##_empty(_list_)) \ - return (V){0}; \ - \ - struct SNAME##_node *scan = PFX##_get_node(_list_, index); \ - \ - if (scan == NULL) \ - return (V){0}; \ - \ - return scan->data; \ - } \ - \ - V *PFX##_get_ref(struct SNAME *_list_, size_t index) \ - { \ - if (index >= _list_->count) \ - return NULL; \ - \ - if (PFX##_empty(_list_)) \ - return NULL; \ - \ - struct SNAME##_node *scan = PFX##_get_node(_list_, index); \ - \ - if (scan == NULL) \ - return NULL; \ - \ - return &(scan->data); \ - } \ - \ - V PFX##_back(struct SNAME *_list_) \ - { \ - if (PFX##_empty(_list_)) \ - return (V){0}; \ - \ - return _list_->tail->data; \ - } \ - \ - bool PFX##_contains(struct SNAME *_list_, V element, int (*comparator)(V, V)) \ - { \ - struct SNAME##_node *scan = _list_->head; \ - \ - while (scan != NULL) \ - { \ - if (comparator(scan->data, element) == 0) \ - return true; \ - \ - scan = scan->next; \ - } \ - \ - return false; \ - } \ - \ - bool PFX##_empty(struct SNAME *_list_) \ - { \ - return _list_->count == 0; \ - } \ - \ - size_t PFX##_count(struct SNAME *_list_) \ - { \ - return _list_->count; \ - } \ - \ - struct SNAME *PFX##_copy_of(struct SNAME *_list_, V (*copy_func)(V)) \ - { \ - struct SNAME *result = PFX##_new_custom(_list_->alloc, _list_->callbacks); \ - \ - if (!result) \ - return NULL; \ - \ - struct 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 */ \ - struct SNAME##_node *new_node; \ - \ - if (copy_func) \ - new_node = PFX##_new_node(_list_, copy_func(scan->data)); \ - else \ - new_node = PFX##_new_node(_list_, 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(struct SNAME *_list1_, struct SNAME *_list2_, int (*comparator)(V, V)) \ - { \ - if (PFX##_count(_list1_) != PFX##_count(_list2_)) \ - return false; \ - \ - struct SNAME##_node *scan1 = _list1_->head; \ - struct 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; \ - } \ - \ - struct cmc_string PFX##_to_string(struct SNAME *_list_) \ - { \ - struct cmc_string str; \ - struct SNAME *l_ = _list_; \ - \ - int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_linkedlist, \ - #SNAME, #V, l_, l_->count, l_->head, l_->tail, \ - l_->alloc, l_->callbacks); \ - \ - if (n < 0 || n == (int)cmc_string_len) \ - return (struct cmc_string){0}; \ - \ - str.s[n] = '\0'; \ - \ - return str; \ - } \ - \ - struct SNAME##_node *PFX##_new_node(struct SNAME *_list_, V element) \ - { \ - struct SNAME##_node *_node_ = _list_->alloc->malloc(sizeof(struct SNAME##_node)); \ - \ - if (!_node_) \ - return NULL; \ - \ - _node_->data = element; \ - _node_->next = NULL; \ - _node_->prev = NULL; \ - \ - return _node_; \ - } \ - \ - void PFX##_free_node(struct SNAME *_list_, struct SNAME##_node *_node_) \ - { \ - _list_->alloc->free(_node_); \ - } \ - \ - struct SNAME##_node *PFX##_head(struct SNAME *_list_) \ - { \ - return _list_->head; \ - } \ - \ - struct SNAME##_node *PFX##_get_node(struct SNAME *_list_, size_t index) \ - { \ - if (index >= _list_->count) \ - return NULL; \ - \ - if (PFX##_empty(_list_)) \ - return NULL; \ - \ - struct 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_; \ - } \ - \ - struct SNAME##_node *PFX##_tail(struct SNAME *_list_) \ - { \ - return _list_->tail; \ - } \ - \ - bool PFX##_insert_after(struct SNAME *_owner_, struct SNAME##_node *_node_, V element) \ - { \ - struct SNAME##_node *new_node = PFX##_new_node(_owner_, 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(struct SNAME *_owner_, struct SNAME##_node *_node_, V element) \ - { \ - struct SNAME##_node *new_node = PFX##_new_node(_owner_, 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(struct SNAME *_owner_, struct SNAME##_node *_node_) \ - { \ - if (_node_->next == NULL) \ - return false; \ - \ - struct SNAME##_node *tmp = _node_->next; \ - \ - if (tmp->next != NULL) \ - { \ - _node_->next = _node_->next->next; \ - _node_->next->prev = _node_; \ - } \ - else \ - _owner_->tail = _node_; \ - \ - _owner_->alloc->free(tmp); \ - \ - _owner_->count--; \ - \ - return true; \ - } \ - \ - bool PFX##_remove_current(struct SNAME *_owner_, struct 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; \ - \ - _owner_->alloc->free(_node_); \ - \ - _owner_->count--; \ - \ - return true; \ - } \ - \ - bool PFX##_remove_before(struct SNAME *_owner_, struct SNAME##_node *_node_) \ - { \ - if (_node_->prev == NULL) \ - return false; \ - \ - struct SNAME##_node *tmp = _node_->prev; \ - \ - if (tmp->prev != NULL) \ - { \ - _node_->prev = _node_->prev->prev; \ - _node_->prev->next = _node_; \ - } \ - else \ - _owner_->head = _node_; \ - \ - _owner_->alloc->free(tmp); \ - \ - _owner_->count--; \ - \ - return true; \ - } \ - \ - struct SNAME##_node *PFX##_next_node(struct SNAME##_node *_node_) \ - { \ - return _node_->next; \ - } \ - \ - struct SNAME##_node *PFX##_prev_node(struct SNAME##_node *_node_) \ - { \ - return _node_->prev; \ - } \ - \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ - { \ - struct SNAME##_iter *iter = target->alloc->malloc(sizeof(struct SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(struct SNAME##_iter *iter) \ - { \ - iter->target->alloc->free(iter); \ - } \ - \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ - { \ - iter->target = target; \ - iter->cursor = target->head; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - } \ - \ - bool PFX##_iter_start(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(struct 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(struct 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(struct 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(struct 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(struct 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(struct 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(struct 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(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){0}; \ - \ - return iter->cursor->data; \ - } \ - \ - V *PFX##_iter_rvalue(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->cursor->data); \ - } \ - \ - size_t PFX##_iter_index(struct SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - struct SNAME##_node *PFX##_iter_node(struct SNAME##_iter *iter) \ - { \ - return iter->cursor; \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_list_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _list_); \ - PFX##_iter_to_start(&iter); \ - \ - return iter; \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_list_) \ - { \ - struct 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 struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_list_); \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_list_); \ + \ + struct SNAME *PFX##_new(void) \ + { \ + struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ + \ + struct SNAME *_list_ = alloc->malloc(sizeof(struct 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; \ + \ + _list_->alloc = alloc; \ + _list_->callbacks = NULL; \ + \ + return _list_; \ + } \ + \ + struct SNAME *PFX##_new_custom(struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_linkedlist *callbacks) \ + { \ + if (!alloc) \ + alloc = &cmc_alloc_node_default; \ + \ + struct SNAME *_list_ = alloc->malloc(sizeof(struct 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; \ + \ + _list_->alloc = alloc; \ + _list_->callbacks = callbacks; \ + \ + return _list_; \ + } \ + \ + void PFX##_clear(struct SNAME *_list_, void (*deallocator)(V)) \ + { \ + struct SNAME##_node *scan = _list_->head; \ + \ + while (_list_->head != NULL) \ + { \ + _list_->head = _list_->head->next; \ + \ + if (deallocator) \ + { \ + deallocator(scan->data); \ + } \ + \ + _list_->alloc->free(scan); \ + \ + scan = _list_->head; \ + } \ + \ + _list_->count = 0; \ + _list_->head = NULL; \ + _list_->tail = NULL; \ + } \ + \ + void PFX##_free(struct SNAME *_list_, void (*deallocator)(V)) \ + { \ + PFX##_clear(_list_, deallocator); \ + \ + _list_->alloc->free(_list_); \ + } \ + \ + void PFX##_customize(struct SNAME *_list_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_linkedlist *callbacks) \ + { \ + if (alloc) \ + _list_->alloc = alloc; \ + \ + if (callbacks) \ + _list_->callbacks = callbacks; \ + } \ + \ + bool PFX##_push_front(struct SNAME *_list_, V element) \ + { \ + struct SNAME##_node *_node_ = PFX##_new_node(_list_, 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_at(struct 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); \ + } \ + \ + struct SNAME##_node *_node_ = PFX##_new_node(_list_, element); \ + \ + if (!_node_) \ + return false; \ + \ + struct 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(struct SNAME *_list_, V element) \ + { \ + struct SNAME##_node *_node_ = PFX##_new_node(_list_, 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(struct SNAME *_list_) \ + { \ + if (PFX##_empty(_list_)) \ + return false; \ + \ + struct SNAME##_node *_node_ = _list_->head; \ + _list_->head = _list_->head->next; \ + \ + _list_->alloc->free(_node_); \ + \ + if (_list_->head == NULL) \ + _list_->tail = NULL; \ + else \ + _list_->head->prev = NULL; \ + \ + _list_->count--; \ + \ + return true; \ + } \ + \ + bool PFX##_pop_at(struct 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_); \ + } \ + \ + struct SNAME##_node *_node_ = PFX##_get_node(_list_, index); \ + \ + if (!_node_) \ + return false; \ + \ + _node_->next->prev = _node_->prev; \ + _node_->prev->next = _node_->next; \ + \ + _list_->alloc->free(_node_); \ + \ + _list_->count--; \ + \ + return true; \ + } \ + \ + bool PFX##_pop_back(struct SNAME *_list_) \ + { \ + if (PFX##_empty(_list_)) \ + return false; \ + \ + struct SNAME##_node *_node_ = _list_->tail; \ + _list_->tail = _list_->tail->prev; \ + \ + _list_->alloc->free(_node_); \ + \ + if (_list_->tail == NULL) \ + _list_->head = NULL; \ + else \ + _list_->tail->next = NULL; \ + \ + _list_->count--; \ + \ + return true; \ + } \ + \ + V PFX##_front(struct SNAME *_list_) \ + { \ + if (PFX##_empty(_list_)) \ + return (V){ 0 }; \ + \ + return _list_->head->data; \ + } \ + \ + V PFX##_get(struct SNAME *_list_, size_t index) \ + { \ + if (index >= _list_->count || PFX##_empty(_list_)) \ + return (V){ 0 }; \ + \ + struct SNAME##_node *scan = PFX##_get_node(_list_, index); \ + \ + if (scan == NULL) \ + return (V){ 0 }; \ + \ + return scan->data; \ + } \ + \ + V *PFX##_get_ref(struct SNAME *_list_, size_t index) \ + { \ + if (index >= _list_->count) \ + return NULL; \ + \ + if (PFX##_empty(_list_)) \ + return NULL; \ + \ + struct SNAME##_node *scan = PFX##_get_node(_list_, index); \ + \ + if (scan == NULL) \ + return NULL; \ + \ + return &(scan->data); \ + } \ + \ + V PFX##_back(struct SNAME *_list_) \ + { \ + if (PFX##_empty(_list_)) \ + return (V){ 0 }; \ + \ + return _list_->tail->data; \ + } \ + \ + bool PFX##_contains(struct SNAME *_list_, V element, \ + int (*comparator)(V, V)) \ + { \ + struct SNAME##_node *scan = _list_->head; \ + \ + while (scan != NULL) \ + { \ + if (comparator(scan->data, element) == 0) \ + return true; \ + \ + scan = scan->next; \ + } \ + \ + return false; \ + } \ + \ + bool PFX##_empty(struct SNAME *_list_) \ + { \ + return _list_->count == 0; \ + } \ + \ + size_t PFX##_count(struct SNAME *_list_) \ + { \ + return _list_->count; \ + } \ + \ + struct SNAME *PFX##_copy_of(struct SNAME *_list_, V (*copy_func)(V)) \ + { \ + struct SNAME *result = \ + PFX##_new_custom(_list_->alloc, _list_->callbacks); \ + \ + if (!result) \ + return NULL; \ + \ + struct 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 */ \ + struct SNAME##_node *new_node; \ + \ + if (copy_func) \ + new_node = PFX##_new_node(_list_, copy_func(scan->data)); \ + else \ + new_node = PFX##_new_node(_list_, 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(struct SNAME *_list1_, struct SNAME *_list2_, \ + int (*comparator)(V, V)) \ + { \ + if (PFX##_count(_list1_) != PFX##_count(_list2_)) \ + return false; \ + \ + struct SNAME##_node *scan1 = _list1_->head; \ + struct 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; \ + } \ + \ + struct cmc_string PFX##_to_string(struct SNAME *_list_) \ + { \ + struct cmc_string str; \ + struct SNAME *l_ = _list_; \ + \ + int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_linkedlist, \ + #SNAME, #V, l_, l_->count, l_->head, l_->tail, \ + l_->alloc, l_->callbacks); \ + \ + if (n < 0 || n == (int)cmc_string_len) \ + return (struct cmc_string){ 0 }; \ + \ + str.s[n] = '\0'; \ + \ + return str; \ + } \ + \ + struct SNAME##_node *PFX##_new_node(struct SNAME *_list_, V element) \ + { \ + struct SNAME##_node *_node_ = \ + _list_->alloc->malloc(sizeof(struct SNAME##_node)); \ + \ + if (!_node_) \ + return NULL; \ + \ + _node_->data = element; \ + _node_->next = NULL; \ + _node_->prev = NULL; \ + \ + return _node_; \ + } \ + \ + void PFX##_free_node(struct SNAME *_list_, struct SNAME##_node *_node_) \ + { \ + _list_->alloc->free(_node_); \ + } \ + \ + struct SNAME##_node *PFX##_head(struct SNAME *_list_) \ + { \ + return _list_->head; \ + } \ + \ + struct SNAME##_node *PFX##_get_node(struct SNAME *_list_, size_t index) \ + { \ + if (index >= _list_->count) \ + return NULL; \ + \ + if (PFX##_empty(_list_)) \ + return NULL; \ + \ + struct 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_; \ + } \ + \ + struct SNAME##_node *PFX##_tail(struct SNAME *_list_) \ + { \ + return _list_->tail; \ + } \ + \ + bool PFX##_insert_after(struct SNAME *_owner_, \ + struct SNAME##_node *_node_, V element) \ + { \ + struct SNAME##_node *new_node = PFX##_new_node(_owner_, 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(struct SNAME *_owner_, \ + struct SNAME##_node *_node_, V element) \ + { \ + struct SNAME##_node *new_node = PFX##_new_node(_owner_, 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(struct SNAME *_owner_, \ + struct SNAME##_node *_node_) \ + { \ + if (_node_->next == NULL) \ + return false; \ + \ + struct SNAME##_node *tmp = _node_->next; \ + \ + if (tmp->next != NULL) \ + { \ + _node_->next = _node_->next->next; \ + _node_->next->prev = _node_; \ + } \ + else \ + _owner_->tail = _node_; \ + \ + _owner_->alloc->free(tmp); \ + \ + _owner_->count--; \ + \ + return true; \ + } \ + \ + bool PFX##_remove_current(struct SNAME *_owner_, \ + struct 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; \ + \ + _owner_->alloc->free(_node_); \ + \ + _owner_->count--; \ + \ + return true; \ + } \ + \ + bool PFX##_remove_before(struct SNAME *_owner_, \ + struct SNAME##_node *_node_) \ + { \ + if (_node_->prev == NULL) \ + return false; \ + \ + struct SNAME##_node *tmp = _node_->prev; \ + \ + if (tmp->prev != NULL) \ + { \ + _node_->prev = _node_->prev->prev; \ + _node_->prev->next = _node_; \ + } \ + else \ + _owner_->head = _node_; \ + \ + _owner_->alloc->free(tmp); \ + \ + _owner_->count--; \ + \ + return true; \ + } \ + \ + struct SNAME##_node *PFX##_next_node(struct SNAME##_node *_node_) \ + { \ + return _node_->next; \ + } \ + \ + struct SNAME##_node *PFX##_prev_node(struct SNAME##_node *_node_) \ + { \ + return _node_->prev; \ + } \ + \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ + { \ + struct SNAME##_iter *iter = \ + target->alloc->malloc(sizeof(struct SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + void PFX##_iter_free(struct SNAME##_iter *iter) \ + { \ + iter->target->alloc->free(iter); \ + } \ + \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ + { \ + iter->target = target; \ + iter->cursor = target->head; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + } \ + \ + bool PFX##_iter_start(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + bool PFX##_iter_end(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + void PFX##_iter_to_start(struct 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(struct 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(struct 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(struct 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(struct 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(struct 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(struct 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(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return (V){ 0 }; \ + \ + return iter->cursor->data; \ + } \ + \ + V *PFX##_iter_rvalue(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return NULL; \ + \ + return &(iter->cursor->data); \ + } \ + \ + size_t PFX##_iter_index(struct SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + struct SNAME##_node *PFX##_iter_node(struct SNAME##_iter *iter) \ + { \ + return iter->cursor; \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_list_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _list_); \ + PFX##_iter_to_start(&iter); \ + \ + return iter; \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_list_) \ + { \ + struct 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 9a31d93..d804e27 100644 --- a/src/cmc/list.h +++ b/src/cmc/list.h @@ -45,13 +45,13 @@ #include #include -#include #include +#include #include -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Core functionalities of the C Macro Collections Library - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ #ifndef CMC_CORE_H #define CMC_CORE_H @@ -70,7 +70,8 @@ static const size_t cmc_string_len = 400; /** * struct cmc_alloc_node * - * Custom allocation node. Allows collections to use custom allocation functions. + * Custom allocation node. Allows collections to use custom allocation + * functions. */ struct cmc_alloc_node { @@ -80,13 +81,14 @@ struct cmc_alloc_node void (*free)(void *); }; -static struct cmc_alloc_node cmc_alloc_node_default = {malloc, calloc, realloc, free}; +static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, + free }; #endif /* CMC_CORE_H */ -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * List specific - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ /* to_string format */ static const char *cmc_string_fmt_list = "struct %s<%s> " "at %p { " @@ -121,794 +123,813 @@ struct cmc_callbacks_list #define CMC_WRAPGEN_LIST_SOURCE(PFX, SNAME, K, V) \ CMC_GENERATE_LIST_SOURCE(PFX, SNAME, V) -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Header - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_LIST_HEADER(PFX, SNAME, V) \ - \ - /* List Structure */ \ - struct SNAME \ - { \ - /* 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 (*it_start)(struct SNAME *); \ - \ - /* Function that returns an iterator to the end of the list */ \ - struct SNAME##_iter (*it_end)(struct SNAME *); \ - \ - /* Custom allocation functions */ \ - struct cmc_alloc_node *alloc; \ - \ - /* Custom callback functions */ \ - struct cmc_callbacks_list *callbacks; \ - }; \ - \ - /* List Iterator */ \ - struct SNAME##_iter \ - { \ - /* Target list */ \ - struct SNAME *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; \ - }; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - struct SNAME *PFX##_new(size_t capacity); \ - struct SNAME *PFX##_new_custom(size_t capacity, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_list *callbacks); \ - struct SNAME *PFX##_new_from(V *elements, size_t size); \ - void PFX##_clear(struct SNAME *_list_, void (*deallocator)(V)); \ - void PFX##_free(struct SNAME *_list_, void (*deallocator)(V)); \ - /* Customization of Allocation and Callbacks */ \ - void PFX##_customize(struct SNAME *_list_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_list *callbacks); \ - /* Collection Input and Output */ \ - bool PFX##_push_front(struct SNAME *_list_, V element); \ - bool PFX##_push_at(struct SNAME *_list_, V element, size_t index); \ - bool PFX##_push_back(struct SNAME *_list_, V element); \ - bool PFX##_pop_front(struct SNAME *_list_); \ - bool PFX##_pop_at(struct SNAME *_list_, size_t index); \ - bool PFX##_pop_back(struct SNAME *_list_); \ - /* Collection Sequence Input and Output */ \ - bool PFX##_seq_push_front(struct SNAME *_list_, V *elements, size_t size); \ - bool PFX##_seq_push_at(struct SNAME *_list_, V *elements, size_t size, size_t index); \ - bool PFX##_seq_push_back(struct SNAME *_list_, V *elements, size_t size); \ - bool PFX##_seq_pop_at(struct SNAME *_list_, size_t from, size_t to); \ - struct SNAME *PFX##_seq_sublist(struct SNAME *_list_, size_t from, size_t to); \ - /* Element Access */ \ - V PFX##_front(struct SNAME *_list_); \ - V PFX##_get(struct SNAME *_list_, size_t index); \ - V *PFX##_get_ref(struct SNAME *_list_, size_t index); \ - V PFX##_back(struct SNAME *_list_); \ - size_t PFX##_indexof(struct SNAME *_list_, V element, int (*comparator)(V, V), \ - bool from_start); \ - /* Collection State */ \ - bool PFX##_contains(struct SNAME *_list_, V element, int (*comparator)(V, V)); \ - bool PFX##_empty(struct SNAME *_list_); \ - bool PFX##_full(struct SNAME *_list_); \ - size_t PFX##_count(struct SNAME *_list_); \ - bool PFX##_fits(struct SNAME *_list_, size_t size); \ - size_t PFX##_capacity(struct SNAME *_list_); \ - /* Collection Utility */ \ - bool PFX##_resize(struct SNAME *_list_, size_t capacity); \ - struct SNAME *PFX##_copy_of(struct SNAME *_list_, V (*copy_func)(V)); \ - bool PFX##_equals(struct SNAME *_list1_, struct SNAME *_list2_, int (*comparator)(V, V)); \ - struct cmc_string PFX##_to_string(struct SNAME *_list_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ - void PFX##_iter_free(struct SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(struct SNAME##_iter *iter); \ - bool PFX##_iter_end(struct SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(struct SNAME##_iter *iter); \ - void PFX##_iter_to_end(struct SNAME##_iter *iter); \ - bool PFX##_iter_next(struct SNAME##_iter *iter); \ - bool PFX##_iter_prev(struct SNAME##_iter *iter); \ - bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - V PFX##_iter_value(struct SNAME##_iter *iter); \ - V *PFX##_iter_rvalue(struct SNAME##_iter *iter); \ + * ------------------------------------------------------------------------- */ +#define CMC_GENERATE_LIST_HEADER(PFX, SNAME, V) \ + \ + /* List Structure */ \ + struct SNAME \ + { \ + /* 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 (*it_start)(struct SNAME *); \ + \ + /* Function that returns an iterator to the end of the list */ \ + struct SNAME##_iter (*it_end)(struct SNAME *); \ + \ + /* Custom allocation functions */ \ + struct cmc_alloc_node *alloc; \ + \ + /* Custom callback functions */ \ + struct cmc_callbacks_list *callbacks; \ + }; \ + \ + /* List Iterator */ \ + struct SNAME##_iter \ + { \ + /* Target list */ \ + struct SNAME *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; \ + }; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + struct SNAME *PFX##_new(size_t capacity); \ + struct SNAME *PFX##_new_custom(size_t capacity, \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_list *callbacks); \ + struct SNAME *PFX##_new_from(V *elements, size_t size); \ + void PFX##_clear(struct SNAME *_list_, void (*deallocator)(V)); \ + void PFX##_free(struct SNAME *_list_, void (*deallocator)(V)); \ + /* Customization of Allocation and Callbacks */ \ + void PFX##_customize(struct SNAME *_list_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_list *callbacks); \ + /* Collection Input and Output */ \ + bool PFX##_push_front(struct SNAME *_list_, V element); \ + bool PFX##_push_at(struct SNAME *_list_, V element, size_t index); \ + bool PFX##_push_back(struct SNAME *_list_, V element); \ + bool PFX##_pop_front(struct SNAME *_list_); \ + bool PFX##_pop_at(struct SNAME *_list_, size_t index); \ + bool PFX##_pop_back(struct SNAME *_list_); \ + /* Collection Sequence Input and Output */ \ + bool PFX##_seq_push_front(struct SNAME *_list_, V *elements, size_t size); \ + bool PFX##_seq_push_at(struct SNAME *_list_, V *elements, size_t size, \ + size_t index); \ + bool PFX##_seq_push_back(struct SNAME *_list_, V *elements, size_t size); \ + bool PFX##_seq_pop_at(struct SNAME *_list_, size_t from, size_t to); \ + struct SNAME *PFX##_seq_sublist(struct SNAME *_list_, size_t from, \ + size_t to); \ + /* Element Access */ \ + V PFX##_front(struct SNAME *_list_); \ + V PFX##_get(struct SNAME *_list_, size_t index); \ + V *PFX##_get_ref(struct SNAME *_list_, size_t index); \ + V PFX##_back(struct SNAME *_list_); \ + size_t PFX##_indexof(struct SNAME *_list_, V element, \ + int (*comparator)(V, V), bool from_start); \ + /* Collection State */ \ + bool PFX##_contains(struct SNAME *_list_, V element, \ + int (*comparator)(V, V)); \ + bool PFX##_empty(struct SNAME *_list_); \ + bool PFX##_full(struct SNAME *_list_); \ + size_t PFX##_count(struct SNAME *_list_); \ + bool PFX##_fits(struct SNAME *_list_, size_t size); \ + size_t PFX##_capacity(struct SNAME *_list_); \ + /* Collection Utility */ \ + bool PFX##_resize(struct SNAME *_list_, size_t capacity); \ + struct SNAME *PFX##_copy_of(struct SNAME *_list_, V (*copy_func)(V)); \ + bool PFX##_equals(struct SNAME *_list1_, struct SNAME *_list2_, \ + int (*comparator)(V, V)); \ + struct cmc_string PFX##_to_string(struct SNAME *_list_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ + void PFX##_iter_free(struct SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(struct SNAME##_iter *iter); \ + bool PFX##_iter_end(struct SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(struct SNAME##_iter *iter); \ + void PFX##_iter_to_end(struct SNAME##_iter *iter); \ + bool PFX##_iter_next(struct SNAME##_iter *iter); \ + bool PFX##_iter_prev(struct SNAME##_iter *iter); \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + V PFX##_iter_value(struct SNAME##_iter *iter); \ + V *PFX##_iter_rvalue(struct SNAME##_iter *iter); \ size_t PFX##_iter_index(struct SNAME##_iter *iter); -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Source - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_LIST_SOURCE(PFX, SNAME, V) \ - \ - /* Implementation Detail Functions */ \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_list_); \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_list_); \ - \ - struct SNAME *PFX##_new(size_t capacity) \ - { \ - struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ - \ - if (capacity < 1) \ - return NULL; \ - \ - struct SNAME *_list_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_list_) \ - return NULL; \ - \ - _list_->buffer = alloc->calloc(capacity, sizeof(V)); \ - \ - if (!_list_->buffer) \ - { \ - alloc->free(_list_); \ - return NULL; \ - } \ - \ - _list_->capacity = capacity; \ - _list_->count = 0; \ - \ - _list_->it_start = PFX##_impl_it_start; \ - _list_->it_end = PFX##_impl_it_end; \ - \ - _list_->alloc = alloc; \ - _list_->callbacks = NULL; \ - \ - return _list_; \ - } \ - \ - struct SNAME *PFX##_new_custom(size_t capacity, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_list *callbacks) \ - { \ - if (capacity < 1) \ - return NULL; \ - \ - if (!alloc) \ - alloc = &cmc_alloc_node_default; \ - \ - struct SNAME *_list_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_list_) \ - return NULL; \ - \ - _list_->buffer = alloc->calloc(capacity, sizeof(V)); \ - \ - if (!_list_->buffer) \ - { \ - alloc->free(_list_); \ - return NULL; \ - } \ - \ - _list_->capacity = capacity; \ - _list_->count = 0; \ - \ - _list_->it_start = PFX##_impl_it_start; \ - _list_->it_end = PFX##_impl_it_end; \ - \ - _list_->alloc = alloc; \ - _list_->callbacks = callbacks; \ - \ - return _list_; \ - } \ - \ - struct SNAME *PFX##_new_from(V *elements, size_t size) \ - { \ - if (size == 0) \ - return NULL; \ - \ - struct SNAME *_list_ = PFX##_new(size + size / 2); \ - \ - if (!_list_) \ - return NULL; \ - \ - memcpy(_list_->buffer, elements, size * sizeof(V)); \ - \ - _list_->count = size; \ - \ - return _list_; \ - } \ - \ - void PFX##_clear(struct SNAME *_list_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _list_->count; i++) \ - deallocator(_list_->buffer[i]); \ - } \ - \ - memset(_list_->buffer, 0, sizeof(V) * _list_->capacity); \ - \ - _list_->count = 0; \ - } \ - \ - void PFX##_free(struct SNAME *_list_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _list_->count; i++) \ - deallocator(_list_->buffer[i]); \ - } \ - \ - _list_->alloc->free(_list_->buffer); \ - _list_->alloc->free(_list_); \ - } \ - \ - void PFX##_customize(struct SNAME *_list_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_list *callbacks) \ - { \ - if (alloc) \ - _list_->alloc = alloc; \ - \ - if (callbacks) \ - _list_->callbacks = callbacks; \ - } \ - \ - bool PFX##_push_front(struct SNAME *_list_, V element) \ - { \ - if (PFX##_full(_list_)) \ - { \ - if (!PFX##_resize(_list_, PFX##_count(_list_) * 2)) \ - return false; \ - } \ - \ - if (!PFX##_empty(_list_)) \ - { \ - memmove(_list_->buffer + 1, _list_->buffer, _list_->count * sizeof(V)); \ - } \ - \ - _list_->buffer[0] = element; \ - \ - _list_->count++; \ - \ - return true; \ - } \ - \ - bool PFX##_push_at(struct SNAME *_list_, V element, size_t index) \ - { \ - if (index > _list_->count) \ - return false; \ - \ - if (PFX##_full(_list_)) \ - { \ - if (!PFX##_resize(_list_, PFX##_count(_list_) * 2)) \ - return false; \ - } \ - \ - memmove(_list_->buffer + index + 1, _list_->buffer + index, \ - (_list_->count - index) * sizeof(V)); \ - \ - _list_->buffer[index] = element; \ - _list_->count++; \ - \ - return true; \ - } \ - \ - bool PFX##_push_back(struct SNAME *_list_, V element) \ - { \ - if (PFX##_full(_list_)) \ - { \ - if (!PFX##_resize(_list_, PFX##_count(_list_) * 2)) \ - return false; \ - } \ - \ - _list_->buffer[_list_->count++] = element; \ - \ - return true; \ - } \ - \ - bool PFX##_pop_front(struct SNAME *_list_) \ - { \ - if (PFX##_empty(_list_)) \ - return false; \ - \ - memmove(_list_->buffer, _list_->buffer + 1, _list_->count * sizeof(V)); \ - \ - _list_->buffer[--_list_->count] = (V){0}; \ - \ - return true; \ - } \ - \ - bool PFX##_pop_at(struct SNAME *_list_, size_t index) \ - { \ - if (index >= _list_->count) \ - return false; \ - \ - memmove(_list_->buffer + index, _list_->buffer + index + 1, \ - (_list_->count - index) * sizeof(V)); \ - \ - _list_->buffer[--_list_->count] = (V){0}; \ - \ - return true; \ - } \ - \ - bool PFX##_pop_back(struct SNAME *_list_) \ - { \ - if (PFX##_empty(_list_)) \ - return false; \ - \ - _list_->buffer[--_list_->count] = (V){0}; \ - \ - return true; \ - } \ - \ - bool PFX##_seq_push_front(struct SNAME *_list_, V *elements, size_t size) \ - { \ - if (size == 0) \ - return false; \ - \ - if (!PFX##_fits(_list_, size)) \ - { \ - if (!PFX##_resize(_list_, PFX##_count(_list_) + size)) \ - return false; \ - } \ - \ - memmove(_list_->buffer + size, _list_->buffer, _list_->count * sizeof(V)); \ - \ - memcpy(_list_->buffer, elements, size * sizeof(V)); \ - \ - _list_->count += size; \ - \ - return true; \ - } \ - \ - bool PFX##_seq_push_at(struct SNAME *_list_, V *elements, size_t size, size_t index) \ - { \ - if (size == 0 || index > _list_->count) \ - return false; \ - \ - if (index == 0) \ - return PFX##_seq_push_front(_list_, elements, size); \ - else if (index == _list_->count) \ - return PFX##_seq_push_back(_list_, elements, size); \ - else \ - { \ - if (!PFX##_fits(_list_, size)) \ - { \ - if (!PFX##_resize(_list_, PFX##_count(_list_) + size)) \ - return false; \ - } \ - \ - memmove(_list_->buffer + index + size, _list_->buffer + index, \ - (_list_->count - index) * sizeof(V)); \ - \ - memcpy(_list_->buffer + index, elements, size * sizeof(V)); \ - \ - _list_->count += size; \ - } \ - \ - return true; \ - } \ - \ - bool PFX##_seq_push_back(struct SNAME *_list_, V *elements, size_t size) \ - { \ - if (size == 0) \ - return false; \ - \ - if (!PFX##_fits(_list_, size)) \ - { \ - if (!PFX##_resize(_list_, _list_->count + size)) \ - return false; \ - } \ - \ - memcpy(_list_->buffer + _list_->count, elements, size * sizeof(V)); \ - \ - _list_->count += size; \ - \ - return true; \ - } \ - \ - bool PFX##_seq_pop_at(struct SNAME *_list_, size_t from, size_t to) \ - { \ - if (from > to || to >= _list_->count) \ - return false; \ - \ - size_t length = (to - from + 1); \ - \ - memmove(_list_->buffer + from, _list_->buffer + to + 1, \ - (_list_->count - to - 1) * sizeof(V)); \ - \ - memset(_list_->buffer + _list_->count - length, 0, length * sizeof(V)); \ - \ - _list_->count -= to - from + 1; \ - \ - return true; \ - } \ - \ - struct SNAME *PFX##_seq_sublist(struct SNAME *_list_, size_t from, size_t to) \ - { \ - if (from > to || to >= _list_->count) \ - return false; \ - \ - size_t length = to - from + 1; \ - \ - struct SNAME *result = PFX##_new(length); \ - \ - if (!result) \ - return NULL; \ - \ - memcpy(result->buffer, _list_->buffer, _list_->count * sizeof(V)); \ - \ - memmove(_list_->buffer + from, _list_->buffer + to + 1, \ - (_list_->count - to - 1) * sizeof(V)); \ - \ - memset(_list_->buffer + _list_->count - length, 0, length * sizeof(V)); \ - \ - _list_->count -= length; \ - result->count = length; \ - \ - return result; \ - } \ - \ - V PFX##_front(struct SNAME *_list_) \ - { \ - if (PFX##_empty(_list_)) \ - return (V){0}; \ - \ - return _list_->buffer[0]; \ - } \ - \ - V PFX##_get(struct SNAME *_list_, size_t index) \ - { \ - if (index >= _list_->count || PFX##_empty(_list_)) \ - return (V){0}; \ - \ - return _list_->buffer[index]; \ - } \ - \ - V *PFX##_get_ref(struct SNAME *_list_, size_t index) \ - { \ - if (index >= _list_->count) \ - return NULL; \ - \ - if (PFX##_empty(_list_)) \ - return NULL; \ - \ - return &(_list_->buffer[index]); \ - } \ - \ - V PFX##_back(struct SNAME *_list_) \ - { \ - if (PFX##_empty(_list_)) \ - return (V){0}; \ - \ - return _list_->buffer[_list_->count - 1]; \ - } \ - \ - size_t PFX##_indexof(struct SNAME *_list_, V element, int (*comparator)(V, V), \ - bool from_start) \ - { \ - if (from_start) \ - { \ - for (size_t i = 0; i < _list_->count; i++) \ - { \ - if (comparator(_list_->buffer[i], element) == 0) \ - return i; \ - } \ - } \ - else \ - { \ - for (size_t i = _list_->count; i > 0; i--) \ - { \ - if (comparator(_list_->buffer[i - 1], element) == 0) \ - return i - 1; \ - } \ - } \ - \ - return _list_->count; \ - } \ - \ - bool PFX##_contains(struct SNAME *_list_, V element, int (*comparator)(V, V)) \ - { \ - for (size_t i = 0; i < _list_->count; i++) \ - { \ - if (comparator(_list_->buffer[i], element) == 0) \ - return true; \ - } \ - \ - return false; \ - } \ - \ - bool PFX##_empty(struct SNAME *_list_) \ - { \ - return _list_->count == 0; \ - } \ - \ - bool PFX##_full(struct SNAME *_list_) \ - { \ - return _list_->count >= _list_->capacity; \ - } \ - \ - size_t PFX##_count(struct SNAME *_list_) \ - { \ - return _list_->count; \ - } \ - \ - bool PFX##_fits(struct SNAME *_list_, size_t size) \ - { \ - return _list_->count + size <= _list_->capacity; \ - } \ - \ - size_t PFX##_capacity(struct SNAME *_list_) \ - { \ - return _list_->capacity; \ - } \ - \ - bool PFX##_resize(struct SNAME *_list_, size_t capacity) \ - { \ - if (PFX##_capacity(_list_) == capacity) \ - return true; \ - \ - if (capacity < PFX##_count(_list_)) \ - return false; \ - \ - V *new_buffer = _list_->alloc->realloc(_list_->buffer, sizeof(V) * capacity); \ - \ - if (!new_buffer) \ - return false; \ - \ - _list_->buffer = new_buffer; \ - _list_->capacity = capacity; \ - \ - return true; \ - } \ - \ - struct SNAME *PFX##_copy_of(struct SNAME *_list_, V (*copy_func)(V)) \ - { \ - struct SNAME *result = PFX##_new_custom(_list_->capacity, _list_->alloc, \ - _list_->callbacks); \ - \ - if (!result) \ - return NULL; \ - \ - if (copy_func) \ - { \ - for (size_t i = 0; i < _list_->count; i++) \ - result->buffer[i] = copy_func(_list_->buffer[i]); \ - } \ - else \ - memcpy(result->buffer, _list_->buffer, sizeof(V) * _list_->count); \ - \ - result->count = _list_->count; \ - \ - return result; \ - } \ - \ - bool PFX##_equals(struct SNAME *_list1_, struct SNAME *_list2_, int (*comparator)(V, V)) \ - { \ - if (PFX##_count(_list1_) != PFX##_count(_list2_)) \ - return false; \ - \ - for (size_t i = 0; i < PFX##_count(_list1_); i++) \ - { \ - if (comparator(_list1_->buffer[i], _list2_->buffer[i]) != 0) \ - return false; \ - } \ - \ - return false; \ - } \ - \ - struct cmc_string PFX##_to_string(struct SNAME *_list_) \ - { \ - struct cmc_string str; \ - struct SNAME *l_ = _list_; \ - \ - int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_list, \ - #SNAME, #V, l_, l_->buffer, l_->capacity, l_->count, \ - l_->alloc, l_->callbacks); \ - \ - if (n < 0 || n == (int)cmc_string_len) \ - return (struct cmc_string){0}; \ - \ - str.s[n] = '\0'; \ - \ - return str; \ - } \ - \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ - { \ - struct SNAME##_iter *iter = target->alloc->malloc(sizeof(struct SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(struct SNAME##_iter *iter) \ - { \ - iter->target->alloc->free(iter); \ - } \ - \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ - { \ - iter->target = target; \ - iter->cursor = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - } \ - \ - bool PFX##_iter_start(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(struct SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - } \ - } \ - \ - void PFX##_iter_to_end(struct SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->start = PFX##_empty(iter->target); \ - iter->cursor = PFX##_empty(iter->target) ? 0 : iter->target->count - 1; \ - iter->end = true; \ - } \ - } \ - \ - bool PFX##_iter_next(struct SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->cursor + 1 == PFX##_count(iter->target)) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - iter->cursor++; \ - \ - return true; \ - } \ - \ - bool PFX##_iter_prev(struct SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->cursor == 0) \ - { \ - 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(struct SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->cursor + 1 == iter->target->count) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->cursor + steps >= PFX##_count(iter->target)) \ - return false; \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - iter->cursor += steps; \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->cursor == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->cursor < steps) \ - 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(struct 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(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){0}; \ - \ - return iter->target->buffer[iter->cursor]; \ - } \ - \ - V *PFX##_iter_rvalue(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->target->buffer[iter->cursor]); \ - } \ - \ - size_t PFX##_iter_index(struct SNAME##_iter *iter) \ - { \ - return iter->cursor; \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_list_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _list_); \ - PFX##_iter_to_start(&iter); \ - \ - return iter; \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_list_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _list_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ + * ------------------------------------------------------------------------- */ +#define CMC_GENERATE_LIST_SOURCE(PFX, SNAME, V) \ + \ + /* Implementation Detail Functions */ \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_list_); \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_list_); \ + \ + struct SNAME *PFX##_new(size_t capacity) \ + { \ + struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ + \ + if (capacity < 1) \ + return NULL; \ + \ + struct SNAME *_list_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_list_) \ + return NULL; \ + \ + _list_->buffer = alloc->calloc(capacity, sizeof(V)); \ + \ + if (!_list_->buffer) \ + { \ + alloc->free(_list_); \ + return NULL; \ + } \ + \ + _list_->capacity = capacity; \ + _list_->count = 0; \ + \ + _list_->it_start = PFX##_impl_it_start; \ + _list_->it_end = PFX##_impl_it_end; \ + \ + _list_->alloc = alloc; \ + _list_->callbacks = NULL; \ + \ + return _list_; \ + } \ + \ + struct SNAME *PFX##_new_custom(size_t capacity, \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_list *callbacks) \ + { \ + if (capacity < 1) \ + return NULL; \ + \ + if (!alloc) \ + alloc = &cmc_alloc_node_default; \ + \ + struct SNAME *_list_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_list_) \ + return NULL; \ + \ + _list_->buffer = alloc->calloc(capacity, sizeof(V)); \ + \ + if (!_list_->buffer) \ + { \ + alloc->free(_list_); \ + return NULL; \ + } \ + \ + _list_->capacity = capacity; \ + _list_->count = 0; \ + \ + _list_->it_start = PFX##_impl_it_start; \ + _list_->it_end = PFX##_impl_it_end; \ + \ + _list_->alloc = alloc; \ + _list_->callbacks = callbacks; \ + \ + return _list_; \ + } \ + \ + struct SNAME *PFX##_new_from(V *elements, size_t size) \ + { \ + if (size == 0) \ + return NULL; \ + \ + struct SNAME *_list_ = PFX##_new(size + size / 2); \ + \ + if (!_list_) \ + return NULL; \ + \ + memcpy(_list_->buffer, elements, size * sizeof(V)); \ + \ + _list_->count = size; \ + \ + return _list_; \ + } \ + \ + void PFX##_clear(struct SNAME *_list_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _list_->count; i++) \ + deallocator(_list_->buffer[i]); \ + } \ + \ + memset(_list_->buffer, 0, sizeof(V) * _list_->capacity); \ + \ + _list_->count = 0; \ + } \ + \ + void PFX##_free(struct SNAME *_list_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _list_->count; i++) \ + deallocator(_list_->buffer[i]); \ + } \ + \ + _list_->alloc->free(_list_->buffer); \ + _list_->alloc->free(_list_); \ + } \ + \ + void PFX##_customize(struct SNAME *_list_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_list *callbacks) \ + { \ + if (alloc) \ + _list_->alloc = alloc; \ + \ + if (callbacks) \ + _list_->callbacks = callbacks; \ + } \ + \ + bool PFX##_push_front(struct SNAME *_list_, V element) \ + { \ + if (PFX##_full(_list_)) \ + { \ + if (!PFX##_resize(_list_, PFX##_count(_list_) * 2)) \ + return false; \ + } \ + \ + if (!PFX##_empty(_list_)) \ + { \ + memmove(_list_->buffer + 1, _list_->buffer, \ + _list_->count * sizeof(V)); \ + } \ + \ + _list_->buffer[0] = element; \ + \ + _list_->count++; \ + \ + return true; \ + } \ + \ + bool PFX##_push_at(struct SNAME *_list_, V element, size_t index) \ + { \ + if (index > _list_->count) \ + return false; \ + \ + if (PFX##_full(_list_)) \ + { \ + if (!PFX##_resize(_list_, PFX##_count(_list_) * 2)) \ + return false; \ + } \ + \ + memmove(_list_->buffer + index + 1, _list_->buffer + index, \ + (_list_->count - index) * sizeof(V)); \ + \ + _list_->buffer[index] = element; \ + _list_->count++; \ + \ + return true; \ + } \ + \ + bool PFX##_push_back(struct SNAME *_list_, V element) \ + { \ + if (PFX##_full(_list_)) \ + { \ + if (!PFX##_resize(_list_, PFX##_count(_list_) * 2)) \ + return false; \ + } \ + \ + _list_->buffer[_list_->count++] = element; \ + \ + return true; \ + } \ + \ + bool PFX##_pop_front(struct SNAME *_list_) \ + { \ + if (PFX##_empty(_list_)) \ + return false; \ + \ + memmove(_list_->buffer, _list_->buffer + 1, \ + _list_->count * sizeof(V)); \ + \ + _list_->buffer[--_list_->count] = (V){ 0 }; \ + \ + return true; \ + } \ + \ + bool PFX##_pop_at(struct SNAME *_list_, size_t index) \ + { \ + if (index >= _list_->count) \ + return false; \ + \ + memmove(_list_->buffer + index, _list_->buffer + index + 1, \ + (_list_->count - index) * sizeof(V)); \ + \ + _list_->buffer[--_list_->count] = (V){ 0 }; \ + \ + return true; \ + } \ + \ + bool PFX##_pop_back(struct SNAME *_list_) \ + { \ + if (PFX##_empty(_list_)) \ + return false; \ + \ + _list_->buffer[--_list_->count] = (V){ 0 }; \ + \ + return true; \ + } \ + \ + bool PFX##_seq_push_front(struct SNAME *_list_, V *elements, size_t size) \ + { \ + if (size == 0) \ + return false; \ + \ + if (!PFX##_fits(_list_, size)) \ + { \ + if (!PFX##_resize(_list_, PFX##_count(_list_) + size)) \ + return false; \ + } \ + \ + memmove(_list_->buffer + size, _list_->buffer, \ + _list_->count * sizeof(V)); \ + \ + memcpy(_list_->buffer, elements, size * sizeof(V)); \ + \ + _list_->count += size; \ + \ + return true; \ + } \ + \ + bool PFX##_seq_push_at(struct SNAME *_list_, V *elements, size_t size, \ + size_t index) \ + { \ + if (size == 0 || index > _list_->count) \ + return false; \ + \ + if (index == 0) \ + return PFX##_seq_push_front(_list_, elements, size); \ + else if (index == _list_->count) \ + return PFX##_seq_push_back(_list_, elements, size); \ + else \ + { \ + if (!PFX##_fits(_list_, size)) \ + { \ + if (!PFX##_resize(_list_, PFX##_count(_list_) + size)) \ + return false; \ + } \ + \ + memmove(_list_->buffer + index + size, _list_->buffer + index, \ + (_list_->count - index) * sizeof(V)); \ + \ + memcpy(_list_->buffer + index, elements, size * sizeof(V)); \ + \ + _list_->count += size; \ + } \ + \ + return true; \ + } \ + \ + bool PFX##_seq_push_back(struct SNAME *_list_, V *elements, size_t size) \ + { \ + if (size == 0) \ + return false; \ + \ + if (!PFX##_fits(_list_, size)) \ + { \ + if (!PFX##_resize(_list_, _list_->count + size)) \ + return false; \ + } \ + \ + memcpy(_list_->buffer + _list_->count, elements, size * sizeof(V)); \ + \ + _list_->count += size; \ + \ + return true; \ + } \ + \ + bool PFX##_seq_pop_at(struct SNAME *_list_, size_t from, size_t to) \ + { \ + if (from > to || to >= _list_->count) \ + return false; \ + \ + size_t length = (to - from + 1); \ + \ + memmove(_list_->buffer + from, _list_->buffer + to + 1, \ + (_list_->count - to - 1) * sizeof(V)); \ + \ + memset(_list_->buffer + _list_->count - length, 0, \ + length * sizeof(V)); \ + \ + _list_->count -= to - from + 1; \ + \ + return true; \ + } \ + \ + struct SNAME *PFX##_seq_sublist(struct SNAME *_list_, size_t from, \ + size_t to) \ + { \ + if (from > to || to >= _list_->count) \ + return false; \ + \ + size_t length = to - from + 1; \ + \ + struct SNAME *result = PFX##_new(length); \ + \ + if (!result) \ + return NULL; \ + \ + memcpy(result->buffer, _list_->buffer, _list_->count * sizeof(V)); \ + \ + memmove(_list_->buffer + from, _list_->buffer + to + 1, \ + (_list_->count - to - 1) * sizeof(V)); \ + \ + memset(_list_->buffer + _list_->count - length, 0, \ + length * sizeof(V)); \ + \ + _list_->count -= length; \ + result->count = length; \ + \ + return result; \ + } \ + \ + V PFX##_front(struct SNAME *_list_) \ + { \ + if (PFX##_empty(_list_)) \ + return (V){ 0 }; \ + \ + return _list_->buffer[0]; \ + } \ + \ + V PFX##_get(struct SNAME *_list_, size_t index) \ + { \ + if (index >= _list_->count || PFX##_empty(_list_)) \ + return (V){ 0 }; \ + \ + return _list_->buffer[index]; \ + } \ + \ + V *PFX##_get_ref(struct SNAME *_list_, size_t index) \ + { \ + if (index >= _list_->count) \ + return NULL; \ + \ + if (PFX##_empty(_list_)) \ + return NULL; \ + \ + return &(_list_->buffer[index]); \ + } \ + \ + V PFX##_back(struct SNAME *_list_) \ + { \ + if (PFX##_empty(_list_)) \ + return (V){ 0 }; \ + \ + return _list_->buffer[_list_->count - 1]; \ + } \ + \ + size_t PFX##_indexof(struct SNAME *_list_, V element, \ + int (*comparator)(V, V), bool from_start) \ + { \ + if (from_start) \ + { \ + for (size_t i = 0; i < _list_->count; i++) \ + { \ + if (comparator(_list_->buffer[i], element) == 0) \ + return i; \ + } \ + } \ + else \ + { \ + for (size_t i = _list_->count; i > 0; i--) \ + { \ + if (comparator(_list_->buffer[i - 1], element) == 0) \ + return i - 1; \ + } \ + } \ + \ + return _list_->count; \ + } \ + \ + bool PFX##_contains(struct SNAME *_list_, V element, \ + int (*comparator)(V, V)) \ + { \ + for (size_t i = 0; i < _list_->count; i++) \ + { \ + if (comparator(_list_->buffer[i], element) == 0) \ + return true; \ + } \ + \ + return false; \ + } \ + \ + bool PFX##_empty(struct SNAME *_list_) \ + { \ + return _list_->count == 0; \ + } \ + \ + bool PFX##_full(struct SNAME *_list_) \ + { \ + return _list_->count >= _list_->capacity; \ + } \ + \ + size_t PFX##_count(struct SNAME *_list_) \ + { \ + return _list_->count; \ + } \ + \ + bool PFX##_fits(struct SNAME *_list_, size_t size) \ + { \ + return _list_->count + size <= _list_->capacity; \ + } \ + \ + size_t PFX##_capacity(struct SNAME *_list_) \ + { \ + return _list_->capacity; \ + } \ + \ + bool PFX##_resize(struct SNAME *_list_, size_t capacity) \ + { \ + if (PFX##_capacity(_list_) == capacity) \ + return true; \ + \ + if (capacity < PFX##_count(_list_)) \ + return false; \ + \ + V *new_buffer = \ + _list_->alloc->realloc(_list_->buffer, sizeof(V) * capacity); \ + \ + if (!new_buffer) \ + return false; \ + \ + _list_->buffer = new_buffer; \ + _list_->capacity = capacity; \ + \ + return true; \ + } \ + \ + struct SNAME *PFX##_copy_of(struct SNAME *_list_, V (*copy_func)(V)) \ + { \ + struct SNAME *result = PFX##_new_custom( \ + _list_->capacity, _list_->alloc, _list_->callbacks); \ + \ + if (!result) \ + return NULL; \ + \ + if (copy_func) \ + { \ + for (size_t i = 0; i < _list_->count; i++) \ + result->buffer[i] = copy_func(_list_->buffer[i]); \ + } \ + else \ + memcpy(result->buffer, _list_->buffer, sizeof(V) * _list_->count); \ + \ + result->count = _list_->count; \ + \ + return result; \ + } \ + \ + bool PFX##_equals(struct SNAME *_list1_, struct SNAME *_list2_, \ + int (*comparator)(V, V)) \ + { \ + if (PFX##_count(_list1_) != PFX##_count(_list2_)) \ + return false; \ + \ + for (size_t i = 0; i < PFX##_count(_list1_); i++) \ + { \ + if (comparator(_list1_->buffer[i], _list2_->buffer[i]) != 0) \ + return false; \ + } \ + \ + return false; \ + } \ + \ + struct cmc_string PFX##_to_string(struct SNAME *_list_) \ + { \ + struct cmc_string str; \ + struct SNAME *l_ = _list_; \ + \ + int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_list, #SNAME, \ + #V, l_, l_->buffer, l_->capacity, l_->count, \ + l_->alloc, l_->callbacks); \ + \ + if (n < 0 || n == (int)cmc_string_len) \ + return (struct cmc_string){ 0 }; \ + \ + str.s[n] = '\0'; \ + \ + return str; \ + } \ + \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ + { \ + struct SNAME##_iter *iter = \ + target->alloc->malloc(sizeof(struct SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + void PFX##_iter_free(struct SNAME##_iter *iter) \ + { \ + iter->target->alloc->free(iter); \ + } \ + \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ + { \ + iter->target = target; \ + iter->cursor = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + } \ + \ + bool PFX##_iter_start(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + bool PFX##_iter_end(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + void PFX##_iter_to_start(struct SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ + } \ + \ + void PFX##_iter_to_end(struct SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->start = PFX##_empty(iter->target); \ + iter->cursor = \ + PFX##_empty(iter->target) ? 0 : iter->target->count - 1; \ + iter->end = true; \ + } \ + } \ + \ + bool PFX##_iter_next(struct SNAME##_iter *iter) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->cursor + 1 == PFX##_count(iter->target)) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + iter->cursor++; \ + \ + return true; \ + } \ + \ + bool PFX##_iter_prev(struct SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor == 0) \ + { \ + 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(struct SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->cursor + 1 == iter->target->count) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->cursor + steps >= PFX##_count(iter->target)) \ + return false; \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + iter->cursor += steps; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->cursor < steps) \ + 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(struct 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(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return (V){ 0 }; \ + \ + return iter->target->buffer[iter->cursor]; \ + } \ + \ + V *PFX##_iter_rvalue(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return NULL; \ + \ + return &(iter->target->buffer[iter->cursor]); \ + } \ + \ + size_t PFX##_iter_index(struct SNAME##_iter *iter) \ + { \ + return iter->cursor; \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_list_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _list_); \ + PFX##_iter_to_start(&iter); \ + \ + return iter; \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_list_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _list_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_LIST_H */ diff --git a/src/cmc/multimap.h b/src/cmc/multimap.h index efcd532..3e46726 100644 --- a/src/cmc/multimap.h +++ b/src/cmc/multimap.h @@ -45,13 +45,13 @@ #include #include -#include #include +#include #include -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Core functionalities of the C Macro Collections Library - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ #ifndef CMC_CORE_H #define CMC_CORE_H @@ -70,7 +70,8 @@ static const size_t cmc_string_len = 400; /** * struct cmc_alloc_node * - * Custom allocation node. Allows collections to use custom allocation functions. + * Custom allocation node. Allows collections to use custom allocation + * functions. */ struct cmc_alloc_node { @@ -80,32 +81,63 @@ struct cmc_alloc_node void (*free)(void *); }; -static struct cmc_alloc_node cmc_alloc_node_default = {malloc, calloc, realloc, free}; +static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, + free }; #endif /* CMC_CORE_H */ -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Hashtable Implementation - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ #ifndef CMC_IMPL_HASHTABLE_PRIMES #define CMC_IMPL_HASHTABLE_PRIMES -static const size_t cmc_hashtable_primes[] = - {53, 97, 191, 383, 769, 1531, 3067, 6143, 12289, 24571, 49157, 98299, 196613, 393209, 786431, - 1572869, 3145721, 6291449, 12582917, 25165813, 50331653, 100663291, 201326611, 402653189, - 805306357, 1610612741, 3221225473, 6442450939, 12884901893, 25769803799, 51539607551, - 103079215111, 206158430209, 412316860441, 824633720831, 1649267441651, 3298534883309, - 6597069766657, 13194139533299, 26388279066623, 52776558133303, 105553116266489, - 211106232532969, 422212465066001, 844424930131963, 1688849860263953, 3377699720527861, - 6755399441055731, 13510798882111483, 27021597764222939, 54043195528445957, 108086391056891903, - 216172782113783773, 432345564227567621, 864691128455135207, 1729382256910270481, - 3458764513820540933, 6917529027641081903, 13835058055282163729llu}; +// clang-format off +static const size_t cmc_hashtable_primes[] = { + /* < 1e3 */ + 53, 97, 191, 383, 769, + /* < 1e4 */ + 1531, 3067, 6143, + /* < 1e5 */ + 12289, 24571, 49157, 98299, + /* < 1e6 */ + 196613, 393209, 786431, + /* < 1e7 */ + 1572869, 3145721, 6291449, + /* < 1e8 */ + 12582917, 25165813, 50331653, + /* < 1e9 */ + 100663291, 201326611, 402653189, 805306357, + /* < 1e10 */ + 1610612741, 3221225473, 6442450939, + /* < 1e11 */ + 12884901893, 25769803799, 51539607551, + /* < 1e12 */ + 103079215111, 206158430209, 412316860441, 824633720831, + /* < 1e13 */ + 1649267441651, 3298534883309, 6597069766657, + /* < 1e14 */ + 13194139533299, 26388279066623, 52776558133303, + /* < 1e15 */ + 105553116266489, 211106232532969, 422212465066001, 844424930131963, + /* < 1e16 */ + 1688849860263953, 3377699720527861, 6755399441055731, + /* < 1e17 */ + 13510798882111483, 27021597764222939, 54043195528445957, + /* < 1e18 */ + 108086391056891903, 216172782113783773, 432345564227567621, 864691128455135207, + /* < 1e19 */ + 1729382256910270481, 3458764513820540933, 6917529027641081903, + /* < 1e20 */ + 13835058055282163729llu, +}; +// clang-format on #endif /* CMC_IMPL_HASHTABLE_PRIMES */ -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * MultiMap specific - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ /* to_string format */ static const char *cmc_string_fmt_multimap = "struct %s<%s, %s> " "at %p { " @@ -143,1104 +175,1136 @@ struct cmc_callbacks_multimap #define CMC_WRAPGEN_MULTIMAP_SOURCE(PFX, SNAME, K, V) \ CMC_GENERATE_MULTIMAP_SOURCE(PFX, SNAME, K, V) -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Header - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_MULTIMAP_HEADER(PFX, SNAME, K, V) \ - \ - /* Multimap Structure */ \ - struct SNAME \ - { \ - /* Array of linked list to entries */ \ - struct SNAME##_entry *(*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 (*it_start)(struct SNAME *); \ - \ - /* Function that returns an iterator to the end of the multimap */ \ - struct SNAME##_iter (*it_end)(struct SNAME *); \ - \ - /* Custom allocation functions */ \ - struct cmc_alloc_node *alloc; \ - \ - /* Custom callback functions */ \ - struct cmc_callbacks_multimap *callbacks; \ - }; \ - \ - /* Multimap Entry */ \ - struct SNAME##_entry \ - { \ - /* Entry Key */ \ - K key; \ - \ - /* Entry Value */ \ - V value; \ - \ - /* Next entry on the linked list */ \ - struct SNAME##_entry *next; \ - \ - /* Previous entry on the linked list */ \ - struct SNAME##_entry *prev; \ - }; \ - \ - struct SNAME##_iter \ - { \ - /* Target multimap */ \ - struct SNAME *target; \ - \ - /* Current entry */ \ - struct SNAME##_entry *curr_entry; \ - \ - /* Cursor`s position (index) */ \ - size_t cursor; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* The index of the first element */ \ - size_t first; \ - \ - /* The index of the last element */ \ - size_t last; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - }; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - struct SNAME *PFX##_new(size_t capacity, double load, int (*compare)(K, K), \ - size_t (*hash)(K)); \ - struct SNAME *PFX##_new_custom(size_t capacity, double load, int (*compare)(K, K), \ - size_t (*hash)(K), struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_multimap *callbacks); \ - void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)); \ - void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)); \ - /* Customization of Allocation and Callbacks */ \ - void PFX##_customize(struct SNAME *_map_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_multimap *callbacks); \ - /* Collection Input and Output */ \ - bool PFX##_insert(struct SNAME *_map_, K key, V value); \ - bool PFX##_update(struct SNAME *_map_, K key, V new_value, V *old_value); \ - size_t PFX##_update_all(struct SNAME *_map_, K key, V new_value, V **old_values); \ - bool PFX##_remove(struct SNAME *_map_, K key, V *out_value); \ - size_t PFX##_remove_all(struct SNAME *_map_, K key, V **out_values); \ - /* Element Access */ \ - bool PFX##_max(struct SNAME *_map_, K *key, V *value); \ - bool PFX##_min(struct SNAME *_map_, K *key, V *value); \ - V PFX##_get(struct SNAME *_map_, K key); \ - V *PFX##_get_ref(struct SNAME *_map_, K key); \ - /* Collection State */ \ - bool PFX##_contains(struct SNAME *_map_, K key); \ - bool PFX##_empty(struct SNAME *_map_); \ - bool PFX##_full(struct SNAME *_map_); \ - size_t PFX##_count(struct SNAME *_map_); \ - size_t PFX##_key_count(struct SNAME *_map_, K key); \ - size_t PFX##_capacity(struct SNAME *_map_); \ - double PFX##_load(struct SNAME *_map_); \ - /* Collection Utility */ \ - bool PFX##_resize(struct SNAME *_map_, size_t capacity); \ - struct SNAME *PFX##_copy_of(struct SNAME *_map_, K (*key_copy_func)(K), \ - V (*value_copy_func)(V)); \ - bool PFX##_equals(struct SNAME *_map1_, struct SNAME *_map2_, bool ignore_key_count); \ - struct cmc_string PFX##_to_string(struct SNAME *_map_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ - void PFX##_iter_free(struct SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(struct SNAME##_iter *iter); \ - bool PFX##_iter_end(struct SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(struct SNAME##_iter *iter); \ - void PFX##_iter_to_end(struct SNAME##_iter *iter); \ - bool PFX##_iter_next(struct SNAME##_iter *iter); \ - bool PFX##_iter_prev(struct SNAME##_iter *iter); \ - bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - K PFX##_iter_key(struct SNAME##_iter *iter); \ - V PFX##_iter_value(struct SNAME##_iter *iter); \ - V *PFX##_iter_rvalue(struct SNAME##_iter *iter); \ + * ------------------------------------------------------------------------- */ +#define CMC_GENERATE_MULTIMAP_HEADER(PFX, SNAME, K, V) \ + \ + /* Multimap Structure */ \ + struct SNAME \ + { \ + /* Array of linked list to entries */ \ + struct SNAME##_entry *(*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 (*it_start)(struct SNAME *); \ + \ + /* Function that returns an iterator to the end of the multimap */ \ + struct SNAME##_iter (*it_end)(struct SNAME *); \ + \ + /* Custom allocation functions */ \ + struct cmc_alloc_node *alloc; \ + \ + /* Custom callback functions */ \ + struct cmc_callbacks_multimap *callbacks; \ + }; \ + \ + /* Multimap Entry */ \ + struct SNAME##_entry \ + { \ + /* Entry Key */ \ + K key; \ + \ + /* Entry Value */ \ + V value; \ + \ + /* Next entry on the linked list */ \ + struct SNAME##_entry *next; \ + \ + /* Previous entry on the linked list */ \ + struct SNAME##_entry *prev; \ + }; \ + \ + struct SNAME##_iter \ + { \ + /* Target multimap */ \ + struct SNAME *target; \ + \ + /* Current entry */ \ + struct SNAME##_entry *curr_entry; \ + \ + /* Cursor`s position (index) */ \ + size_t cursor; \ + \ + /* Keeps track of relative index to the iteration of elements */ \ + size_t index; \ + \ + /* The index of the first element */ \ + size_t first; \ + \ + /* The index of the last element */ \ + size_t last; \ + \ + /* If the iterator has reached the start of the iteration */ \ + bool start; \ + \ + /* If the iterator has reached the end of the iteration */ \ + bool end; \ + }; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + struct SNAME *PFX##_new(size_t capacity, double load, \ + int (*compare)(K, K), size_t (*hash)(K)); \ + struct SNAME *PFX##_new_custom(size_t capacity, double load, \ + int (*compare)(K, K), size_t (*hash)(K), \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_multimap *callbacks); \ + void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)); \ + void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)); \ + /* Customization of Allocation and Callbacks */ \ + void PFX##_customize(struct SNAME *_map_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_multimap *callbacks); \ + /* Collection Input and Output */ \ + bool PFX##_insert(struct SNAME *_map_, K key, V value); \ + bool PFX##_update(struct SNAME *_map_, K key, V new_value, V *old_value); \ + size_t PFX##_update_all(struct SNAME *_map_, K key, V new_value, \ + V **old_values); \ + bool PFX##_remove(struct SNAME *_map_, K key, V *out_value); \ + size_t PFX##_remove_all(struct SNAME *_map_, K key, V **out_values); \ + /* Element Access */ \ + bool PFX##_max(struct SNAME *_map_, K *key, V *value); \ + bool PFX##_min(struct SNAME *_map_, K *key, V *value); \ + V PFX##_get(struct SNAME *_map_, K key); \ + V *PFX##_get_ref(struct SNAME *_map_, K key); \ + /* Collection State */ \ + bool PFX##_contains(struct SNAME *_map_, K key); \ + bool PFX##_empty(struct SNAME *_map_); \ + bool PFX##_full(struct SNAME *_map_); \ + size_t PFX##_count(struct SNAME *_map_); \ + size_t PFX##_key_count(struct SNAME *_map_, K key); \ + size_t PFX##_capacity(struct SNAME *_map_); \ + double PFX##_load(struct SNAME *_map_); \ + /* Collection Utility */ \ + bool PFX##_resize(struct SNAME *_map_, size_t capacity); \ + struct SNAME *PFX##_copy_of(struct SNAME *_map_, K (*key_copy_func)(K), \ + V (*value_copy_func)(V)); \ + bool PFX##_equals(struct SNAME *_map1_, struct SNAME *_map2_, \ + bool ignore_key_count); \ + struct cmc_string PFX##_to_string(struct SNAME *_map_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ + void PFX##_iter_free(struct SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(struct SNAME##_iter *iter); \ + bool PFX##_iter_end(struct SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(struct SNAME##_iter *iter); \ + void PFX##_iter_to_end(struct SNAME##_iter *iter); \ + bool PFX##_iter_next(struct SNAME##_iter *iter); \ + bool PFX##_iter_prev(struct SNAME##_iter *iter); \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + K PFX##_iter_key(struct SNAME##_iter *iter); \ + V PFX##_iter_value(struct SNAME##_iter *iter); \ + V *PFX##_iter_rvalue(struct SNAME##_iter *iter); \ size_t PFX##_iter_index(struct SNAME##_iter *iter); -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Source - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_MULTIMAP_SOURCE(PFX, SNAME, K, V) \ - \ - /* Implementation Detail Functions */ \ - struct SNAME##_entry *PFX##_impl_new_entry(K key, V value); \ - struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_map_, K key); \ - size_t PFX##_impl_calculate_size(size_t required); \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_map_); \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_map_); \ - \ - struct SNAME *PFX##_new(size_t capacity, double load, int (*compare)(K, K), size_t (*hash)(K)) \ - { \ - struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ - \ - 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); \ - \ - struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_map_) \ - return NULL; \ - \ - _map_->buffer = alloc->calloc(real_capacity, sizeof(struct SNAME##_entry * [2])); \ - \ - if (!_map_->buffer) \ - { \ - alloc->free(_map_); \ - return NULL; \ - } \ - \ - _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; \ - \ - _map_->alloc = alloc; \ - _map_->callbacks = NULL; \ - \ - return _map_; \ - } \ - \ - struct SNAME *PFX##_new_custom(size_t capacity, double load, int (*compare)(K, K), \ - size_t (*hash)(K), struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_multimap *callbacks) \ - { \ - if (capacity == 0 || load <= 0) \ - return NULL; \ - \ - /* Prevent integer overflow */ \ - if (capacity >= UINTMAX_MAX * load) \ - return NULL; \ - \ - if (!alloc) \ - alloc = &cmc_alloc_node_default; \ - \ - size_t real_capacity = PFX##_impl_calculate_size(capacity / load); \ - \ - struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_map_) \ - return NULL; \ - \ - _map_->buffer = alloc->calloc(real_capacity, sizeof(struct SNAME##_entry * [2])); \ - \ - if (!_map_->buffer) \ - { \ - alloc->free(_map_); \ - return NULL; \ - } \ - \ - _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; \ - \ - _map_->alloc = alloc; \ - _map_->callbacks = callbacks; \ - \ - return _map_; \ - } \ - \ - void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - size_t index = 0; \ - struct 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) \ - { \ - struct SNAME##_entry *tmp = scan; \ - \ - scan = scan->next; \ - \ - if (deallocator) \ - deallocator(tmp->key, tmp->value); \ - \ - free(tmp); \ - } \ - } \ - } \ - \ - index++; \ - } \ - \ - memset(_map_->buffer, 0, sizeof(struct SNAME##_entry * [2]) * _map_->capacity); \ - \ - _map_->count = 0; \ - } \ - \ - void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - size_t index = 0; \ - struct 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) \ - { \ - struct SNAME##_entry *tmp = scan; \ - \ - scan = scan->next; \ - \ - if (deallocator) \ - deallocator(tmp->key, tmp->value); \ - \ - free(tmp); \ - } \ - } \ - } \ - \ - index++; \ - } \ - \ - free(_map_->buffer); \ - free(_map_); \ - } \ - \ - void PFX##_customize(struct SNAME *_map_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_multimap *callbacks) \ - { \ - if (alloc) \ - _map_->alloc = alloc; \ - \ - if (callbacks) \ - _map_->callbacks = callbacks; \ - } \ - \ - bool PFX##_insert(struct SNAME *_map_, K key, V value) \ - { \ - if (PFX##_full(_map_)) \ - { \ - if (!PFX##_resize(_map_, PFX##_capacity(_map_) + 1)) \ - return false; \ - } \ - \ - size_t hash = _map_->hash(key); \ - size_t pos = hash % _map_->capacity; \ - \ - struct 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(struct SNAME *_map_, K key, V new_value, V *old_value) \ - { \ - struct 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(struct 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); \ - \ - struct 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(struct SNAME *_map_, K key, V *out_value) \ - { \ - size_t hash = _map_->hash(key); \ - \ - struct SNAME##_entry **head = &(_map_->buffer[hash % _map_->capacity][0]); \ - struct SNAME##_entry **tail = &(_map_->buffer[hash % _map_->capacity][1]); \ - \ - if (*head == NULL) \ - return false; \ - \ - struct 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(struct SNAME *_map_, K key, V **out_values) \ - { \ - size_t hash = _map_->hash(key); \ - \ - struct SNAME##_entry **head = &(_map_->buffer[hash % _map_->capacity][0]); \ - struct 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(struct SNAME##_entry) * total); \ - \ - struct 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; \ - \ - struct 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##_max(struct SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - struct 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(struct SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - struct 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(struct SNAME *_map_, K key) \ - { \ - struct SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ - \ - if (!entry) \ - return (V){0}; \ - \ - return entry->value; \ - } \ - \ - V *PFX##_get_ref(struct SNAME *_map_, K key) \ - { \ - struct SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ - \ - if (!entry) \ - return NULL; \ - \ - return &(entry->value); \ - } \ - \ - bool PFX##_contains(struct SNAME *_map_, K key) \ - { \ - return PFX##_impl_get_entry(_map_, key) != NULL; \ - } \ - \ - bool PFX##_empty(struct SNAME *_map_) \ - { \ - return _map_->count == 0; \ - } \ - \ - bool PFX##_full(struct SNAME *_map_) \ - { \ - return (double)PFX##_capacity(_map_) * PFX##_load(_map_) <= (double)PFX##_count(_map_); \ - } \ - \ - size_t PFX##_count(struct SNAME *_map_) \ - { \ - return _map_->count; \ - } \ - \ - size_t PFX##_key_count(struct SNAME *_map_, K key) \ - { \ - size_t hash = _map_->hash(key); \ - \ - struct 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(struct SNAME *_map_) \ - { \ - return _map_->capacity; \ - } \ - \ - double PFX##_load(struct SNAME *_map_) \ - { \ - return _map_->load; \ - } \ - \ - bool PFX##_resize(struct SNAME *_map_, size_t capacity) \ - { \ - if (PFX##_capacity(_map_) == capacity) \ - return true; \ - \ - if (PFX##_capacity(_map_) > capacity / PFX##_load(_map_)) \ - return true; \ - \ - /* Prevent integer overflow */ \ - if (capacity >= UINTMAX_MAX * PFX##_load(_map_)) \ - return false; \ - \ - /* Calculate required capacity based on the prime numbers */ \ - size_t theoretical_size = PFX##_impl_calculate_size(capacity); \ - \ - /* Not possible to shrink with current available prime numbers */ \ - if (theoretical_size < PFX##_count(_map_) / PFX##_load(_map_)) \ - return false; \ - \ - struct SNAME *_new_map_ = PFX##_new(capacity, PFX##_load(_map_), _map_->cmp, _map_->hash); \ - \ - if (!_new_map_) \ - return false; \ - \ - struct 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 (PFX##_count(_map_) != PFX##_count(_new_map_)) \ - { \ - PFX##_free(_new_map_, NULL); \ - return false; \ - } \ - \ - struct 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; \ - } \ - \ - struct SNAME *PFX##_copy_of(struct SNAME *_map_, K (*key_copy_func)(K), \ - V (*value_copy_func)(V)) \ - { \ - struct SNAME *result = PFX##_new(_map_->capacity, _map_->load, _map_->cmp, _map_->hash); \ - \ - if (!result) \ - return NULL; \ - \ - struct 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(struct SNAME *_map1_, struct SNAME *_map2_, bool ignore_key_count) \ - { \ - if (ignore_key_count) \ - { \ - struct 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; \ - \ - struct 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; \ - } \ - \ - struct cmc_string PFX##_to_string(struct SNAME *_map_) \ - { \ - struct cmc_string str; \ - struct SNAME *m_ = _map_; \ - \ - int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_multimap, \ - #SNAME, #K, #V, m_, m_->buffer, m_->capacity, m_->count, \ - m_->load, m_->cmp, m_->hash, m_->alloc, m_->callbacks); \ - \ - if (n < 0 || n == (int)cmc_string_len) \ - return (struct cmc_string){0}; \ - \ - str.s[n] = '\0'; \ - \ - return str; \ - } \ - \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ - { \ - struct SNAME##_iter *iter = malloc(sizeof(struct SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(struct SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ - { \ - memset(iter, 0, sizeof(struct 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(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(struct 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(struct 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(struct 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(struct 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(struct 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(struct 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(struct 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(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (K){0}; \ - \ - return iter->curr_entry->key; \ - } \ - \ - V PFX##_iter_value(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){0}; \ - \ - return iter->curr_entry->value; \ - } \ - \ - V *PFX##_iter_rvalue(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->curr_entry->value); \ - } \ - \ - size_t PFX##_iter_index(struct SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - struct SNAME##_entry *PFX##_impl_new_entry(K key, V value) \ - { \ - struct SNAME##_entry *entry = malloc(sizeof(struct SNAME##_entry)); \ - \ - if (!entry) \ - return NULL; \ - \ - entry->key = key; \ - entry->value = value; \ - entry->next = NULL; \ - entry->prev = NULL; \ - \ - return entry; \ - } \ - \ - struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_map_, K key) \ - { \ - size_t hash = _map_->hash(key); \ - \ - struct 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 struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_map_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _map_); \ - \ - return iter; \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_map_) \ - { \ - struct 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 */ \ + struct SNAME##_entry *PFX##_impl_new_entry(K key, V value); \ + struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_map_, K key); \ + size_t PFX##_impl_calculate_size(size_t required); \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_map_); \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_map_); \ + \ + struct SNAME *PFX##_new(size_t capacity, double load, \ + int (*compare)(K, K), size_t (*hash)(K)) \ + { \ + struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ + \ + 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); \ + \ + struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_map_) \ + return NULL; \ + \ + _map_->buffer = \ + alloc->calloc(real_capacity, sizeof(struct SNAME##_entry *[2])); \ + \ + if (!_map_->buffer) \ + { \ + alloc->free(_map_); \ + return NULL; \ + } \ + \ + _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; \ + \ + _map_->alloc = alloc; \ + _map_->callbacks = NULL; \ + \ + return _map_; \ + } \ + \ + struct SNAME *PFX##_new_custom(size_t capacity, double load, \ + int (*compare)(K, K), size_t (*hash)(K), \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_multimap *callbacks) \ + { \ + if (capacity == 0 || load <= 0) \ + return NULL; \ + \ + /* Prevent integer overflow */ \ + if (capacity >= UINTMAX_MAX * load) \ + return NULL; \ + \ + if (!alloc) \ + alloc = &cmc_alloc_node_default; \ + \ + size_t real_capacity = PFX##_impl_calculate_size(capacity / load); \ + \ + struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_map_) \ + return NULL; \ + \ + _map_->buffer = \ + alloc->calloc(real_capacity, sizeof(struct SNAME##_entry *[2])); \ + \ + if (!_map_->buffer) \ + { \ + alloc->free(_map_); \ + return NULL; \ + } \ + \ + _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; \ + \ + _map_->alloc = alloc; \ + _map_->callbacks = callbacks; \ + \ + return _map_; \ + } \ + \ + void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)) \ + { \ + size_t index = 0; \ + struct 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) \ + { \ + struct SNAME##_entry *tmp = scan; \ + \ + scan = scan->next; \ + \ + if (deallocator) \ + deallocator(tmp->key, tmp->value); \ + \ + free(tmp); \ + } \ + } \ + } \ + \ + index++; \ + } \ + \ + memset(_map_->buffer, 0, \ + sizeof(struct SNAME##_entry *[2]) * _map_->capacity); \ + \ + _map_->count = 0; \ + } \ + \ + void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)) \ + { \ + size_t index = 0; \ + struct 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) \ + { \ + struct SNAME##_entry *tmp = scan; \ + \ + scan = scan->next; \ + \ + if (deallocator) \ + deallocator(tmp->key, tmp->value); \ + \ + free(tmp); \ + } \ + } \ + } \ + \ + index++; \ + } \ + \ + free(_map_->buffer); \ + free(_map_); \ + } \ + \ + void PFX##_customize(struct SNAME *_map_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_multimap *callbacks) \ + { \ + if (alloc) \ + _map_->alloc = alloc; \ + \ + if (callbacks) \ + _map_->callbacks = callbacks; \ + } \ + \ + bool PFX##_insert(struct SNAME *_map_, K key, V value) \ + { \ + if (PFX##_full(_map_)) \ + { \ + if (!PFX##_resize(_map_, PFX##_capacity(_map_) + 1)) \ + return false; \ + } \ + \ + size_t hash = _map_->hash(key); \ + size_t pos = hash % _map_->capacity; \ + \ + struct 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(struct SNAME *_map_, K key, V new_value, V *old_value) \ + { \ + struct 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(struct 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); \ + \ + struct 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(struct SNAME *_map_, K key, V *out_value) \ + { \ + size_t hash = _map_->hash(key); \ + \ + struct SNAME##_entry **head = \ + &(_map_->buffer[hash % _map_->capacity][0]); \ + struct SNAME##_entry **tail = \ + &(_map_->buffer[hash % _map_->capacity][1]); \ + \ + if (*head == NULL) \ + return false; \ + \ + struct 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(struct SNAME *_map_, K key, V **out_values) \ + { \ + size_t hash = _map_->hash(key); \ + \ + struct SNAME##_entry **head = \ + &(_map_->buffer[hash % _map_->capacity][0]); \ + struct 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(struct SNAME##_entry) * total); \ + \ + struct 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; \ + \ + struct 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##_max(struct SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + struct 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(struct SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + struct 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(struct SNAME *_map_, K key) \ + { \ + struct SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ + \ + if (!entry) \ + return (V){ 0 }; \ + \ + return entry->value; \ + } \ + \ + V *PFX##_get_ref(struct SNAME *_map_, K key) \ + { \ + struct SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ + \ + if (!entry) \ + return NULL; \ + \ + return &(entry->value); \ + } \ + \ + bool PFX##_contains(struct SNAME *_map_, K key) \ + { \ + return PFX##_impl_get_entry(_map_, key) != NULL; \ + } \ + \ + bool PFX##_empty(struct SNAME *_map_) \ + { \ + return _map_->count == 0; \ + } \ + \ + bool PFX##_full(struct SNAME *_map_) \ + { \ + return (double)PFX##_capacity(_map_) * PFX##_load(_map_) <= \ + (double)PFX##_count(_map_); \ + } \ + \ + size_t PFX##_count(struct SNAME *_map_) \ + { \ + return _map_->count; \ + } \ + \ + size_t PFX##_key_count(struct SNAME *_map_, K key) \ + { \ + size_t hash = _map_->hash(key); \ + \ + struct 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(struct SNAME *_map_) \ + { \ + return _map_->capacity; \ + } \ + \ + double PFX##_load(struct SNAME *_map_) \ + { \ + return _map_->load; \ + } \ + \ + bool PFX##_resize(struct SNAME *_map_, size_t capacity) \ + { \ + if (PFX##_capacity(_map_) == capacity) \ + return true; \ + \ + if (PFX##_capacity(_map_) > capacity / PFX##_load(_map_)) \ + return true; \ + \ + /* Prevent integer overflow */ \ + if (capacity >= UINTMAX_MAX * PFX##_load(_map_)) \ + return false; \ + \ + /* Calculate required capacity based on the prime numbers */ \ + size_t theoretical_size = PFX##_impl_calculate_size(capacity); \ + \ + /* Not possible to shrink with current available prime numbers */ \ + if (theoretical_size < PFX##_count(_map_) / PFX##_load(_map_)) \ + return false; \ + \ + struct SNAME *_new_map_ = \ + PFX##_new(capacity, PFX##_load(_map_), _map_->cmp, _map_->hash); \ + \ + if (!_new_map_) \ + return false; \ + \ + struct 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 (PFX##_count(_map_) != PFX##_count(_new_map_)) \ + { \ + PFX##_free(_new_map_, NULL); \ + return false; \ + } \ + \ + struct 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; \ + } \ + \ + struct SNAME *PFX##_copy_of(struct SNAME *_map_, K (*key_copy_func)(K), \ + V (*value_copy_func)(V)) \ + { \ + struct SNAME *result = \ + PFX##_new(_map_->capacity, _map_->load, _map_->cmp, _map_->hash); \ + \ + if (!result) \ + return NULL; \ + \ + struct 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(struct SNAME *_map1_, struct SNAME *_map2_, \ + bool ignore_key_count) \ + { \ + if (ignore_key_count) \ + { \ + struct 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; \ + \ + struct 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; \ + } \ + \ + struct cmc_string PFX##_to_string(struct SNAME *_map_) \ + { \ + struct cmc_string str; \ + struct SNAME *m_ = _map_; \ + \ + int n = \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_multimap, #SNAME, \ + #K, #V, m_, m_->buffer, m_->capacity, m_->count, \ + m_->load, m_->cmp, m_->hash, m_->alloc, m_->callbacks); \ + \ + if (n < 0 || n == (int)cmc_string_len) \ + return (struct cmc_string){ 0 }; \ + \ + str.s[n] = '\0'; \ + \ + return str; \ + } \ + \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ + { \ + struct SNAME##_iter *iter = malloc(sizeof(struct SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + void PFX##_iter_free(struct SNAME##_iter *iter) \ + { \ + free(iter); \ + } \ + \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ + { \ + memset(iter, 0, sizeof(struct 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(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + bool PFX##_iter_end(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + void PFX##_iter_to_start(struct 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(struct 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(struct 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(struct 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(struct 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(struct 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(struct 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(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return (K){ 0 }; \ + \ + return iter->curr_entry->key; \ + } \ + \ + V PFX##_iter_value(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return (V){ 0 }; \ + \ + return iter->curr_entry->value; \ + } \ + \ + V *PFX##_iter_rvalue(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return NULL; \ + \ + return &(iter->curr_entry->value); \ + } \ + \ + size_t PFX##_iter_index(struct SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + struct SNAME##_entry *PFX##_impl_new_entry(K key, V value) \ + { \ + struct SNAME##_entry *entry = malloc(sizeof(struct SNAME##_entry)); \ + \ + if (!entry) \ + return NULL; \ + \ + entry->key = key; \ + entry->value = value; \ + entry->next = NULL; \ + entry->prev = NULL; \ + \ + return entry; \ + } \ + \ + struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_map_, K key) \ + { \ + size_t hash = _map_->hash(key); \ + \ + struct 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 struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_map_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _map_); \ + \ + return iter; \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_map_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _map_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_MULTIMAP_H */ diff --git a/src/cmc/multiset.h b/src/cmc/multiset.h index d19efff..4ef4fd9 100644 --- a/src/cmc/multiset.h +++ b/src/cmc/multiset.h @@ -23,13 +23,13 @@ #include #include -#include #include +#include #include -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Core functionalities of the C Macro Collections Library - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ #ifndef CMC_CORE_H #define CMC_CORE_H @@ -48,7 +48,8 @@ static const size_t cmc_string_len = 400; /** * struct cmc_alloc_node * - * Custom allocation node. Allows collections to use custom allocation functions. + * Custom allocation node. Allows collections to use custom allocation + * functions. */ struct cmc_alloc_node { @@ -58,13 +59,14 @@ struct cmc_alloc_node void (*free)(void *); }; -static struct cmc_alloc_node cmc_alloc_node_default = {malloc, calloc, realloc, free}; +static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, + free }; #endif /* CMC_CORE_H */ -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Hashtable Implementation - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ #ifndef CMC_IMPL_HASHTABLE_STATE #define CMC_IMPL_HASHTABLE_STATE @@ -80,22 +82,52 @@ enum cmc_entry_state #ifndef CMC_IMPL_HASHTABLE_PRIMES #define CMC_IMPL_HASHTABLE_PRIMES -static const size_t cmc_hashtable_primes[] = - {53, 97, 191, 383, 769, 1531, 3067, 6143, 12289, 24571, 49157, 98299, 196613, 393209, 786431, - 1572869, 3145721, 6291449, 12582917, 25165813, 50331653, 100663291, 201326611, 402653189, - 805306357, 1610612741, 3221225473, 6442450939, 12884901893, 25769803799, 51539607551, - 103079215111, 206158430209, 412316860441, 824633720831, 1649267441651, 3298534883309, - 6597069766657, 13194139533299, 26388279066623, 52776558133303, 105553116266489, - 211106232532969, 422212465066001, 844424930131963, 1688849860263953, 3377699720527861, - 6755399441055731, 13510798882111483, 27021597764222939, 54043195528445957, 108086391056891903, - 216172782113783773, 432345564227567621, 864691128455135207, 1729382256910270481, - 3458764513820540933, 6917529027641081903, 13835058055282163729llu}; +// clang-format off +static const size_t cmc_hashtable_primes[] = { + /* < 1e3 */ + 53, 97, 191, 383, 769, + /* < 1e4 */ + 1531, 3067, 6143, + /* < 1e5 */ + 12289, 24571, 49157, 98299, + /* < 1e6 */ + 196613, 393209, 786431, + /* < 1e7 */ + 1572869, 3145721, 6291449, + /* < 1e8 */ + 12582917, 25165813, 50331653, + /* < 1e9 */ + 100663291, 201326611, 402653189, 805306357, + /* < 1e10 */ + 1610612741, 3221225473, 6442450939, + /* < 1e11 */ + 12884901893, 25769803799, 51539607551, + /* < 1e12 */ + 103079215111, 206158430209, 412316860441, 824633720831, + /* < 1e13 */ + 1649267441651, 3298534883309, 6597069766657, + /* < 1e14 */ + 13194139533299, 26388279066623, 52776558133303, + /* < 1e15 */ + 105553116266489, 211106232532969, 422212465066001, 844424930131963, + /* < 1e16 */ + 1688849860263953, 3377699720527861, 6755399441055731, + /* < 1e17 */ + 13510798882111483, 27021597764222939, 54043195528445957, + /* < 1e18 */ + 108086391056891903, 216172782113783773, 432345564227567621, 864691128455135207, + /* < 1e19 */ + 1729382256910270481, 3458764513820540933, 6917529027641081903, + /* < 1e20 */ + 13835058055282163729llu, +}; +// clang-format on #endif /* CMC_IMPL_HASHTABLE_PRIMES */ -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * MultiSet specific - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ /* to_string format */ static const char *cmc_string_fmt_multiset = "struct %s<%s> " "at %p { " @@ -134,1225 +166,1276 @@ struct cmc_callbacks_multiset #define CMC_WRAPGEN_MULTISET_SOURCE(PFX, SNAME, K, V) \ CMC_GENERATE_MULTISET_SOURCE(PFX, SNAME, V) -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Header - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_MULTISET_HEADER(PFX, SNAME, V) \ - \ - /* Hashset Structure */ \ - struct SNAME \ - { \ - /* Array of Entries */ \ - struct SNAME##_entry *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 (*it_start)(struct SNAME *); \ - \ - /* Function that returns an iterator to the end of the hashset */ \ - struct SNAME##_iter (*it_end)(struct SNAME *); \ - \ - /* Custom allocation functions */ \ - struct cmc_alloc_node *alloc; \ - \ - /* Custom callback functions */ \ - struct cmc_callbacks_multiset *callbacks; \ - }; \ - \ - struct SNAME##_entry \ - { \ - /* 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 state; \ - }; \ - \ - /* Hashset Iterator */ \ - struct SNAME##_iter \ - { \ - /* Target Hashset */ \ - struct SNAME *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* The index of the first element */ \ - size_t first; \ - \ - /* The index of the last element */ \ - size_t last; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - }; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - struct SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), \ - size_t (*hash)(V)); \ - struct SNAME *PFX##_new_custom(size_t capacity, double load, int (*compare)(V, V), \ - size_t (*hash)(V), struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_multiset *callbacks); \ - void PFX##_clear(struct SNAME *_set_, void (*deallocator)(V)); \ - void PFX##_free(struct SNAME *_set_, void (*deallocator)(V)); \ - /* Customization of Allocation and Callbacks */ \ - void PFX##_customize(struct SNAME *_set_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_multiset *callbacks); \ - /* Collection Input and Output */ \ - bool PFX##_insert(struct SNAME *_set_, V element); \ - bool PFX##_insert_many(struct SNAME *_set_, V element, size_t count); \ - bool PFX##_update(struct SNAME *_set_, V element, size_t multiplicity); \ - bool PFX##_remove(struct SNAME *_set_, V element); \ - size_t PFX##_remove_all(struct SNAME *_set_, V element); \ - /* Element Access */ \ - bool PFX##_max(struct SNAME *_set_, V *value); \ - bool PFX##_min(struct SNAME *_set_, V *value); \ - size_t PFX##_multiplicity_of(struct SNAME *_set_, V element); \ - /* Collection State */ \ - bool PFX##_contains(struct SNAME *_set_, V element); \ - bool PFX##_empty(struct SNAME *_set_); \ - bool PFX##_full(struct SNAME *_set_); \ - size_t PFX##_count(struct SNAME *_set_); \ - size_t PFX##_cardinality(struct SNAME *_set_); \ - size_t PFX##_capacity(struct SNAME *_set_); \ - double PFX##_load(struct SNAME *_set_); \ - /* Collection Utility */ \ - bool PFX##_resize(struct SNAME *_set_, size_t capacity); \ - struct SNAME *PFX##_copy_of(struct SNAME *_set_, V (*copy_func)(V)); \ - bool PFX##_equals(struct SNAME *_set1_, struct SNAME *_set2_, bool ignore_multiplicity); \ - struct cmc_string PFX##_to_string(struct SNAME *_set_); \ - \ - /* Set Operations */ \ - struct SNAME *PFX##_union(struct SNAME *_set1_, struct SNAME *_set2_); \ - struct SNAME *PFX##_intersection(struct SNAME *_set1_, struct SNAME *_set2_); \ - struct SNAME *PFX##_difference(struct SNAME *_set1_, struct SNAME *_set2_); \ - struct SNAME *PFX##_summation(struct SNAME *_set1_, struct SNAME *_set2_); \ - struct SNAME *PFX##_symmetric_difference(struct SNAME *_set1_, struct SNAME *_set2_); \ - bool PFX##_is_subset(struct SNAME *_set1_, struct SNAME *_set2_); \ - bool PFX##_is_superset(struct SNAME *_set1_, struct SNAME *_set2_); \ - bool PFX##_is_proper_subset(struct SNAME *_set1_, struct SNAME *_set2_); \ - bool PFX##_is_proper_superset(struct SNAME *_set1_, struct SNAME *_set2_); \ - bool PFX##_is_disjointset(struct SNAME *_set1_, struct SNAME *_set2_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ - void PFX##_iter_free(struct SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(struct SNAME##_iter *iter); \ - bool PFX##_iter_end(struct SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(struct SNAME##_iter *iter); \ - void PFX##_iter_to_end(struct SNAME##_iter *iter); \ - bool PFX##_iter_next(struct SNAME##_iter *iter); \ - bool PFX##_iter_prev(struct SNAME##_iter *iter); \ - bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - V PFX##_iter_value(struct SNAME##_iter *iter); \ - size_t PFX##_iter_multiplicity(struct SNAME##_iter *iter); \ + * ------------------------------------------------------------------------- */ +#define CMC_GENERATE_MULTISET_HEADER(PFX, SNAME, V) \ + \ + /* Hashset Structure */ \ + struct SNAME \ + { \ + /* Array of Entries */ \ + struct SNAME##_entry *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 (*it_start)(struct SNAME *); \ + \ + /* Function that returns an iterator to the end of the hashset */ \ + struct SNAME##_iter (*it_end)(struct SNAME *); \ + \ + /* Custom allocation functions */ \ + struct cmc_alloc_node *alloc; \ + \ + /* Custom callback functions */ \ + struct cmc_callbacks_multiset *callbacks; \ + }; \ + \ + struct SNAME##_entry \ + { \ + /* 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 state; \ + }; \ + \ + /* Hashset Iterator */ \ + struct SNAME##_iter \ + { \ + /* Target Hashset */ \ + struct SNAME *target; \ + \ + /* Cursor's position (index) */ \ + size_t cursor; \ + \ + /* Keeps track of relative index to the iteration of elements */ \ + size_t index; \ + \ + /* The index of the first element */ \ + size_t first; \ + \ + /* The index of the last element */ \ + size_t last; \ + \ + /* If the iterator has reached the start of the iteration */ \ + bool start; \ + \ + /* If the iterator has reached the end of the iteration */ \ + bool end; \ + }; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + struct SNAME *PFX##_new(size_t capacity, double load, \ + int (*compare)(V, V), size_t (*hash)(V)); \ + struct SNAME *PFX##_new_custom(size_t capacity, double load, \ + int (*compare)(V, V), size_t (*hash)(V), \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_multiset *callbacks); \ + void PFX##_clear(struct SNAME *_set_, void (*deallocator)(V)); \ + void PFX##_free(struct SNAME *_set_, void (*deallocator)(V)); \ + /* Customization of Allocation and Callbacks */ \ + void PFX##_customize(struct SNAME *_set_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_multiset *callbacks); \ + /* Collection Input and Output */ \ + bool PFX##_insert(struct SNAME *_set_, V element); \ + bool PFX##_insert_many(struct SNAME *_set_, V element, size_t count); \ + bool PFX##_update(struct SNAME *_set_, V element, size_t multiplicity); \ + bool PFX##_remove(struct SNAME *_set_, V element); \ + size_t PFX##_remove_all(struct SNAME *_set_, V element); \ + /* Element Access */ \ + bool PFX##_max(struct SNAME *_set_, V *value); \ + bool PFX##_min(struct SNAME *_set_, V *value); \ + size_t PFX##_multiplicity_of(struct SNAME *_set_, V element); \ + /* Collection State */ \ + bool PFX##_contains(struct SNAME *_set_, V element); \ + bool PFX##_empty(struct SNAME *_set_); \ + bool PFX##_full(struct SNAME *_set_); \ + size_t PFX##_count(struct SNAME *_set_); \ + size_t PFX##_cardinality(struct SNAME *_set_); \ + size_t PFX##_capacity(struct SNAME *_set_); \ + double PFX##_load(struct SNAME *_set_); \ + /* Collection Utility */ \ + bool PFX##_resize(struct SNAME *_set_, size_t capacity); \ + struct SNAME *PFX##_copy_of(struct SNAME *_set_, V (*copy_func)(V)); \ + bool PFX##_equals(struct SNAME *_set1_, struct SNAME *_set2_, \ + bool ignore_multiplicity); \ + struct cmc_string PFX##_to_string(struct SNAME *_set_); \ + \ + /* Set Operations */ \ + struct SNAME *PFX##_union(struct SNAME *_set1_, struct SNAME *_set2_); \ + struct SNAME *PFX##_intersection(struct SNAME *_set1_, \ + struct SNAME *_set2_); \ + struct SNAME *PFX##_difference(struct SNAME *_set1_, \ + struct SNAME *_set2_); \ + struct SNAME *PFX##_summation(struct SNAME *_set1_, struct SNAME *_set2_); \ + struct SNAME *PFX##_symmetric_difference(struct SNAME *_set1_, \ + struct SNAME *_set2_); \ + bool PFX##_is_subset(struct SNAME *_set1_, struct SNAME *_set2_); \ + bool PFX##_is_superset(struct SNAME *_set1_, struct SNAME *_set2_); \ + bool PFX##_is_proper_subset(struct SNAME *_set1_, struct SNAME *_set2_); \ + bool PFX##_is_proper_superset(struct SNAME *_set1_, struct SNAME *_set2_); \ + bool PFX##_is_disjointset(struct SNAME *_set1_, struct SNAME *_set2_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ + void PFX##_iter_free(struct SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(struct SNAME##_iter *iter); \ + bool PFX##_iter_end(struct SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(struct SNAME##_iter *iter); \ + void PFX##_iter_to_end(struct SNAME##_iter *iter); \ + bool PFX##_iter_next(struct SNAME##_iter *iter); \ + bool PFX##_iter_prev(struct SNAME##_iter *iter); \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + V PFX##_iter_value(struct SNAME##_iter *iter); \ + size_t PFX##_iter_multiplicity(struct SNAME##_iter *iter); \ size_t PFX##_iter_index(struct SNAME##_iter *iter); -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Source - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_MULTISET_SOURCE(PFX, SNAME, V) \ - \ - /* Implementation Detail Functions */ \ - static struct SNAME##_entry *PFX##_impl_insert_and_return(struct SNAME *_set_, V element, \ - bool *new_node); \ - static struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_set_, V element); \ - static size_t PFX##_impl_calculate_size(size_t required); \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_set_); \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_set_); \ - \ - struct SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), size_t (*hash)(V)) \ - { \ - struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ - \ - 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); \ - \ - struct SNAME *_set_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_set_) \ - return NULL; \ - \ - _set_->buffer = alloc->calloc(real_capacity, sizeof(struct SNAME##_entry)); \ - \ - if (!_set_->buffer) \ - { \ - alloc->free(_set_); \ - return NULL; \ - } \ - \ - _set_->count = 0; \ - _set_->cardinality = 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; \ - \ - _set_->alloc = alloc; \ - _set_->callbacks = NULL; \ - \ - return _set_; \ - } \ - \ - struct SNAME *PFX##_new_custom(size_t capacity, double load, int (*compare)(V, V), \ - size_t (*hash)(V), struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_multiset *callbacks) \ - { \ - 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); \ - \ - if (!alloc) \ - alloc = &cmc_alloc_node_default; \ - \ - struct SNAME *_set_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_set_) \ - return NULL; \ - \ - _set_->buffer = alloc->calloc(real_capacity, sizeof(struct SNAME##_entry)); \ - \ - if (!_set_->buffer) \ - { \ - alloc->free(_set_); \ - return NULL; \ - } \ - \ - _set_->count = 0; \ - _set_->cardinality = 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; \ - \ - _set_->alloc = alloc; \ - _set_->callbacks = callbacks; \ - \ - return _set_; \ - } \ - \ - void PFX##_clear(struct SNAME *_set_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _set_->capacity; i++) \ - { \ - struct SNAME##_entry *entry = &(_set_->buffer[i]); \ - \ - if (entry->state == CMC_ES_FILLED) \ - { \ - deallocator(entry->value); \ - } \ - } \ - } \ - \ - memset(_set_->buffer, 0, sizeof(struct SNAME##_entry) * _set_->capacity); \ - \ - _set_->count = 0; \ - } \ - \ - void PFX##_free(struct SNAME *_set_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _set_->capacity; i++) \ - { \ - struct SNAME##_entry *entry = &(_set_->buffer[i]); \ - \ - if (entry->state == CMC_ES_FILLED) \ - { \ - deallocator(entry->value); \ - } \ - } \ - } \ - \ - free(_set_->buffer); \ - free(_set_); \ - } \ - \ - void PFX##_customize(struct SNAME *_set_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_multiset *callbacks) \ - { \ - if (alloc) \ - _set_->alloc = alloc; \ - \ - if (callbacks) \ - _set_->callbacks = callbacks; \ - } \ - \ - bool PFX##_insert(struct SNAME *_set_, V element) \ - { \ - bool new_node; \ - \ - struct SNAME##_entry *entry = PFX##_impl_insert_and_return(_set_, element, &new_node); \ - \ - if (!entry) \ - return false; \ - \ - if (!new_node) \ - entry->multiplicity++; \ - \ - _set_->cardinality++; \ - \ - return true; \ - } \ - \ - bool PFX##_insert_many(struct SNAME *_set_, V element, size_t count) \ - { \ - if (count == 0) \ - return true; \ - \ - bool new_node; \ - \ - struct SNAME##_entry *entry = PFX##_impl_insert_and_return(_set_, element, &new_node); \ - \ - if (!entry) \ - return false; \ - \ - if (new_node) \ - entry->multiplicity = count; \ - else \ - entry->multiplicity += count; \ - \ - _set_->cardinality += count; \ - \ - return true; \ - } \ - \ - bool PFX##_update(struct SNAME *_set_, V element, size_t multiplicity) \ - { \ - if (multiplicity == 0) \ - return PFX##_remove_all(_set_, element); \ - \ - bool new_node; \ - \ - struct SNAME##_entry *entry = PFX##_impl_insert_and_return(_set_, element, &new_node); \ - \ - if (!entry) \ - return false; \ - \ - if (new_node) \ - _set_->cardinality++; \ - \ - _set_->cardinality = (_set_->cardinality - entry->multiplicity) + multiplicity; \ - \ - entry->multiplicity = multiplicity; \ - \ - return true; \ - } \ - \ - bool PFX##_remove(struct SNAME *_set_, V element) \ - { \ - struct SNAME##_entry *result = PFX##_impl_get_entry(_set_, element); \ - \ - if (result == NULL) \ - return false; \ - \ - if (result->multiplicity > 1) \ - result->multiplicity--; \ - else \ - { \ - result->value = (V){0}; \ - result->multiplicity = 0; \ - result->dist = 0; \ - result->state = CMC_ES_DELETED; \ - \ - _set_->count--; \ - } \ - \ - _set_->cardinality--; \ - \ - return true; \ - } \ - \ - size_t PFX##_remove_all(struct SNAME *_set_, V element) \ - { \ - struct SNAME##_entry *result = PFX##_impl_get_entry(_set_, element); \ - \ - if (result == NULL) \ - return 0; \ - \ - size_t removed = result->multiplicity; \ - \ - result->value = (V){0}; \ - result->multiplicity = 0; \ - result->dist = 0; \ - result->state = CMC_ES_DELETED; \ - \ - _set_->count--; \ - _set_->cardinality -= removed; \ - \ - return removed; \ - } \ - \ - bool PFX##_max(struct SNAME *_set_, V *value) \ - { \ - if (PFX##_empty(_set_)) \ - return false; \ - \ - struct 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(struct SNAME *_set_, V *value) \ - { \ - if (PFX##_empty(_set_)) \ - return false; \ - \ - struct 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; \ - } \ - \ - size_t PFX##_multiplicity_of(struct SNAME *_set_, V element) \ - { \ - struct SNAME##_entry *entry = PFX##_impl_get_entry(_set_, element); \ - \ - if (!entry) \ - return 0; \ - \ - return entry->multiplicity; \ - } \ - \ - bool PFX##_contains(struct SNAME *_set_, V element) \ - { \ - return PFX##_impl_get_entry(_set_, element) != NULL; \ - } \ - \ - bool PFX##_empty(struct SNAME *_set_) \ - { \ - return _set_->count == 0; \ - } \ - \ - bool PFX##_full(struct SNAME *_set_) \ - { \ - return (double)PFX##_capacity(_set_) * PFX##_load(_set_) <= (double)PFX##_count(_set_); \ - } \ - \ - size_t PFX##_count(struct SNAME *_set_) \ - { \ - return _set_->count; \ - } \ - \ - size_t PFX##_cardinality(struct SNAME *_set_) \ - { \ - return _set_->cardinality; \ - } \ - \ - size_t PFX##_capacity(struct SNAME *_set_) \ - { \ - return _set_->capacity; \ - } \ - \ - double PFX##_load(struct SNAME *_set_) \ - { \ - return _set_->load; \ - } \ - \ - bool PFX##_resize(struct SNAME *_set_, size_t capacity) \ - { \ - if (PFX##_capacity(_set_) == capacity) \ - return true; \ - \ - if (PFX##_capacity(_set_) > capacity / PFX##_load(_set_)) \ - return true; \ - \ - /* Prevent integer overflow */ \ - if (capacity >= UINTMAX_MAX * PFX##_load(_set_)) \ - return false; \ - \ - /* Calculate required capacity based on the prime numbers */ \ - size_t theoretical_size = PFX##_impl_calculate_size(capacity); \ - \ - /* Not possible to shrink with current available prime numbers */ \ - if (theoretical_size < PFX##_count(_set_) / PFX##_load(_set_)) \ - return false; \ - \ - struct SNAME *_new_set_ = PFX##_new(capacity, PFX##_load(_set_), _set_->cmp, _set_->hash); \ - \ - if (!_new_set_) \ - return false; \ - \ - struct SNAME##_iter iter; \ - \ - for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - PFX##_insert_many(_new_set_, PFX##_iter_value(&iter), PFX##_iter_multiplicity(&iter)); \ - } \ - \ - if (PFX##_count(_set_) != PFX##_count(_new_set_)) \ - { \ - PFX##_free(_new_set_, NULL); \ - return false; \ - } \ - \ - struct 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; \ - } \ - \ - struct SNAME *PFX##_copy_of(struct SNAME *_set_, V (*copy_func)(V)) \ - { \ - struct 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++) \ - { \ - struct SNAME##_entry *scan = &(_set_->buffer[i]); \ - \ - if (scan->state != CMC_ES_EMPTY) \ - { \ - struct 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->multiplicity = scan->multiplicity; \ - \ - target->value = copy_func(scan->value); \ - } \ - } \ - } \ - } \ - else \ - memcpy(result->buffer, _set_->buffer, sizeof(struct SNAME##_entry) * _set_->capacity); \ - \ - result->count = _set_->count; \ - result->cardinality = _set_->cardinality; \ - \ - return result; \ - } \ - \ - bool PFX##_equals(struct SNAME *_set1_, struct SNAME *_set2_, bool ignore_multiplicity) \ - { \ - if (PFX##_count(_set1_) != PFX##_count(_set2_)) \ - return false; \ - \ - if (!ignore_multiplicity && PFX##_cardinality(_set1_) != PFX##_cardinality(_set2_)) \ - return false; \ - \ - if (PFX##_count(_set1_) == 0) \ - return true; \ - \ - struct SNAME##_iter iter; \ - PFX##_iter_init(&iter, _set1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - struct SNAME##_entry *entry = PFX##_impl_get_entry(_set2_, PFX##_iter_value(&iter)); \ - \ - if (entry == NULL) \ - return false; \ - \ - if (!ignore_multiplicity && entry->multiplicity != PFX##_iter_multiplicity(&iter)) \ - return false; \ - } \ - \ - return true; \ - } \ - \ - struct cmc_string PFX##_to_string(struct SNAME *_set_) \ - { \ - struct cmc_string str; \ - struct SNAME *s_ = _set_; \ - \ - int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_multiset, \ - #SNAME, #V, s_, s_->buffer, s_->capacity, s_->count, \ - s_->cardinality, s_->load, s_->cmp, s_->hash, \ - s_->alloc, s_->callbacks); \ - \ - if (n < 0 || n == (int)cmc_string_len) \ - return (struct cmc_string){0}; \ - \ - str.s[n] = '\0'; \ - \ - return str; \ - } \ - \ - struct SNAME *PFX##_union(struct SNAME *_set1_, struct SNAME *_set2_) \ - { \ - struct SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, \ - _set1_->hash); \ - \ - if (!_set_r_) \ - return NULL; \ - \ - struct 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)) \ - { \ - V value = PFX##_iter_value(&iter1); \ - \ - size_t m1 = PFX##_iter_multiplicity(&iter1); \ - size_t m2 = PFX##_multiplicity_of(_set2_, value); \ - size_t max_ = m1 > m2 ? m1 : m2; \ - \ - PFX##_update(_set_r_, value, max_); \ - } \ - \ - for (PFX##_iter_to_start(&iter2); !PFX##_iter_end(&iter2); PFX##_iter_next(&iter2)) \ - { \ - V value = PFX##_iter_value(&iter2); \ - \ - size_t m1 = PFX##_multiplicity_of(_set1_, value); \ - size_t m2 = PFX##_iter_multiplicity(&iter2); \ - size_t max_ = m1 > m2 ? m1 : m2; \ - \ - PFX##_update(_set_r_, value, max_); \ - } \ - \ - return _set_r_; \ - } \ - \ - struct SNAME *PFX##_intersection(struct SNAME *_set1_, struct SNAME *_set2_) \ - { \ - struct SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, \ - _set1_->hash); \ - \ - if (!_set_r_) \ - return NULL; \ - \ - struct SNAME *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; \ - struct SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \ - \ - struct 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); \ - \ - size_t m1 = PFX##_iter_multiplicity(&iter); \ - size_t m2 = PFX##_multiplicity_of(_set_B_, value); \ - size_t max_ = m1 < m2 ? m1 : m2; \ - \ - PFX##_update(_set_r_, value, max_); \ - } \ - \ - return _set_r_; \ - } \ - \ - struct SNAME *PFX##_difference(struct SNAME *_set1_, struct SNAME *_set2_) \ - { \ - struct SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, \ - _set1_->hash); \ - \ - if (!_set_r_) \ - return NULL; \ - \ - struct 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); \ - \ - size_t m1 = PFX##_iter_multiplicity(&iter); \ - size_t m2 = PFX##_multiplicity_of(_set2_, value); \ - \ - if (m1 > m2) \ - PFX##_update(_set_r_, value, m1 - m2); \ - } \ - \ - return _set_r_; \ - } \ - \ - struct SNAME *PFX##_summation(struct SNAME *_set1_, struct SNAME *_set2_) \ - { \ - struct SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, \ - _set1_->hash); \ - \ - if (!_set_r_) \ - return NULL; \ - \ - struct 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_many(_set_r_, PFX##_iter_value(&iter1), PFX##_iter_multiplicity(&iter1)); \ - } \ - \ - for (PFX##_iter_to_start(&iter2); !PFX##_iter_end(&iter2); PFX##_iter_next(&iter2)) \ - { \ - PFX##_insert_many(_set_r_, PFX##_iter_value(&iter2), PFX##_iter_multiplicity(&iter2)); \ - } \ - \ - return _set_r_; \ - } \ - \ - struct SNAME *PFX##_symmetric_difference(struct SNAME *_set1_, struct SNAME *_set2_) \ - { \ - struct SNAME##_iter iter1, iter2; \ - \ - struct 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); \ - \ - size_t m1 = PFX##_iter_multiplicity(&iter1); \ - size_t m2 = PFX##_multiplicity_of(_set2_, value); \ - \ - if (m1 != m2) \ - { \ - if (m1 > m2) \ - PFX##_update(_set_r_, value, m1 - m2); \ - else \ - PFX##_update(_set_r_, value, m2 - m1); \ - } \ - } \ - \ - for (PFX##_iter_to_start(&iter2); !PFX##_iter_end(&iter2); PFX##_iter_next(&iter2)) \ - { \ - V value = PFX##_iter_value(&iter2); \ - \ - size_t m1 = PFX##_multiplicity_of(_set1_, value); \ - size_t m2 = PFX##_iter_multiplicity(&iter2); \ - \ - if (m1 != m2) \ - { \ - if (m1 > m2) \ - PFX##_update(_set_r_, value, m1 - m2); \ - else \ - PFX##_update(_set_r_, value, m2 - m1); \ - } \ - } \ - \ - return _set_r_; \ - } \ - \ - bool PFX##_is_subset(struct SNAME *_set1_, struct SNAME *_set2_) \ - { \ - if (PFX##_count(_set1_) > PFX##_count(_set2_)) \ - return false; \ - \ - if (PFX##_empty(_set1_)) \ - return true; \ - \ - struct 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); \ - \ - size_t m1 = PFX##_iter_multiplicity(&iter); \ - size_t m2 = PFX##_multiplicity_of(_set2_, value); \ - \ - if (m1 > m2) \ - return false; \ - } \ - \ - return true; \ - } \ - \ - bool PFX##_is_superset(struct SNAME *_set1_, struct SNAME *_set2_) \ - { \ - return PFX##_is_subset(_set2_, _set1_); \ - } \ - \ - bool PFX##_is_proper_subset(struct SNAME *_set1_, struct SNAME *_set2_) \ - { \ - if (PFX##_count(_set1_) >= PFX##_count(_set2_)) \ - return false; \ - \ - if (PFX##_empty(_set1_)) \ - { \ - if (!PFX##_empty(_set2_)) \ - return true; \ - else \ - return false; \ - } \ - \ - struct 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); \ - \ - size_t m1 = PFX##_iter_multiplicity(&iter); \ - size_t m2 = PFX##_multiplicity_of(_set2_, value); \ - \ - if (m1 >= m2) \ - return false; \ - } \ - \ - return true; \ - } \ - \ - bool PFX##_is_proper_superset(struct SNAME *_set1_, struct SNAME *_set2_) \ - { \ - return PFX##_is_proper_subset(_set2_, _set1_); \ - } \ - \ - bool PFX##_is_disjointset(struct SNAME *_set1_, struct SNAME *_set2_) \ - { \ - if (PFX##_empty(_set1_)) \ - return true; \ - \ - struct 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; \ - } \ - \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ - { \ - struct SNAME##_iter *iter = malloc(sizeof(struct SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(struct SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ - { \ - memset(iter, 0, sizeof(struct 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(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(struct 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(struct 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; \ - } \ - } \ - \ - bool PFX##_iter_next(struct 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); \ - \ - struct 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(struct SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->index == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - struct 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(struct 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(struct 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(struct 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(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){0}; \ - \ - return iter->target->buffer[iter->cursor].value; \ - } \ - \ - size_t PFX##_iter_multiplicity(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return 0; \ - \ - return iter->target->buffer[iter->cursor].multiplicity; \ - } \ - \ - size_t PFX##_iter_index(struct SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - static struct SNAME##_entry *PFX##_impl_insert_and_return(struct SNAME *_set_, V element, \ - bool *new_node) \ - { \ - /* If the entry already exists simply return it as we might do something with it */ \ - /* This function only guarantees that there is a valid entry for a given element */ \ - \ - *new_node = false; \ - \ - struct SNAME##_entry *entry = PFX##_impl_get_entry(_set_, element); \ - \ - if (entry != NULL) \ - return entry; \ - \ - *new_node = true; \ - \ - if (PFX##_full(_set_)) \ - { \ - if (!PFX##_resize(_set_, PFX##_capacity(_set_) + 1)) \ - return NULL; \ - } \ - \ - size_t hash = _set_->hash(element); \ - size_t original_pos = hash % _set_->capacity; \ - size_t pos = original_pos; \ - /* Current multiplicity. Might change due to robin hood hashing */ \ - size_t curr_mul = 1; \ - \ - struct SNAME##_entry *target = &(_set_->buffer[pos]); \ - \ - if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) \ - { \ - target->value = element; \ - target->multiplicity = curr_mul; \ - target->dist = pos - original_pos; \ - 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->multiplicity = curr_mul; \ - target->dist = pos - original_pos; \ - target->state = CMC_ES_FILLED; \ - \ - break; \ - } \ - else if (target->dist < pos - original_pos) \ - { \ - /* Swap everything */ \ - V tmp = target->value; \ - size_t tmp_dist = target->dist; \ - size_t tmp_mul = target->multiplicity; \ - \ - target->value = element; \ - target->dist = pos - original_pos; \ - target->multiplicity = curr_mul; \ - \ - element = tmp; \ - original_pos = pos - tmp_dist; \ - curr_mul = tmp_mul; \ - } \ - } \ - } \ - \ - _set_->count++; \ - \ - return target; \ - } \ - \ - static struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_set_, V element) \ - { \ - size_t hash = _set_->hash(element); \ - size_t pos = hash % _set_->capacity; \ - \ - struct 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 struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_set_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _set_); \ - \ - return iter; \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_set_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _set_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ + * ------------------------------------------------------------------------- */ +#define CMC_GENERATE_MULTISET_SOURCE(PFX, SNAME, V) \ + \ + /* Implementation Detail Functions */ \ + static struct SNAME##_entry *PFX##_impl_insert_and_return( \ + struct SNAME *_set_, V element, bool *new_node); \ + static struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_set_, \ + V element); \ + static size_t PFX##_impl_calculate_size(size_t required); \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_set_); \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_set_); \ + \ + struct SNAME *PFX##_new(size_t capacity, double load, \ + int (*compare)(V, V), size_t (*hash)(V)) \ + { \ + struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ + \ + 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); \ + \ + struct SNAME *_set_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_set_) \ + return NULL; \ + \ + _set_->buffer = \ + alloc->calloc(real_capacity, sizeof(struct SNAME##_entry)); \ + \ + if (!_set_->buffer) \ + { \ + alloc->free(_set_); \ + return NULL; \ + } \ + \ + _set_->count = 0; \ + _set_->cardinality = 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; \ + \ + _set_->alloc = alloc; \ + _set_->callbacks = NULL; \ + \ + return _set_; \ + } \ + \ + struct SNAME *PFX##_new_custom(size_t capacity, double load, \ + int (*compare)(V, V), size_t (*hash)(V), \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_multiset *callbacks) \ + { \ + 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); \ + \ + if (!alloc) \ + alloc = &cmc_alloc_node_default; \ + \ + struct SNAME *_set_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_set_) \ + return NULL; \ + \ + _set_->buffer = \ + alloc->calloc(real_capacity, sizeof(struct SNAME##_entry)); \ + \ + if (!_set_->buffer) \ + { \ + alloc->free(_set_); \ + return NULL; \ + } \ + \ + _set_->count = 0; \ + _set_->cardinality = 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; \ + \ + _set_->alloc = alloc; \ + _set_->callbacks = callbacks; \ + \ + return _set_; \ + } \ + \ + void PFX##_clear(struct SNAME *_set_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _set_->capacity; i++) \ + { \ + struct SNAME##_entry *entry = &(_set_->buffer[i]); \ + \ + if (entry->state == CMC_ES_FILLED) \ + { \ + deallocator(entry->value); \ + } \ + } \ + } \ + \ + memset(_set_->buffer, 0, \ + sizeof(struct SNAME##_entry) * _set_->capacity); \ + \ + _set_->count = 0; \ + } \ + \ + void PFX##_free(struct SNAME *_set_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _set_->capacity; i++) \ + { \ + struct SNAME##_entry *entry = &(_set_->buffer[i]); \ + \ + if (entry->state == CMC_ES_FILLED) \ + { \ + deallocator(entry->value); \ + } \ + } \ + } \ + \ + free(_set_->buffer); \ + free(_set_); \ + } \ + \ + void PFX##_customize(struct SNAME *_set_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_multiset *callbacks) \ + { \ + if (alloc) \ + _set_->alloc = alloc; \ + \ + if (callbacks) \ + _set_->callbacks = callbacks; \ + } \ + \ + bool PFX##_insert(struct SNAME *_set_, V element) \ + { \ + bool new_node; \ + \ + struct SNAME##_entry *entry = \ + PFX##_impl_insert_and_return(_set_, element, &new_node); \ + \ + if (!entry) \ + return false; \ + \ + if (!new_node) \ + entry->multiplicity++; \ + \ + _set_->cardinality++; \ + \ + return true; \ + } \ + \ + bool PFX##_insert_many(struct SNAME *_set_, V element, size_t count) \ + { \ + if (count == 0) \ + return true; \ + \ + bool new_node; \ + \ + struct SNAME##_entry *entry = \ + PFX##_impl_insert_and_return(_set_, element, &new_node); \ + \ + if (!entry) \ + return false; \ + \ + if (new_node) \ + entry->multiplicity = count; \ + else \ + entry->multiplicity += count; \ + \ + _set_->cardinality += count; \ + \ + return true; \ + } \ + \ + bool PFX##_update(struct SNAME *_set_, V element, size_t multiplicity) \ + { \ + if (multiplicity == 0) \ + return PFX##_remove_all(_set_, element); \ + \ + bool new_node; \ + \ + struct SNAME##_entry *entry = \ + PFX##_impl_insert_and_return(_set_, element, &new_node); \ + \ + if (!entry) \ + return false; \ + \ + if (new_node) \ + _set_->cardinality++; \ + \ + _set_->cardinality = \ + (_set_->cardinality - entry->multiplicity) + multiplicity; \ + \ + entry->multiplicity = multiplicity; \ + \ + return true; \ + } \ + \ + bool PFX##_remove(struct SNAME *_set_, V element) \ + { \ + struct SNAME##_entry *result = PFX##_impl_get_entry(_set_, element); \ + \ + if (result == NULL) \ + return false; \ + \ + if (result->multiplicity > 1) \ + result->multiplicity--; \ + else \ + { \ + result->value = (V){ 0 }; \ + result->multiplicity = 0; \ + result->dist = 0; \ + result->state = CMC_ES_DELETED; \ + \ + _set_->count--; \ + } \ + \ + _set_->cardinality--; \ + \ + return true; \ + } \ + \ + size_t PFX##_remove_all(struct SNAME *_set_, V element) \ + { \ + struct SNAME##_entry *result = PFX##_impl_get_entry(_set_, element); \ + \ + if (result == NULL) \ + return 0; \ + \ + size_t removed = result->multiplicity; \ + \ + result->value = (V){ 0 }; \ + result->multiplicity = 0; \ + result->dist = 0; \ + result->state = CMC_ES_DELETED; \ + \ + _set_->count--; \ + _set_->cardinality -= removed; \ + \ + return removed; \ + } \ + \ + bool PFX##_max(struct SNAME *_set_, V *value) \ + { \ + if (PFX##_empty(_set_)) \ + return false; \ + \ + struct 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(struct SNAME *_set_, V *value) \ + { \ + if (PFX##_empty(_set_)) \ + return false; \ + \ + struct 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; \ + } \ + \ + size_t PFX##_multiplicity_of(struct SNAME *_set_, V element) \ + { \ + struct SNAME##_entry *entry = PFX##_impl_get_entry(_set_, element); \ + \ + if (!entry) \ + return 0; \ + \ + return entry->multiplicity; \ + } \ + \ + bool PFX##_contains(struct SNAME *_set_, V element) \ + { \ + return PFX##_impl_get_entry(_set_, element) != NULL; \ + } \ + \ + bool PFX##_empty(struct SNAME *_set_) \ + { \ + return _set_->count == 0; \ + } \ + \ + bool PFX##_full(struct SNAME *_set_) \ + { \ + return (double)PFX##_capacity(_set_) * PFX##_load(_set_) <= \ + (double)PFX##_count(_set_); \ + } \ + \ + size_t PFX##_count(struct SNAME *_set_) \ + { \ + return _set_->count; \ + } \ + \ + size_t PFX##_cardinality(struct SNAME *_set_) \ + { \ + return _set_->cardinality; \ + } \ + \ + size_t PFX##_capacity(struct SNAME *_set_) \ + { \ + return _set_->capacity; \ + } \ + \ + double PFX##_load(struct SNAME *_set_) \ + { \ + return _set_->load; \ + } \ + \ + bool PFX##_resize(struct SNAME *_set_, size_t capacity) \ + { \ + if (PFX##_capacity(_set_) == capacity) \ + return true; \ + \ + if (PFX##_capacity(_set_) > capacity / PFX##_load(_set_)) \ + return true; \ + \ + /* Prevent integer overflow */ \ + if (capacity >= UINTMAX_MAX * PFX##_load(_set_)) \ + return false; \ + \ + /* Calculate required capacity based on the prime numbers */ \ + size_t theoretical_size = PFX##_impl_calculate_size(capacity); \ + \ + /* Not possible to shrink with current available prime numbers */ \ + if (theoretical_size < PFX##_count(_set_) / PFX##_load(_set_)) \ + return false; \ + \ + struct SNAME *_new_set_ = \ + PFX##_new(capacity, PFX##_load(_set_), _set_->cmp, _set_->hash); \ + \ + if (!_new_set_) \ + return false; \ + \ + struct SNAME##_iter iter; \ + \ + for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); \ + PFX##_iter_next(&iter)) \ + { \ + PFX##_insert_many(_new_set_, PFX##_iter_value(&iter), \ + PFX##_iter_multiplicity(&iter)); \ + } \ + \ + if (PFX##_count(_set_) != PFX##_count(_new_set_)) \ + { \ + PFX##_free(_new_set_, NULL); \ + return false; \ + } \ + \ + struct 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; \ + } \ + \ + struct SNAME *PFX##_copy_of(struct SNAME *_set_, V (*copy_func)(V)) \ + { \ + struct 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++) \ + { \ + struct SNAME##_entry *scan = &(_set_->buffer[i]); \ + \ + if (scan->state != CMC_ES_EMPTY) \ + { \ + struct 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->multiplicity = scan->multiplicity; \ + \ + target->value = copy_func(scan->value); \ + } \ + } \ + } \ + } \ + else \ + memcpy(result->buffer, _set_->buffer, \ + sizeof(struct SNAME##_entry) * _set_->capacity); \ + \ + result->count = _set_->count; \ + result->cardinality = _set_->cardinality; \ + \ + return result; \ + } \ + \ + bool PFX##_equals(struct SNAME *_set1_, struct SNAME *_set2_, \ + bool ignore_multiplicity) \ + { \ + if (PFX##_count(_set1_) != PFX##_count(_set2_)) \ + return false; \ + \ + if (!ignore_multiplicity && \ + PFX##_cardinality(_set1_) != PFX##_cardinality(_set2_)) \ + return false; \ + \ + if (PFX##_count(_set1_) == 0) \ + return true; \ + \ + struct SNAME##_iter iter; \ + PFX##_iter_init(&iter, _set1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); \ + PFX##_iter_next(&iter)) \ + { \ + struct SNAME##_entry *entry = \ + PFX##_impl_get_entry(_set2_, PFX##_iter_value(&iter)); \ + \ + if (entry == NULL) \ + return false; \ + \ + if (!ignore_multiplicity && \ + entry->multiplicity != PFX##_iter_multiplicity(&iter)) \ + return false; \ + } \ + \ + return true; \ + } \ + \ + struct cmc_string PFX##_to_string(struct SNAME *_set_) \ + { \ + struct cmc_string str; \ + struct SNAME *s_ = _set_; \ + \ + int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_multiset, \ + #SNAME, #V, s_, s_->buffer, s_->capacity, s_->count, \ + s_->cardinality, s_->load, s_->cmp, s_->hash, \ + s_->alloc, s_->callbacks); \ + \ + if (n < 0 || n == (int)cmc_string_len) \ + return (struct cmc_string){ 0 }; \ + \ + str.s[n] = '\0'; \ + \ + return str; \ + } \ + \ + struct SNAME *PFX##_union(struct SNAME *_set1_, struct SNAME *_set2_) \ + { \ + struct SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, \ + _set1_->cmp, _set1_->hash); \ + \ + if (!_set_r_) \ + return NULL; \ + \ + struct 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)) \ + { \ + V value = PFX##_iter_value(&iter1); \ + \ + size_t m1 = PFX##_iter_multiplicity(&iter1); \ + size_t m2 = PFX##_multiplicity_of(_set2_, value); \ + size_t max_ = m1 > m2 ? m1 : m2; \ + \ + PFX##_update(_set_r_, value, max_); \ + } \ + \ + for (PFX##_iter_to_start(&iter2); !PFX##_iter_end(&iter2); \ + PFX##_iter_next(&iter2)) \ + { \ + V value = PFX##_iter_value(&iter2); \ + \ + size_t m1 = PFX##_multiplicity_of(_set1_, value); \ + size_t m2 = PFX##_iter_multiplicity(&iter2); \ + size_t max_ = m1 > m2 ? m1 : m2; \ + \ + PFX##_update(_set_r_, value, max_); \ + } \ + \ + return _set_r_; \ + } \ + \ + struct SNAME *PFX##_intersection(struct SNAME *_set1_, \ + struct SNAME *_set2_) \ + { \ + struct SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, \ + _set1_->cmp, _set1_->hash); \ + \ + if (!_set_r_) \ + return NULL; \ + \ + struct SNAME *_set_A_ = \ + _set1_->count < _set2_->count ? _set1_ : _set2_; \ + struct SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \ + \ + struct 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); \ + \ + size_t m1 = PFX##_iter_multiplicity(&iter); \ + size_t m2 = PFX##_multiplicity_of(_set_B_, value); \ + size_t max_ = m1 < m2 ? m1 : m2; \ + \ + PFX##_update(_set_r_, value, max_); \ + } \ + \ + return _set_r_; \ + } \ + \ + struct SNAME *PFX##_difference(struct SNAME *_set1_, struct SNAME *_set2_) \ + { \ + struct SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, \ + _set1_->cmp, _set1_->hash); \ + \ + if (!_set_r_) \ + return NULL; \ + \ + struct 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); \ + \ + size_t m1 = PFX##_iter_multiplicity(&iter); \ + size_t m2 = PFX##_multiplicity_of(_set2_, value); \ + \ + if (m1 > m2) \ + PFX##_update(_set_r_, value, m1 - m2); \ + } \ + \ + return _set_r_; \ + } \ + \ + struct SNAME *PFX##_summation(struct SNAME *_set1_, struct SNAME *_set2_) \ + { \ + struct SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, \ + _set1_->cmp, _set1_->hash); \ + \ + if (!_set_r_) \ + return NULL; \ + \ + struct 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_many(_set_r_, PFX##_iter_value(&iter1), \ + PFX##_iter_multiplicity(&iter1)); \ + } \ + \ + for (PFX##_iter_to_start(&iter2); !PFX##_iter_end(&iter2); \ + PFX##_iter_next(&iter2)) \ + { \ + PFX##_insert_many(_set_r_, PFX##_iter_value(&iter2), \ + PFX##_iter_multiplicity(&iter2)); \ + } \ + \ + return _set_r_; \ + } \ + \ + struct SNAME *PFX##_symmetric_difference(struct SNAME *_set1_, \ + struct SNAME *_set2_) \ + { \ + struct SNAME##_iter iter1, iter2; \ + \ + struct 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); \ + \ + size_t m1 = PFX##_iter_multiplicity(&iter1); \ + size_t m2 = PFX##_multiplicity_of(_set2_, value); \ + \ + if (m1 != m2) \ + { \ + if (m1 > m2) \ + PFX##_update(_set_r_, value, m1 - m2); \ + else \ + PFX##_update(_set_r_, value, m2 - m1); \ + } \ + } \ + \ + for (PFX##_iter_to_start(&iter2); !PFX##_iter_end(&iter2); \ + PFX##_iter_next(&iter2)) \ + { \ + V value = PFX##_iter_value(&iter2); \ + \ + size_t m1 = PFX##_multiplicity_of(_set1_, value); \ + size_t m2 = PFX##_iter_multiplicity(&iter2); \ + \ + if (m1 != m2) \ + { \ + if (m1 > m2) \ + PFX##_update(_set_r_, value, m1 - m2); \ + else \ + PFX##_update(_set_r_, value, m2 - m1); \ + } \ + } \ + \ + return _set_r_; \ + } \ + \ + bool PFX##_is_subset(struct SNAME *_set1_, struct SNAME *_set2_) \ + { \ + if (PFX##_count(_set1_) > PFX##_count(_set2_)) \ + return false; \ + \ + if (PFX##_empty(_set1_)) \ + return true; \ + \ + struct 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); \ + \ + size_t m1 = PFX##_iter_multiplicity(&iter); \ + size_t m2 = PFX##_multiplicity_of(_set2_, value); \ + \ + if (m1 > m2) \ + return false; \ + } \ + \ + return true; \ + } \ + \ + bool PFX##_is_superset(struct SNAME *_set1_, struct SNAME *_set2_) \ + { \ + return PFX##_is_subset(_set2_, _set1_); \ + } \ + \ + bool PFX##_is_proper_subset(struct SNAME *_set1_, struct SNAME *_set2_) \ + { \ + if (PFX##_count(_set1_) >= PFX##_count(_set2_)) \ + return false; \ + \ + if (PFX##_empty(_set1_)) \ + { \ + if (!PFX##_empty(_set2_)) \ + return true; \ + else \ + return false; \ + } \ + \ + struct 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); \ + \ + size_t m1 = PFX##_iter_multiplicity(&iter); \ + size_t m2 = PFX##_multiplicity_of(_set2_, value); \ + \ + if (m1 >= m2) \ + return false; \ + } \ + \ + return true; \ + } \ + \ + bool PFX##_is_proper_superset(struct SNAME *_set1_, struct SNAME *_set2_) \ + { \ + return PFX##_is_proper_subset(_set2_, _set1_); \ + } \ + \ + bool PFX##_is_disjointset(struct SNAME *_set1_, struct SNAME *_set2_) \ + { \ + if (PFX##_empty(_set1_)) \ + return true; \ + \ + struct 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; \ + } \ + \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ + { \ + struct SNAME##_iter *iter = malloc(sizeof(struct SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + void PFX##_iter_free(struct SNAME##_iter *iter) \ + { \ + free(iter); \ + } \ + \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ + { \ + memset(iter, 0, sizeof(struct 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(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + bool PFX##_iter_end(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + void PFX##_iter_to_start(struct 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(struct 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; \ + } \ + } \ + \ + bool PFX##_iter_next(struct 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); \ + \ + struct 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(struct SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->index == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + struct 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(struct 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(struct 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(struct 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(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return (V){ 0 }; \ + \ + return iter->target->buffer[iter->cursor].value; \ + } \ + \ + size_t PFX##_iter_multiplicity(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return 0; \ + \ + return iter->target->buffer[iter->cursor].multiplicity; \ + } \ + \ + size_t PFX##_iter_index(struct SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + static struct SNAME##_entry *PFX##_impl_insert_and_return( \ + struct SNAME *_set_, V element, bool *new_node) \ + { \ + /* If the entry already exists simply return it as we might do */ \ + /* something with it. This function only guarantees that there is */ \ + /* a valid entry for a given element */ \ + \ + *new_node = false; \ + \ + struct SNAME##_entry *entry = PFX##_impl_get_entry(_set_, element); \ + \ + if (entry != NULL) \ + return entry; \ + \ + *new_node = true; \ + \ + if (PFX##_full(_set_)) \ + { \ + if (!PFX##_resize(_set_, PFX##_capacity(_set_) + 1)) \ + return NULL; \ + } \ + \ + size_t hash = _set_->hash(element); \ + size_t original_pos = hash % _set_->capacity; \ + size_t pos = original_pos; \ + /* Current multiplicity. Might change due to robin hood hashing */ \ + size_t curr_mul = 1; \ + \ + struct SNAME##_entry *target = &(_set_->buffer[pos]); \ + \ + if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) \ + { \ + target->value = element; \ + target->multiplicity = curr_mul; \ + target->dist = pos - original_pos; \ + 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->multiplicity = curr_mul; \ + target->dist = pos - original_pos; \ + target->state = CMC_ES_FILLED; \ + \ + break; \ + } \ + else if (target->dist < pos - original_pos) \ + { \ + /* Swap everything */ \ + V tmp = target->value; \ + size_t tmp_dist = target->dist; \ + size_t tmp_mul = target->multiplicity; \ + \ + target->value = element; \ + target->dist = pos - original_pos; \ + target->multiplicity = curr_mul; \ + \ + element = tmp; \ + original_pos = pos - tmp_dist; \ + curr_mul = tmp_mul; \ + } \ + } \ + } \ + \ + _set_->count++; \ + \ + return target; \ + } \ + \ + static struct SNAME##_entry *PFX##_impl_get_entry(struct SNAME *_set_, \ + V element) \ + { \ + size_t hash = _set_->hash(element); \ + size_t pos = hash % _set_->capacity; \ + \ + struct 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 struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_set_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _set_); \ + \ + return iter; \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_set_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _set_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_MULTISET_H */ diff --git a/src/cmc/queue.h b/src/cmc/queue.h index daca648..8b297a5 100644 --- a/src/cmc/queue.h +++ b/src/cmc/queue.h @@ -45,13 +45,13 @@ #include #include -#include #include +#include #include -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Core functionalities of the C Macro Collections Library - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ #ifndef CMC_CORE_H #define CMC_CORE_H @@ -70,7 +70,8 @@ static const size_t cmc_string_len = 400; /** * struct cmc_alloc_node * - * Custom allocation node. Allows collections to use custom allocation functions. + * Custom allocation node. Allows collections to use custom allocation + * functions. */ struct cmc_alloc_node { @@ -80,13 +81,14 @@ struct cmc_alloc_node void (*free)(void *); }; -static struct cmc_alloc_node cmc_alloc_node_default = {malloc, calloc, realloc, free}; +static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, + free }; #endif /* CMC_CORE_H */ -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Queue specific - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ /* to_string format */ static const char *cmc_string_fmt_queue = "struct %s<%s> " "at %p { " @@ -123,603 +125,616 @@ struct cmc_callbacks_queue #define CMC_WRAPGEN_QUEUE_SOURCE(PFX, SNAME, K, V) \ CMC_GENERATE_QUEUE_SOURCE(PFX, SNAME, V) -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Header - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_QUEUE_HEADER(PFX, SNAME, V) \ - \ - /* Queue Structure */ \ - struct SNAME \ - { \ - /* 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 (*it_start)(struct SNAME *); \ - \ - /* Function that returns an iterator to the end of the queue */ \ - struct SNAME##_iter (*it_end)(struct SNAME *); \ - \ - /* Custom allocation functions */ \ - struct cmc_alloc_node *alloc; \ - \ - /* Custom callback functions */ \ - struct cmc_callbacks_queue *callbacks; \ - }; \ - \ - /* Queue Iterator */ \ - struct SNAME##_iter \ - { \ - /* Target queue */ \ - struct SNAME *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; \ - }; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - struct SNAME *PFX##_new(size_t capacity); \ - struct SNAME *PFX##_new_custom(size_t capacity, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_queue *callbacks); \ - void PFX##_clear(struct SNAME *_queue_, void (*deallocator)(V)); \ - void PFX##_free(struct SNAME *_queue_, void (*deallocator)(V)); \ - /* Customization of Allocation and Callbacks */ \ - void PFX##_customize(struct SNAME *_queue_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_queue *callbacks); \ - /* Collection Input and Output */ \ - bool PFX##_enqueue(struct SNAME *_queue_, V element); \ - bool PFX##_dequeue(struct SNAME *_queue_); \ - /* Element Access */ \ - V PFX##_peek(struct SNAME *_queue_); \ - /* Collection State */ \ - bool PFX##_contains(struct SNAME *_queue_, V element, int (*comparator)(V, V)); \ - bool PFX##_empty(struct SNAME *_queue_); \ - bool PFX##_full(struct SNAME *_queue_); \ - size_t PFX##_count(struct SNAME *_queue_); \ - size_t PFX##_capacity(struct SNAME *_queue_); \ - /* Collection Utility */ \ - bool PFX##_resize(struct SNAME *_queue_, size_t capacity); \ - struct SNAME *PFX##_copy_of(struct SNAME *_queue_, V (*copy_func)(V)); \ - bool PFX##_equals(struct SNAME *_queue1_, struct SNAME *_queue2_, int (*comparator)(V, V)); \ - struct cmc_string PFX##_to_string(struct SNAME *_queue_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ - void PFX##_iter_free(struct SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(struct SNAME##_iter *iter); \ - bool PFX##_iter_end(struct SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(struct SNAME##_iter *iter); \ - void PFX##_iter_to_end(struct SNAME##_iter *iter); \ - bool PFX##_iter_next(struct SNAME##_iter *iter); \ - bool PFX##_iter_prev(struct SNAME##_iter *iter); \ - bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - V PFX##_iter_value(struct SNAME##_iter *iter); \ - V *PFX##_iter_rvalue(struct SNAME##_iter *iter); \ + * ------------------------------------------------------------------------- */ +#define CMC_GENERATE_QUEUE_HEADER(PFX, SNAME, V) \ + \ + /* Queue Structure */ \ + struct SNAME \ + { \ + /* 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 (*it_start)(struct SNAME *); \ + \ + /* Function that returns an iterator to the end of the queue */ \ + struct SNAME##_iter (*it_end)(struct SNAME *); \ + \ + /* Custom allocation functions */ \ + struct cmc_alloc_node *alloc; \ + \ + /* Custom callback functions */ \ + struct cmc_callbacks_queue *callbacks; \ + }; \ + \ + /* Queue Iterator */ \ + struct SNAME##_iter \ + { \ + /* Target queue */ \ + struct SNAME *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; \ + }; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + struct SNAME *PFX##_new(size_t capacity); \ + struct SNAME *PFX##_new_custom(size_t capacity, \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_queue *callbacks); \ + void PFX##_clear(struct SNAME *_queue_, void (*deallocator)(V)); \ + void PFX##_free(struct SNAME *_queue_, void (*deallocator)(V)); \ + /* Customization of Allocation and Callbacks */ \ + void PFX##_customize(struct SNAME *_queue_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_queue *callbacks); \ + /* Collection Input and Output */ \ + bool PFX##_enqueue(struct SNAME *_queue_, V element); \ + bool PFX##_dequeue(struct SNAME *_queue_); \ + /* Element Access */ \ + V PFX##_peek(struct SNAME *_queue_); \ + /* Collection State */ \ + bool PFX##_contains(struct SNAME *_queue_, V element, \ + int (*comparator)(V, V)); \ + bool PFX##_empty(struct SNAME *_queue_); \ + bool PFX##_full(struct SNAME *_queue_); \ + size_t PFX##_count(struct SNAME *_queue_); \ + size_t PFX##_capacity(struct SNAME *_queue_); \ + /* Collection Utility */ \ + bool PFX##_resize(struct SNAME *_queue_, size_t capacity); \ + struct SNAME *PFX##_copy_of(struct SNAME *_queue_, V (*copy_func)(V)); \ + bool PFX##_equals(struct SNAME *_queue1_, struct SNAME *_queue2_, \ + int (*comparator)(V, V)); \ + struct cmc_string PFX##_to_string(struct SNAME *_queue_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ + void PFX##_iter_free(struct SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(struct SNAME##_iter *iter); \ + bool PFX##_iter_end(struct SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(struct SNAME##_iter *iter); \ + void PFX##_iter_to_end(struct SNAME##_iter *iter); \ + bool PFX##_iter_next(struct SNAME##_iter *iter); \ + bool PFX##_iter_prev(struct SNAME##_iter *iter); \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + V PFX##_iter_value(struct SNAME##_iter *iter); \ + V *PFX##_iter_rvalue(struct SNAME##_iter *iter); \ size_t PFX##_iter_index(struct SNAME##_iter *iter); -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Source - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_QUEUE_SOURCE(PFX, SNAME, V) \ - \ - /* Implementation Detail Functions */ \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_queue_); \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_queue_); \ - \ - struct SNAME *PFX##_new(size_t capacity) \ - { \ - struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ - \ - if (capacity < 1) \ - return NULL; \ - \ - struct SNAME *_queue_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_queue_) \ - return NULL; \ - \ - _queue_->buffer = alloc->calloc(capacity, sizeof(V)); \ - \ - if (!_queue_->buffer) \ - { \ - alloc->free(_queue_); \ - return NULL; \ - } \ - \ - _queue_->capacity = capacity; \ - _queue_->count = 0; \ - _queue_->front = 0; \ - _queue_->back = 0; \ - \ - _queue_->it_start = PFX##_impl_it_start; \ - _queue_->it_end = PFX##_impl_it_end; \ - \ - _queue_->alloc = alloc; \ - _queue_->callbacks = NULL; \ - \ - return _queue_; \ - } \ - \ - struct SNAME *PFX##_new_custom(size_t capacity, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_queue *callbacks) \ - { \ - if (capacity < 1) \ - return NULL; \ - \ - if (!alloc) \ - alloc = &cmc_alloc_node_default; \ - \ - struct SNAME *_queue_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_queue_) \ - return NULL; \ - \ - _queue_->buffer = alloc->calloc(capacity, sizeof(V)); \ - \ - if (!_queue_->buffer) \ - { \ - alloc->free(_queue_); \ - return NULL; \ - } \ - \ - _queue_->capacity = capacity; \ - _queue_->count = 0; \ - _queue_->front = 0; \ - _queue_->back = 0; \ - \ - _queue_->it_start = PFX##_impl_it_start; \ - _queue_->it_end = PFX##_impl_it_end; \ - \ - _queue_->alloc = alloc; \ - _queue_->callbacks = callbacks; \ - \ - return _queue_; \ - } \ - \ - void PFX##_clear(struct SNAME *_queue_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) \ - { \ - deallocator(_queue_->buffer[i]); \ - \ - i = (i + 1) % _queue_->capacity; \ - } \ - } \ - \ - memset(_queue_->buffer, 0, sizeof(V) * _queue_->capacity); \ - \ - _queue_->count = 0; \ - _queue_->front = 0; \ - _queue_->back = 0; \ - } \ - \ - void PFX##_free(struct SNAME *_queue_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) \ - { \ - deallocator(_queue_->buffer[i]); \ - \ - i = (i + 1) % _queue_->capacity; \ - } \ - } \ - \ - _queue_->alloc->free(_queue_->buffer); \ - _queue_->alloc->free(_queue_); \ - } \ - \ - void PFX##_customize(struct SNAME *_queue_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_queue *callbacks) \ - { \ - if (alloc) \ - _queue_->alloc = alloc; \ - \ - if (callbacks) \ - _queue_->callbacks = callbacks; \ - } \ - \ - bool PFX##_enqueue(struct SNAME *_queue_, V element) \ - { \ - if (PFX##_full(_queue_)) \ - { \ - if (!PFX##_resize(_queue_, PFX##_capacity(_queue_) * 2)) \ - return false; \ - } \ - \ - _queue_->buffer[_queue_->back] = element; \ - \ - _queue_->back = (_queue_->back == _queue_->capacity - 1) ? 0 : _queue_->back + 1; \ - _queue_->count++; \ - \ - return true; \ - } \ - \ - bool PFX##_dequeue(struct SNAME *_queue_) \ - { \ - if (PFX##_empty(_queue_)) \ - return false; \ - \ - _queue_->buffer[_queue_->front] = (V){0}; \ - \ - _queue_->front = (_queue_->front == _queue_->capacity - 1) ? 0 : _queue_->front + 1; \ - _queue_->count--; \ - \ - return true; \ - } \ - \ - V PFX##_peek(struct SNAME *_queue_) \ - { \ - if (PFX##_empty(_queue_)) \ - return (V){0}; \ - \ - return _queue_->buffer[_queue_->front]; \ - } \ - \ - bool PFX##_contains(struct SNAME *_queue_, V element, int (*comparator)(V, V)) \ - { \ - for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) \ - { \ - if (comparator(_queue_->buffer[i], element) == 0) \ - return true; \ - \ - i = (i + 1) % _queue_->capacity; \ - } \ - \ - return false; \ - } \ - \ - bool PFX##_empty(struct SNAME *_queue_) \ - { \ - return _queue_->count == 0; \ - } \ - \ - bool PFX##_full(struct SNAME *_queue_) \ - { \ - return _queue_->count >= _queue_->capacity; \ - } \ - \ - size_t PFX##_count(struct SNAME *_queue_) \ - { \ - return _queue_->count; \ - } \ - \ - size_t PFX##_capacity(struct SNAME *_queue_) \ - { \ - return _queue_->capacity; \ - } \ - \ - bool PFX##_resize(struct SNAME *_queue_, size_t capacity) \ - { \ - if (PFX##_capacity(_queue_) == capacity) \ - return true; \ - \ - if (capacity < PFX##_count(_queue_)) \ - return false; \ - \ - V *new_buffer = _queue_->alloc->malloc(sizeof(V) * capacity); \ - \ - if (!new_buffer) \ - return false; \ - \ - for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) \ - { \ - new_buffer[j] = _queue_->buffer[i]; \ - \ - i = (i + 1) % PFX##_capacity(_queue_); \ - } \ - \ - _queue_->alloc->free(_queue_->buffer); \ - \ - _queue_->buffer = new_buffer; \ - _queue_->capacity = capacity; \ - _queue_->front = 0; \ - _queue_->back = _queue_->count; \ - \ - return true; \ - } \ - \ - struct SNAME *PFX##_copy_of(struct SNAME *_queue_, V (*copy_func)(V)) \ - { \ - struct SNAME *result = PFX##_new(_queue_->capacity); \ - \ - if (!result) \ - return NULL; \ - \ - if (copy_func) \ - { \ - for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) \ - { \ - result->buffer[j] = copy_func(_queue_->buffer[i]); \ - \ - i = (i + 1) % _queue_->capacity; \ - } \ - } \ - else \ - { \ - for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) \ - { \ - result->buffer[j] = _queue_->buffer[i]; \ - \ - i = (i + 1) % _queue_->capacity; \ - } \ - } \ - \ - result->count = _queue_->count; \ - \ - return result; \ - } \ - \ - bool PFX##_equals(struct SNAME *_queue1_, struct SNAME *_queue2_, int (*comparator)(V, V)) \ - { \ - if (PFX##_count(_queue1_) != PFX##_count(_queue2_)) \ - return false; \ - \ - size_t i, j, k; \ - for (i = _queue1_->front, j = _queue2_->front, k = 0; k < PFX##_count(_queue1_); k++) \ - { \ - if (comparator(_queue1_->buffer[i], _queue2_->buffer[j]) != 0) \ - return false; \ - \ - i = (i + 1) % _queue1_->capacity; \ - j = (j + 1) % _queue2_->capacity; \ - } \ - \ - return true; \ - } \ - \ - struct cmc_string PFX##_to_string(struct SNAME *_queue_) \ - { \ - struct cmc_string str; \ - struct SNAME *q_ = _queue_; \ - \ - int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_queue, \ - #SNAME, #V, q_, q_->buffer, q_->capacity, q_->count, \ - q_->front, q_->back, q_->alloc, q_->callbacks); \ - \ - if (n < 0 || n == (int)cmc_string_len) \ - return (struct cmc_string){0}; \ - \ - str.s[n] = '\0'; \ - \ - return str; \ - } \ - \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ - { \ - struct SNAME##_iter *iter = target->alloc->malloc(sizeof(struct SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(struct SNAME##_iter *iter) \ - { \ - iter->target->alloc->free(iter); \ - } \ - \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ - { \ - iter->target = target; \ - iter->cursor = target->front; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - } \ - \ - bool PFX##_iter_start(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(struct SNAME##_iter *iter) \ - { \ - iter->cursor = iter->target->front; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - } \ - \ - void PFX##_iter_to_end(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - iter->cursor = 0; \ - else \ - { \ - if (iter->target->back == 0) \ - iter->cursor = iter->target->capacity - 1; \ - else \ - iter->cursor = iter->target->back - 1; \ - } \ - \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - } \ - \ - bool PFX##_iter_next(struct 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); \ - \ - iter->cursor = (iter->cursor + 1) % (iter->target->capacity); \ - iter->index++; \ - \ - return true; \ - } \ - \ - bool PFX##_iter_prev(struct SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->index == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; \ - iter->index--; \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool PFX##_iter_advance(struct 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; \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - iter->index += steps; \ - iter->cursor = (iter->cursor + steps) % iter->target->capacity; \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool PFX##_iter_rewind(struct 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; \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - iter->index -= steps; \ - \ - /* Prevent underflow */ \ - if (iter->cursor < steps) \ - iter->cursor += PFX##_capacity(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(struct 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(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){0}; \ - \ - return iter->target->buffer[iter->cursor]; \ - } \ - \ - V *PFX##_iter_rvalue(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->target->buffer[iter->cursor]); \ - } \ - \ - size_t PFX##_iter_index(struct SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_queue_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _queue_); \ - PFX##_iter_to_start(&iter); \ - \ - return iter; \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_queue_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _queue_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ + * ------------------------------------------------------------------------- */ +#define CMC_GENERATE_QUEUE_SOURCE(PFX, SNAME, V) \ + \ + /* Implementation Detail Functions */ \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_queue_); \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_queue_); \ + \ + struct SNAME *PFX##_new(size_t capacity) \ + { \ + struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ + \ + if (capacity < 1) \ + return NULL; \ + \ + struct SNAME *_queue_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_queue_) \ + return NULL; \ + \ + _queue_->buffer = alloc->calloc(capacity, sizeof(V)); \ + \ + if (!_queue_->buffer) \ + { \ + alloc->free(_queue_); \ + return NULL; \ + } \ + \ + _queue_->capacity = capacity; \ + _queue_->count = 0; \ + _queue_->front = 0; \ + _queue_->back = 0; \ + \ + _queue_->it_start = PFX##_impl_it_start; \ + _queue_->it_end = PFX##_impl_it_end; \ + \ + _queue_->alloc = alloc; \ + _queue_->callbacks = NULL; \ + \ + return _queue_; \ + } \ + \ + struct SNAME *PFX##_new_custom(size_t capacity, \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_queue *callbacks) \ + { \ + if (capacity < 1) \ + return NULL; \ + \ + if (!alloc) \ + alloc = &cmc_alloc_node_default; \ + \ + struct SNAME *_queue_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_queue_) \ + return NULL; \ + \ + _queue_->buffer = alloc->calloc(capacity, sizeof(V)); \ + \ + if (!_queue_->buffer) \ + { \ + alloc->free(_queue_); \ + return NULL; \ + } \ + \ + _queue_->capacity = capacity; \ + _queue_->count = 0; \ + _queue_->front = 0; \ + _queue_->back = 0; \ + \ + _queue_->it_start = PFX##_impl_it_start; \ + _queue_->it_end = PFX##_impl_it_end; \ + \ + _queue_->alloc = alloc; \ + _queue_->callbacks = callbacks; \ + \ + return _queue_; \ + } \ + \ + void PFX##_clear(struct SNAME *_queue_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) \ + { \ + deallocator(_queue_->buffer[i]); \ + \ + i = (i + 1) % _queue_->capacity; \ + } \ + } \ + \ + memset(_queue_->buffer, 0, sizeof(V) * _queue_->capacity); \ + \ + _queue_->count = 0; \ + _queue_->front = 0; \ + _queue_->back = 0; \ + } \ + \ + void PFX##_free(struct SNAME *_queue_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) \ + { \ + deallocator(_queue_->buffer[i]); \ + \ + i = (i + 1) % _queue_->capacity; \ + } \ + } \ + \ + _queue_->alloc->free(_queue_->buffer); \ + _queue_->alloc->free(_queue_); \ + } \ + \ + void PFX##_customize(struct SNAME *_queue_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_queue *callbacks) \ + { \ + if (alloc) \ + _queue_->alloc = alloc; \ + \ + if (callbacks) \ + _queue_->callbacks = callbacks; \ + } \ + \ + bool PFX##_enqueue(struct SNAME *_queue_, V element) \ + { \ + if (PFX##_full(_queue_)) \ + { \ + if (!PFX##_resize(_queue_, PFX##_capacity(_queue_) * 2)) \ + return false; \ + } \ + \ + _queue_->buffer[_queue_->back] = element; \ + \ + _queue_->back = \ + (_queue_->back == _queue_->capacity - 1) ? 0 : _queue_->back + 1; \ + _queue_->count++; \ + \ + return true; \ + } \ + \ + bool PFX##_dequeue(struct SNAME *_queue_) \ + { \ + if (PFX##_empty(_queue_)) \ + return false; \ + \ + _queue_->buffer[_queue_->front] = (V){ 0 }; \ + \ + _queue_->front = (_queue_->front == _queue_->capacity - 1) \ + ? 0 \ + : _queue_->front + 1; \ + _queue_->count--; \ + \ + return true; \ + } \ + \ + V PFX##_peek(struct SNAME *_queue_) \ + { \ + if (PFX##_empty(_queue_)) \ + return (V){ 0 }; \ + \ + return _queue_->buffer[_queue_->front]; \ + } \ + \ + bool PFX##_contains(struct SNAME *_queue_, V element, \ + int (*comparator)(V, V)) \ + { \ + for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) \ + { \ + if (comparator(_queue_->buffer[i], element) == 0) \ + return true; \ + \ + i = (i + 1) % _queue_->capacity; \ + } \ + \ + return false; \ + } \ + \ + bool PFX##_empty(struct SNAME *_queue_) \ + { \ + return _queue_->count == 0; \ + } \ + \ + bool PFX##_full(struct SNAME *_queue_) \ + { \ + return _queue_->count >= _queue_->capacity; \ + } \ + \ + size_t PFX##_count(struct SNAME *_queue_) \ + { \ + return _queue_->count; \ + } \ + \ + size_t PFX##_capacity(struct SNAME *_queue_) \ + { \ + return _queue_->capacity; \ + } \ + \ + bool PFX##_resize(struct SNAME *_queue_, size_t capacity) \ + { \ + if (PFX##_capacity(_queue_) == capacity) \ + return true; \ + \ + if (capacity < PFX##_count(_queue_)) \ + return false; \ + \ + V *new_buffer = _queue_->alloc->malloc(sizeof(V) * capacity); \ + \ + if (!new_buffer) \ + return false; \ + \ + for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) \ + { \ + new_buffer[j] = _queue_->buffer[i]; \ + \ + i = (i + 1) % PFX##_capacity(_queue_); \ + } \ + \ + _queue_->alloc->free(_queue_->buffer); \ + \ + _queue_->buffer = new_buffer; \ + _queue_->capacity = capacity; \ + _queue_->front = 0; \ + _queue_->back = _queue_->count; \ + \ + return true; \ + } \ + \ + struct SNAME *PFX##_copy_of(struct SNAME *_queue_, V (*copy_func)(V)) \ + { \ + struct SNAME *result = PFX##_new(_queue_->capacity); \ + \ + if (!result) \ + return NULL; \ + \ + if (copy_func) \ + { \ + for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) \ + { \ + result->buffer[j] = copy_func(_queue_->buffer[i]); \ + \ + i = (i + 1) % _queue_->capacity; \ + } \ + } \ + else \ + { \ + for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) \ + { \ + result->buffer[j] = _queue_->buffer[i]; \ + \ + i = (i + 1) % _queue_->capacity; \ + } \ + } \ + \ + result->count = _queue_->count; \ + \ + return result; \ + } \ + \ + bool PFX##_equals(struct SNAME *_queue1_, struct SNAME *_queue2_, \ + int (*comparator)(V, V)) \ + { \ + if (PFX##_count(_queue1_) != PFX##_count(_queue2_)) \ + return false; \ + \ + size_t i, j, k; \ + for (i = _queue1_->front, j = _queue2_->front, k = 0; \ + k < PFX##_count(_queue1_); k++) \ + { \ + if (comparator(_queue1_->buffer[i], _queue2_->buffer[j]) != 0) \ + return false; \ + \ + i = (i + 1) % _queue1_->capacity; \ + j = (j + 1) % _queue2_->capacity; \ + } \ + \ + return true; \ + } \ + \ + struct cmc_string PFX##_to_string(struct SNAME *_queue_) \ + { \ + struct cmc_string str; \ + struct SNAME *q_ = _queue_; \ + \ + int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_queue, #SNAME, \ + #V, q_, q_->buffer, q_->capacity, q_->count, \ + q_->front, q_->back, q_->alloc, q_->callbacks); \ + \ + if (n < 0 || n == (int)cmc_string_len) \ + return (struct cmc_string){ 0 }; \ + \ + str.s[n] = '\0'; \ + \ + return str; \ + } \ + \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ + { \ + struct SNAME##_iter *iter = \ + target->alloc->malloc(sizeof(struct SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + void PFX##_iter_free(struct SNAME##_iter *iter) \ + { \ + iter->target->alloc->free(iter); \ + } \ + \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ + { \ + iter->target = target; \ + iter->cursor = target->front; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + } \ + \ + bool PFX##_iter_start(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + bool PFX##_iter_end(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + void PFX##_iter_to_start(struct SNAME##_iter *iter) \ + { \ + iter->cursor = iter->target->front; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ + \ + void PFX##_iter_to_end(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + iter->cursor = 0; \ + else \ + { \ + if (iter->target->back == 0) \ + iter->cursor = iter->target->capacity - 1; \ + else \ + iter->cursor = iter->target->back - 1; \ + } \ + \ + iter->index = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + } \ + \ + bool PFX##_iter_next(struct 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); \ + \ + iter->cursor = (iter->cursor + 1) % (iter->target->capacity); \ + iter->index++; \ + \ + return true; \ + } \ + \ + bool PFX##_iter_prev(struct SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->index == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 \ + : iter->cursor - 1; \ + iter->index--; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool PFX##_iter_advance(struct 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; \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + iter->index += steps; \ + iter->cursor = (iter->cursor + steps) % iter->target->capacity; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool PFX##_iter_rewind(struct 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; \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->index -= steps; \ + \ + /* Prevent underflow */ \ + if (iter->cursor < steps) \ + iter->cursor += PFX##_capacity(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(struct 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(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return (V){ 0 }; \ + \ + return iter->target->buffer[iter->cursor]; \ + } \ + \ + V *PFX##_iter_rvalue(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return NULL; \ + \ + return &(iter->target->buffer[iter->cursor]); \ + } \ + \ + size_t PFX##_iter_index(struct SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_queue_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _queue_); \ + PFX##_iter_to_start(&iter); \ + \ + return iter; \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_queue_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _queue_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_QUEUE_H */ diff --git a/src/cmc/sortedlist.h b/src/cmc/sortedlist.h index 6fd6741..b23f9fe 100644 --- a/src/cmc/sortedlist.h +++ b/src/cmc/sortedlist.h @@ -24,13 +24,13 @@ #include #include -#include #include +#include #include -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Core functionalities of the C Macro Collections Library - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ #ifndef CMC_CORE_H #define CMC_CORE_H @@ -49,7 +49,8 @@ static const size_t cmc_string_len = 400; /** * struct cmc_alloc_node * - * Custom allocation node. Allows collections to use custom allocation functions. + * Custom allocation node. Allows collections to use custom allocation + * functions. */ struct cmc_alloc_node { @@ -59,13 +60,14 @@ struct cmc_alloc_node void (*free)(void *); }; -static struct cmc_alloc_node cmc_alloc_node_default = {malloc, calloc, realloc, free}; +static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, + free }; #endif /* CMC_CORE_H */ -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * SortedList specific - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ /* to_string format */ static const char *cmc_string_fmt_sortedlist = "struct %s<%s> " "at %p { " @@ -102,722 +104,735 @@ struct cmc_callbacks_sortedlist #define CMC_WRAPGEN_SORTEDLIST_SOURCE(PFX, SNAME, K, V) \ CMC_GENERATE_SORTEDLIST_SOURCE(PFX, SNAME, V) -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Header - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_SORTEDLIST_HEADER(PFX, SNAME, V) \ - \ - /* List Structure */ \ - struct SNAME \ - { \ - /* Dynamic array of elements */ \ - V *buffer; \ - \ - /* Current array capacity */ \ - size_t capacity; \ - \ - /* Current amount of elements */ \ - size_t count; \ - \ - /* Flag if the list is sorted or not, used by lazy evaluation */ \ - bool is_sorted; \ - \ - /* Element comparison function */ \ - int (*cmp)(V, V); \ - \ - /* Function that returns an iterator to the start of the list */ \ - struct SNAME##_iter (*it_start)(struct SNAME *); \ - \ - /* Function that returns an iterator to the end of the list */ \ - struct SNAME##_iter (*it_end)(struct SNAME *); \ - \ - /* Custom allocation functions */ \ - struct cmc_alloc_node *alloc; \ - \ - /* Custom callback functions */ \ - struct cmc_callbacks_sortedlist *callbacks; \ - }; \ - \ - /* List Iterator */ \ - struct SNAME##_iter \ - { \ - /* Target list */ \ - struct SNAME *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; \ - }; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - struct SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)); \ - struct SNAME *PFX##_new_custom(size_t capacity, int (*compare)(V, V), \ - struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_sortedlist *callbacks); \ - void PFX##_clear(struct SNAME *_list_, void (*deallocator)(V)); \ - void PFX##_free(struct SNAME *_list_, void (*deallocator)(V)); \ - /* Customization of Allocation and Callbacks */ \ - void PFX##_customize(struct SNAME *_list_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_sortedlist *callbacks); \ - /* Collection Input and Output */ \ - bool PFX##_insert(struct SNAME *_list_, V element); \ - bool PFX##_remove(struct SNAME *_list_, size_t index); \ - /* Element Access */ \ - bool PFX##_max(struct SNAME *_list_, V *result); \ - bool PFX##_min(struct SNAME *_list_, V *result); \ - V PFX##_get(struct SNAME *_list_, size_t index); \ - size_t PFX##_indexof(struct SNAME *_list_, V element, bool from_start); \ - /* Collection State */ \ - bool PFX##_contains(struct SNAME *_list_, V element); \ - bool PFX##_empty(struct SNAME *_list_); \ - bool PFX##_full(struct SNAME *_list_); \ - size_t PFX##_count(struct SNAME *_list_); \ - size_t PFX##_capacity(struct SNAME *_list_); \ - /* Collection Utility */ \ - bool PFX##_resize(struct SNAME *_list_, size_t capacity); \ - void PFX##_sort(struct SNAME *_list_); \ - struct SNAME *PFX##_copy_of(struct SNAME *_list_, V (*copy_func)(V)); \ - bool PFX##_equals(struct SNAME *_list1_, struct SNAME *_list2_); \ - struct cmc_string PFX##_to_string(struct SNAME *_list_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ - void PFX##_iter_free(struct SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(struct SNAME##_iter *iter); \ - bool PFX##_iter_end(struct SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(struct SNAME##_iter *iter); \ - void PFX##_iter_to_end(struct SNAME##_iter *iter); \ - bool PFX##_iter_next(struct SNAME##_iter *iter); \ - bool PFX##_iter_prev(struct SNAME##_iter *iter); \ - bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - V PFX##_iter_value(struct SNAME##_iter *iter); \ + * ------------------------------------------------------------------------- */ +#define CMC_GENERATE_SORTEDLIST_HEADER(PFX, SNAME, V) \ + \ + /* List Structure */ \ + struct SNAME \ + { \ + /* Dynamic array of elements */ \ + V *buffer; \ + \ + /* Current array capacity */ \ + size_t capacity; \ + \ + /* Current amount of elements */ \ + size_t count; \ + \ + /* Flag if the list is sorted or not, used by lazy evaluation */ \ + bool is_sorted; \ + \ + /* Element comparison function */ \ + int (*cmp)(V, V); \ + \ + /* Function that returns an iterator to the start of the list */ \ + struct SNAME##_iter (*it_start)(struct SNAME *); \ + \ + /* Function that returns an iterator to the end of the list */ \ + struct SNAME##_iter (*it_end)(struct SNAME *); \ + \ + /* Custom allocation functions */ \ + struct cmc_alloc_node *alloc; \ + \ + /* Custom callback functions */ \ + struct cmc_callbacks_sortedlist *callbacks; \ + }; \ + \ + /* List Iterator */ \ + struct SNAME##_iter \ + { \ + /* Target list */ \ + struct SNAME *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; \ + }; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + struct SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)); \ + struct SNAME *PFX##_new_custom( \ + size_t capacity, int (*compare)(V, V), struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_sortedlist *callbacks); \ + void PFX##_clear(struct SNAME *_list_, void (*deallocator)(V)); \ + void PFX##_free(struct SNAME *_list_, void (*deallocator)(V)); \ + /* Customization of Allocation and Callbacks */ \ + void PFX##_customize(struct SNAME *_list_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_sortedlist *callbacks); \ + /* Collection Input and Output */ \ + bool PFX##_insert(struct SNAME *_list_, V element); \ + bool PFX##_remove(struct SNAME *_list_, size_t index); \ + /* Element Access */ \ + bool PFX##_max(struct SNAME *_list_, V *result); \ + bool PFX##_min(struct SNAME *_list_, V *result); \ + V PFX##_get(struct SNAME *_list_, size_t index); \ + size_t PFX##_indexof(struct SNAME *_list_, V element, bool from_start); \ + /* Collection State */ \ + bool PFX##_contains(struct SNAME *_list_, V element); \ + bool PFX##_empty(struct SNAME *_list_); \ + bool PFX##_full(struct SNAME *_list_); \ + size_t PFX##_count(struct SNAME *_list_); \ + size_t PFX##_capacity(struct SNAME *_list_); \ + /* Collection Utility */ \ + bool PFX##_resize(struct SNAME *_list_, size_t capacity); \ + void PFX##_sort(struct SNAME *_list_); \ + struct SNAME *PFX##_copy_of(struct SNAME *_list_, V (*copy_func)(V)); \ + bool PFX##_equals(struct SNAME *_list1_, struct SNAME *_list2_); \ + struct cmc_string PFX##_to_string(struct SNAME *_list_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ + void PFX##_iter_free(struct SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(struct SNAME##_iter *iter); \ + bool PFX##_iter_end(struct SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(struct SNAME##_iter *iter); \ + void PFX##_iter_to_end(struct SNAME##_iter *iter); \ + bool PFX##_iter_next(struct SNAME##_iter *iter); \ + bool PFX##_iter_prev(struct SNAME##_iter *iter); \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + V PFX##_iter_value(struct SNAME##_iter *iter); \ size_t PFX##_iter_index(struct SNAME##_iter *iter); -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Source - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_SORTEDLIST_SOURCE(PFX, SNAME, V) \ - \ - /* Implementation Detail Functions */ \ - static size_t PFX##_impl_binary_search_first(struct SNAME *_list_, V value); \ - static size_t PFX##_impl_binary_search_last(struct SNAME *_list_, V value); \ - void PFX##_impl_sort_quicksort(V *array, int (*cmp)(V, V), size_t low, size_t high); \ - void PFX##_impl_sort_insertion(V *array, int (*cmp)(V, V), size_t low, size_t high); \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_list_); \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_list_); \ - \ - struct SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)) \ - { \ - struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ - \ - if (capacity < 1) \ - return NULL; \ - \ - struct SNAME *_list_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_list_) \ - return NULL; \ - \ - _list_->buffer = alloc->calloc(capacity, sizeof(V)); \ - \ - if (!_list_->buffer) \ - { \ - alloc->free(_list_); \ - return NULL; \ - } \ - \ - _list_->capacity = capacity; \ - _list_->count = 0; \ - _list_->cmp = compare; \ - _list_->is_sorted = false; \ - \ - _list_->it_start = PFX##_impl_it_start; \ - _list_->it_end = PFX##_impl_it_end; \ - \ - _list_->alloc = alloc; \ - _list_->callbacks = NULL; \ - \ - return _list_; \ - } \ - \ - struct SNAME *PFX##_new_custom(size_t capacity, int (*compare)(V, V), \ - struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_sortedlist *callbacks) \ - { \ - if (capacity < 1) \ - return NULL; \ - \ - if (!alloc) \ - alloc = &cmc_alloc_node_default; \ - \ - struct SNAME *_list_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_list_) \ - return NULL; \ - \ - _list_->buffer = alloc->calloc(capacity, sizeof(V)); \ - \ - if (!_list_->buffer) \ - { \ - alloc->free(_list_); \ - return NULL; \ - } \ - \ - _list_->capacity = capacity; \ - _list_->count = 0; \ - _list_->cmp = compare; \ - _list_->is_sorted = false; \ - \ - _list_->it_start = PFX##_impl_it_start; \ - _list_->it_end = PFX##_impl_it_end; \ - \ - _list_->alloc = alloc; \ - _list_->callbacks = callbacks; \ - \ - return _list_; \ - } \ - \ - void PFX##_clear(struct SNAME *_list_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _list_->count; i++) \ - deallocator(_list_->buffer[i]); \ - } \ - \ - memset(_list_->buffer, 0, sizeof(V) * _list_->capacity); \ - \ - _list_->count = 0; \ - } \ - \ - void PFX##_free(struct SNAME *_list_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _list_->count; i++) \ - deallocator(_list_->buffer[i]); \ - } \ - \ - _list_->alloc->free(_list_->buffer); \ - _list_->alloc->free(_list_); \ - } \ - \ - void PFX##_customize(struct SNAME *_list_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_sortedlist *callbacks) \ - { \ - if (alloc) \ - _list_->alloc = alloc; \ - \ - if (callbacks) \ - _list_->callbacks = callbacks; \ - } \ - \ - bool PFX##_insert(struct SNAME *_list_, V element) \ - { \ - if (PFX##_full(_list_)) \ - { \ - if (!PFX##_resize(_list_, PFX##_capacity(_list_) * 2)) \ - return false; \ - } \ - \ - _list_->buffer[_list_->count++] = element; \ - \ - _list_->is_sorted = false; \ - \ - return true; \ - } \ - \ - bool PFX##_remove(struct SNAME *_list_, size_t index) \ - { \ - if (index >= _list_->count) \ - return false; \ - \ - memmove(_list_->buffer + index, _list_->buffer + index + 1, \ - (_list_->count - index) * sizeof(V)); \ - \ - _list_->buffer[--_list_->count] = (V){0}; \ - \ - return true; \ - } \ - \ - bool PFX##_min(struct SNAME *_list_, V *result) \ - { \ - if (PFX##_empty(_list_)) \ - return false; \ - \ - PFX##_sort(_list_); \ - \ - *result = _list_->buffer[0]; \ - \ - return true; \ - } \ - \ - bool PFX##_max(struct SNAME *_list_, V *result) \ - { \ - if (PFX##_empty(_list_)) \ - return false; \ - \ - PFX##_sort(_list_); \ - \ - *result = _list_->buffer[_list_->count - 1]; \ - \ - return true; \ - } \ - \ - V PFX##_get(struct SNAME *_list_, size_t index) \ - { \ - if (index >= _list_->count) \ - return (V){0}; \ - \ - PFX##_sort(_list_); \ - \ - return _list_->buffer[index]; \ - } \ - \ - size_t PFX##_indexof(struct SNAME *_list_, V element, bool from_start) \ - { \ - PFX##_sort(_list_); \ - \ - if (from_start) \ - { \ - return PFX##_impl_binary_search_first(_list_, element); \ - } \ - \ - return PFX##_impl_binary_search_last(_list_, element); \ - } \ - \ - bool PFX##_contains(struct SNAME *_list_, V element) \ - { \ - if (PFX##_empty(_list_)) \ - return false; \ - \ - PFX##_sort(_list_); \ - \ - return PFX##_impl_binary_search_first(_list_, element) < PFX##_count(_list_); \ - } \ - \ - bool PFX##_empty(struct SNAME *_list_) \ - { \ - return _list_->count == 0; \ - } \ - \ - bool PFX##_full(struct SNAME *_list_) \ - { \ - return _list_->count >= _list_->capacity; \ - } \ - \ - size_t PFX##_count(struct SNAME *_list_) \ - { \ - return _list_->count; \ - } \ - \ - size_t PFX##_capacity(struct SNAME *_list_) \ - { \ - return _list_->capacity; \ - } \ - \ - bool PFX##_resize(struct SNAME *_list_, size_t capacity) \ - { \ - if (PFX##_capacity(_list_) == capacity) \ - return true; \ - \ - if (capacity < PFX##_count(_list_)) \ - return false; \ - \ - V *new_buffer = _list_->alloc->realloc(_list_->buffer, sizeof(V) * capacity); \ - \ - if (!new_buffer) \ - return false; \ - \ - _list_->buffer = new_buffer; \ - _list_->capacity = capacity; \ - \ - return true; \ - } \ - \ - void PFX##_sort(struct SNAME *_list_) \ - { \ - if (!_list_->is_sorted && _list_->count > 1) \ - { \ - PFX##_impl_sort_quicksort(_list_->buffer, _list_->cmp, 0, _list_->count - 1); \ - \ - _list_->is_sorted = true; \ - } \ - } \ - \ - struct SNAME *PFX##_copy_of(struct SNAME *_list_, V (*copy_func)(V)) \ - { \ - struct SNAME *result = PFX##_new(_list_->capacity, _list_->cmp); \ - \ - if (!result) \ - return NULL; \ - \ - if (copy_func) \ - { \ - for (size_t i = 0; i < _list_->count; i++) \ - result->buffer[i] = copy_func(_list_->buffer[i]); \ - } \ - else \ - memcpy(result->buffer, _list_->buffer, sizeof(V) * _list_->count); \ - \ - result->count = _list_->count; \ - \ - return result; \ - } \ - \ - bool PFX##_equals(struct SNAME *_list1_, struct SNAME *_list2_) \ - { \ - if (PFX##_count(_list1_) != PFX##_count(_list2_)) \ - return false; \ - \ - PFX##_sort(_list1_); \ - PFX##_sort(_list2_); \ - \ - for (size_t i = 0; i < PFX##_count(_list1_); i++) \ - { \ - if (_list1_->cmp(_list1_->buffer[i], _list2_->buffer[i]) != 0) \ - return false; \ - } \ - \ - return false; \ - } \ - \ - struct cmc_string PFX##_to_string(struct SNAME *_list_) \ - { \ - struct cmc_string str; \ - struct SNAME *l_ = _list_; \ - \ - int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_sortedlist, \ - #SNAME, #V, l_, l_->buffer, l_->capacity, l_->count, \ - l_->is_sorted ? "true" : "false", l_->cmp, \ - l_->alloc, l_->callbacks); \ - \ - if (n < 0 || n == (int)cmc_string_len) \ - return (struct cmc_string){0}; \ - \ - str.s[n] = '\0'; \ - \ - return str; \ - } \ - \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ - { \ - struct SNAME##_iter *iter = target->alloc->malloc(sizeof(struct SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(struct SNAME##_iter *iter) \ - { \ - iter->target->alloc->free(iter); \ - } \ - \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ - { \ - PFX##_sort(target); \ - \ - iter->target = target; \ - iter->cursor = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - } \ - \ - bool PFX##_iter_start(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(struct SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - } \ - } \ - \ - void PFX##_iter_to_end(struct SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->start = PFX##_empty(iter->target); \ - iter->cursor = PFX##_empty(iter->target) ? 0 : iter->target->count - 1; \ - iter->end = true; \ - } \ - } \ - \ - bool PFX##_iter_next(struct SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->cursor + 1 == PFX##_count(iter->target)) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - iter->cursor++; \ - \ - return true; \ - } \ - \ - bool PFX##_iter_prev(struct SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->cursor == 0) \ - { \ - 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(struct SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->cursor + 1 == iter->target->count) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->cursor + steps >= PFX##_count(iter->target)) \ - return false; \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - iter->cursor += steps; \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->cursor == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->cursor < steps) \ - 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(struct 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(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){0}; \ - \ - return iter->target->buffer[iter->cursor]; \ - } \ - \ - size_t PFX##_iter_index(struct SNAME##_iter *iter) \ - { \ - return iter->cursor; \ - } \ - \ - static size_t PFX##_impl_binary_search_first(struct SNAME *_list_, V value) \ - { \ - if (PFX##_empty(_list_)) \ - return 1; \ - \ - size_t L = 0; \ - size_t R = PFX##_count(_list_); \ - \ - while (L < R) \ - { \ - size_t M = L + (R - L) / 2; \ - \ - if (_list_->cmp(_list_->buffer[M], value) < 0) \ - L = M + 1; \ - else \ - R = M; \ - } \ - \ - if (_list_->cmp(_list_->buffer[L], value) == 0) \ - return L; \ - \ - /* Not found */ \ - return PFX##_count(_list_); \ - } \ - \ - static size_t PFX##_impl_binary_search_last(struct SNAME *_list_, V value) \ - { \ - if (PFX##_empty(_list_)) \ - return 1; \ - \ - size_t L = 0; \ - size_t R = PFX##_count(_list_); \ - \ - while (L < R) \ - { \ - size_t M = L + (R - L) / 2; \ - \ - if (_list_->cmp(_list_->buffer[M], value) > 0) \ - R = M; \ - else \ - L = M + 1; \ - } \ - \ - if (_list_->cmp(_list_->buffer[L - 1], value) == 0) \ - return L - 1; \ - \ - /* Not found */ \ - return PFX##_count(_list_); \ - } \ - \ - /* Characteristics of this quicksort implementation: */ \ - /* - Hybrid: uses insertion sort for small arrays */ \ - /* - Partition: Lomuto's Method (can be optimized and use Hoare's Method) */ \ - /* - Tail recursion: minimize recursion depth */ \ - void PFX##_impl_sort_quicksort(V *array, int (*cmp)(V, V), size_t low, size_t high) \ - { \ - while (low < high) \ - { \ - /* Quicksort performs poorly for smaller arrays so let insertion */ \ - /* sort do the job */ \ - if (high - low < 10) \ - { \ - PFX##_impl_sort_insertion(array, cmp, low, high); \ - break; \ - } \ - else \ - { \ - /* Partition */ \ - V pivot = array[high]; \ - \ - size_t pindex = low; \ - \ - for (size_t i = low; i < high; i++) \ - { \ - if (cmp(array[i], pivot) <= 0) \ - { \ - V _tmp_ = array[i]; \ - array[i] = array[pindex]; \ - array[pindex] = _tmp_; \ - \ - pindex++; \ - } \ - } \ - \ - V _tmp_ = array[pindex]; \ - array[pindex] = array[high]; \ - array[high] = _tmp_; \ - \ - /* Tail recursion */ \ - if (pindex - low < high - pindex) \ - { \ - PFX##_impl_sort_quicksort(array, cmp, low, pindex - 1); \ - \ - low = pindex + 1; \ - } \ - else \ - { \ - PFX##_impl_sort_quicksort(array, cmp, pindex + 1, high); \ - \ - high = pindex - 1; \ - } \ - } \ - } \ - } \ - \ - void PFX##_impl_sort_insertion(V *array, int (*cmp)(V, V), size_t low, size_t high) \ - { \ - for (size_t i = low + 1; i <= high; i++) \ - { \ - V _tmp_ = array[i]; \ - size_t j = i; \ - \ - while (j > low && cmp(array[j - 1], _tmp_) > 0) \ - { \ - array[j] = array[j - 1]; \ - j--; \ - } \ - \ - array[j] = _tmp_; \ - } \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_list_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _list_); \ - PFX##_iter_to_start(&iter); \ - \ - return iter; \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_list_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _list_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ + * ------------------------------------------------------------------------- */ +#define CMC_GENERATE_SORTEDLIST_SOURCE(PFX, SNAME, V) \ + \ + /* Implementation Detail Functions */ \ + static size_t PFX##_impl_binary_search_first(struct SNAME *_list_, \ + V value); \ + static size_t PFX##_impl_binary_search_last(struct SNAME *_list_, \ + V value); \ + void PFX##_impl_sort_quicksort(V *array, int (*cmp)(V, V), size_t low, \ + size_t high); \ + void PFX##_impl_sort_insertion(V *array, int (*cmp)(V, V), size_t low, \ + size_t high); \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_list_); \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_list_); \ + \ + struct SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)) \ + { \ + struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ + \ + if (capacity < 1) \ + return NULL; \ + \ + struct SNAME *_list_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_list_) \ + return NULL; \ + \ + _list_->buffer = alloc->calloc(capacity, sizeof(V)); \ + \ + if (!_list_->buffer) \ + { \ + alloc->free(_list_); \ + return NULL; \ + } \ + \ + _list_->capacity = capacity; \ + _list_->count = 0; \ + _list_->cmp = compare; \ + _list_->is_sorted = false; \ + \ + _list_->it_start = PFX##_impl_it_start; \ + _list_->it_end = PFX##_impl_it_end; \ + \ + _list_->alloc = alloc; \ + _list_->callbacks = NULL; \ + \ + return _list_; \ + } \ + \ + struct SNAME *PFX##_new_custom(size_t capacity, int (*compare)(V, V), \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_sortedlist *callbacks) \ + { \ + if (capacity < 1) \ + return NULL; \ + \ + if (!alloc) \ + alloc = &cmc_alloc_node_default; \ + \ + struct SNAME *_list_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_list_) \ + return NULL; \ + \ + _list_->buffer = alloc->calloc(capacity, sizeof(V)); \ + \ + if (!_list_->buffer) \ + { \ + alloc->free(_list_); \ + return NULL; \ + } \ + \ + _list_->capacity = capacity; \ + _list_->count = 0; \ + _list_->cmp = compare; \ + _list_->is_sorted = false; \ + \ + _list_->it_start = PFX##_impl_it_start; \ + _list_->it_end = PFX##_impl_it_end; \ + \ + _list_->alloc = alloc; \ + _list_->callbacks = callbacks; \ + \ + return _list_; \ + } \ + \ + void PFX##_clear(struct SNAME *_list_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _list_->count; i++) \ + deallocator(_list_->buffer[i]); \ + } \ + \ + memset(_list_->buffer, 0, sizeof(V) * _list_->capacity); \ + \ + _list_->count = 0; \ + } \ + \ + void PFX##_free(struct SNAME *_list_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _list_->count; i++) \ + deallocator(_list_->buffer[i]); \ + } \ + \ + _list_->alloc->free(_list_->buffer); \ + _list_->alloc->free(_list_); \ + } \ + \ + void PFX##_customize(struct SNAME *_list_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_sortedlist *callbacks) \ + { \ + if (alloc) \ + _list_->alloc = alloc; \ + \ + if (callbacks) \ + _list_->callbacks = callbacks; \ + } \ + \ + bool PFX##_insert(struct SNAME *_list_, V element) \ + { \ + if (PFX##_full(_list_)) \ + { \ + if (!PFX##_resize(_list_, PFX##_capacity(_list_) * 2)) \ + return false; \ + } \ + \ + _list_->buffer[_list_->count++] = element; \ + \ + _list_->is_sorted = false; \ + \ + return true; \ + } \ + \ + bool PFX##_remove(struct SNAME *_list_, size_t index) \ + { \ + if (index >= _list_->count) \ + return false; \ + \ + memmove(_list_->buffer + index, _list_->buffer + index + 1, \ + (_list_->count - index) * sizeof(V)); \ + \ + _list_->buffer[--_list_->count] = (V){ 0 }; \ + \ + return true; \ + } \ + \ + bool PFX##_min(struct SNAME *_list_, V *result) \ + { \ + if (PFX##_empty(_list_)) \ + return false; \ + \ + PFX##_sort(_list_); \ + \ + *result = _list_->buffer[0]; \ + \ + return true; \ + } \ + \ + bool PFX##_max(struct SNAME *_list_, V *result) \ + { \ + if (PFX##_empty(_list_)) \ + return false; \ + \ + PFX##_sort(_list_); \ + \ + *result = _list_->buffer[_list_->count - 1]; \ + \ + return true; \ + } \ + \ + V PFX##_get(struct SNAME *_list_, size_t index) \ + { \ + if (index >= _list_->count) \ + return (V){ 0 }; \ + \ + PFX##_sort(_list_); \ + \ + return _list_->buffer[index]; \ + } \ + \ + size_t PFX##_indexof(struct SNAME *_list_, V element, bool from_start) \ + { \ + PFX##_sort(_list_); \ + \ + if (from_start) \ + { \ + return PFX##_impl_binary_search_first(_list_, element); \ + } \ + \ + return PFX##_impl_binary_search_last(_list_, element); \ + } \ + \ + bool PFX##_contains(struct SNAME *_list_, V element) \ + { \ + if (PFX##_empty(_list_)) \ + return false; \ + \ + PFX##_sort(_list_); \ + \ + return PFX##_impl_binary_search_first(_list_, element) < \ + PFX##_count(_list_); \ + } \ + \ + bool PFX##_empty(struct SNAME *_list_) \ + { \ + return _list_->count == 0; \ + } \ + \ + bool PFX##_full(struct SNAME *_list_) \ + { \ + return _list_->count >= _list_->capacity; \ + } \ + \ + size_t PFX##_count(struct SNAME *_list_) \ + { \ + return _list_->count; \ + } \ + \ + size_t PFX##_capacity(struct SNAME *_list_) \ + { \ + return _list_->capacity; \ + } \ + \ + bool PFX##_resize(struct SNAME *_list_, size_t capacity) \ + { \ + if (PFX##_capacity(_list_) == capacity) \ + return true; \ + \ + if (capacity < PFX##_count(_list_)) \ + return false; \ + \ + V *new_buffer = \ + _list_->alloc->realloc(_list_->buffer, sizeof(V) * capacity); \ + \ + if (!new_buffer) \ + return false; \ + \ + _list_->buffer = new_buffer; \ + _list_->capacity = capacity; \ + \ + return true; \ + } \ + \ + void PFX##_sort(struct SNAME *_list_) \ + { \ + if (!_list_->is_sorted && _list_->count > 1) \ + { \ + PFX##_impl_sort_quicksort(_list_->buffer, _list_->cmp, 0, \ + _list_->count - 1); \ + \ + _list_->is_sorted = true; \ + } \ + } \ + \ + struct SNAME *PFX##_copy_of(struct SNAME *_list_, V (*copy_func)(V)) \ + { \ + struct SNAME *result = PFX##_new(_list_->capacity, _list_->cmp); \ + \ + if (!result) \ + return NULL; \ + \ + if (copy_func) \ + { \ + for (size_t i = 0; i < _list_->count; i++) \ + result->buffer[i] = copy_func(_list_->buffer[i]); \ + } \ + else \ + memcpy(result->buffer, _list_->buffer, sizeof(V) * _list_->count); \ + \ + result->count = _list_->count; \ + \ + return result; \ + } \ + \ + bool PFX##_equals(struct SNAME *_list1_, struct SNAME *_list2_) \ + { \ + if (PFX##_count(_list1_) != PFX##_count(_list2_)) \ + return false; \ + \ + PFX##_sort(_list1_); \ + PFX##_sort(_list2_); \ + \ + for (size_t i = 0; i < PFX##_count(_list1_); i++) \ + { \ + if (_list1_->cmp(_list1_->buffer[i], _list2_->buffer[i]) != 0) \ + return false; \ + } \ + \ + return false; \ + } \ + \ + struct cmc_string PFX##_to_string(struct SNAME *_list_) \ + { \ + struct cmc_string str; \ + struct SNAME *l_ = _list_; \ + \ + int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_sortedlist, \ + #SNAME, #V, l_, l_->buffer, l_->capacity, l_->count, \ + l_->is_sorted ? "true" : "false", l_->cmp, l_->alloc, \ + l_->callbacks); \ + \ + if (n < 0 || n == (int)cmc_string_len) \ + return (struct cmc_string){ 0 }; \ + \ + str.s[n] = '\0'; \ + \ + return str; \ + } \ + \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ + { \ + struct SNAME##_iter *iter = \ + target->alloc->malloc(sizeof(struct SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + void PFX##_iter_free(struct SNAME##_iter *iter) \ + { \ + iter->target->alloc->free(iter); \ + } \ + \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ + { \ + PFX##_sort(target); \ + \ + iter->target = target; \ + iter->cursor = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + } \ + \ + bool PFX##_iter_start(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + bool PFX##_iter_end(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + void PFX##_iter_to_start(struct SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ + } \ + \ + void PFX##_iter_to_end(struct SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->start = PFX##_empty(iter->target); \ + iter->cursor = \ + PFX##_empty(iter->target) ? 0 : iter->target->count - 1; \ + iter->end = true; \ + } \ + } \ + \ + bool PFX##_iter_next(struct SNAME##_iter *iter) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->cursor + 1 == PFX##_count(iter->target)) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + iter->cursor++; \ + \ + return true; \ + } \ + \ + bool PFX##_iter_prev(struct SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor == 0) \ + { \ + 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(struct SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->cursor + 1 == iter->target->count) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->cursor + steps >= PFX##_count(iter->target)) \ + return false; \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + iter->cursor += steps; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->cursor < steps) \ + 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(struct 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(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return (V){ 0 }; \ + \ + return iter->target->buffer[iter->cursor]; \ + } \ + \ + size_t PFX##_iter_index(struct SNAME##_iter *iter) \ + { \ + return iter->cursor; \ + } \ + \ + static size_t PFX##_impl_binary_search_first(struct SNAME *_list_, \ + V value) \ + { \ + if (PFX##_empty(_list_)) \ + return 1; \ + \ + size_t L = 0; \ + size_t R = PFX##_count(_list_); \ + \ + while (L < R) \ + { \ + size_t M = L + (R - L) / 2; \ + \ + if (_list_->cmp(_list_->buffer[M], value) < 0) \ + L = M + 1; \ + else \ + R = M; \ + } \ + \ + if (_list_->cmp(_list_->buffer[L], value) == 0) \ + return L; \ + \ + /* Not found */ \ + return PFX##_count(_list_); \ + } \ + \ + static size_t PFX##_impl_binary_search_last(struct SNAME *_list_, V value) \ + { \ + if (PFX##_empty(_list_)) \ + return 1; \ + \ + size_t L = 0; \ + size_t R = PFX##_count(_list_); \ + \ + while (L < R) \ + { \ + size_t M = L + (R - L) / 2; \ + \ + if (_list_->cmp(_list_->buffer[M], value) > 0) \ + R = M; \ + else \ + L = M + 1; \ + } \ + \ + if (_list_->cmp(_list_->buffer[L - 1], value) == 0) \ + return L - 1; \ + \ + /* Not found */ \ + return PFX##_count(_list_); \ + } \ + \ + /* Characteristics of this quicksort implementation: */ \ + /* - Hybrid: uses insertion sort for small arrays */ \ + /* - Partition: Lomuto's Method */ \ + /* - Tail recursion: minimize recursion depth */ \ + void PFX##_impl_sort_quicksort(V *array, int (*cmp)(V, V), size_t low, \ + size_t high) \ + { \ + while (low < high) \ + { \ + /* Quicksort performs poorly for smaller arrays so let */ \ + /* insertion sort do the job */ \ + if (high - low < 10) \ + { \ + PFX##_impl_sort_insertion(array, cmp, low, high); \ + break; \ + } \ + else \ + { \ + /* Partition */ \ + V pivot = array[high]; \ + \ + size_t pindex = low; \ + \ + for (size_t i = low; i < high; i++) \ + { \ + if (cmp(array[i], pivot) <= 0) \ + { \ + V _tmp_ = array[i]; \ + array[i] = array[pindex]; \ + array[pindex] = _tmp_; \ + \ + pindex++; \ + } \ + } \ + \ + V _tmp_ = array[pindex]; \ + array[pindex] = array[high]; \ + array[high] = _tmp_; \ + \ + /* Tail recursion */ \ + if (pindex - low < high - pindex) \ + { \ + PFX##_impl_sort_quicksort(array, cmp, low, pindex - 1); \ + \ + low = pindex + 1; \ + } \ + else \ + { \ + PFX##_impl_sort_quicksort(array, cmp, pindex + 1, high); \ + \ + high = pindex - 1; \ + } \ + } \ + } \ + } \ + \ + void PFX##_impl_sort_insertion(V *array, int (*cmp)(V, V), size_t low, \ + size_t high) \ + { \ + for (size_t i = low + 1; i <= high; i++) \ + { \ + V _tmp_ = array[i]; \ + size_t j = i; \ + \ + while (j > low && cmp(array[j - 1], _tmp_) > 0) \ + { \ + array[j] = array[j - 1]; \ + j--; \ + } \ + \ + array[j] = _tmp_; \ + } \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_list_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _list_); \ + PFX##_iter_to_start(&iter); \ + \ + return iter; \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_list_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _list_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_SORTEDLIST_H */ diff --git a/src/cmc/stack.h b/src/cmc/stack.h index a9f47c4..cab366b 100644 --- a/src/cmc/stack.h +++ b/src/cmc/stack.h @@ -30,13 +30,13 @@ #include #include -#include #include +#include #include -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Core functionalities of the C Macro Collections Library - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ #ifndef CMC_CORE_H #define CMC_CORE_H @@ -55,7 +55,8 @@ static const size_t cmc_string_len = 400; /** * struct cmc_alloc_node * - * Custom allocation node. Allows collections to use custom allocation functions. + * Custom allocation node. Allows collections to use custom allocation + * functions. */ struct cmc_alloc_node { @@ -65,13 +66,14 @@ struct cmc_alloc_node void (*free)(void *); }; -static struct cmc_alloc_node cmc_alloc_node_default = {malloc, calloc, realloc, free}; +static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, + free }; #endif /* CMC_CORE_H */ -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Stack specific - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ /* to_string format */ static const char *cmc_string_fmt_stack = "struct %s<%s> " "at %p { " @@ -106,536 +108,545 @@ struct cmc_callbacks_stack #define CMC_WRAPGEN_STACK_SOURCE(PFX, SNAME, K, V) \ CMC_GENERATE_STACK_SOURCE(PFX, SNAME, V) -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Header - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_STACK_HEADER(PFX, SNAME, V) \ - \ - /* Stack Structure */ \ - struct SNAME \ - { \ - /* 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 (*it_start)(struct SNAME *); \ - \ - /* Function that returns an iterator to the end of the stack */ \ - struct SNAME##_iter (*it_end)(struct SNAME *); \ - \ - /* Custom allocation functions */ \ - struct cmc_alloc_node *alloc; \ - \ - /* Custom callback functions */ \ - struct cmc_callbacks_stack *callbacks; \ - }; \ - \ - /* Stack Iterator */ \ - struct SNAME##_iter \ - { \ - /* Target stack */ \ - struct SNAME *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; \ - }; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - struct SNAME *PFX##_new(size_t capacity); \ - struct SNAME *PFX##_new_custom(size_t capacity, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_stack *callbacks); \ - void PFX##_clear(struct SNAME *_stack_, void (*deallocator)(V)); \ - void PFX##_free(struct SNAME *_stack_, void (*deallocator)(V)); \ - /* Customization of Allocation and Callbacks */ \ - void PFX##_customize(struct SNAME *_stack_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_stack *callbacks); \ - /* Collection Input and Output */ \ - bool PFX##_push(struct SNAME *_stack_, V element); \ - bool PFX##_pop(struct SNAME *_stack_); \ - /* Element Access */ \ - V PFX##_top(struct SNAME *_stack_); \ - /* Collection State */ \ - bool PFX##_contains(struct SNAME *_stack_, V element, int (*comparator)(V, V)); \ - bool PFX##_empty(struct SNAME *_stack_); \ - bool PFX##_full(struct SNAME *_stack_); \ - size_t PFX##_count(struct SNAME *_stack_); \ - size_t PFX##_capacity(struct SNAME *_stack_); \ - /* Collection Utility */ \ - bool PFX##_resize(struct SNAME *_stack_, size_t capacity); \ - struct SNAME *PFX##_copy_of(struct SNAME *_stack_, V (*copy_func)(V)); \ - bool PFX##_equals(struct SNAME *_stack1_, struct SNAME *_stack2_, int (*comparator)(V, V)); \ - struct cmc_string PFX##_to_string(struct SNAME *_stack_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ - void PFX##_iter_free(struct SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(struct SNAME##_iter *iter); \ - bool PFX##_iter_end(struct SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(struct SNAME##_iter *iter); \ - void PFX##_iter_to_end(struct SNAME##_iter *iter); \ - bool PFX##_iter_next(struct SNAME##_iter *iter); \ - bool PFX##_iter_prev(struct SNAME##_iter *iter); \ - bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - V PFX##_iter_value(struct SNAME##_iter *iter); \ - V *PFX##_iter_rvalue(struct SNAME##_iter *iter); \ + * ------------------------------------------------------------------------- */ +#define CMC_GENERATE_STACK_HEADER(PFX, SNAME, V) \ + \ + /* Stack Structure */ \ + struct SNAME \ + { \ + /* 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 (*it_start)(struct SNAME *); \ + \ + /* Function that returns an iterator to the end of the stack */ \ + struct SNAME##_iter (*it_end)(struct SNAME *); \ + \ + /* Custom allocation functions */ \ + struct cmc_alloc_node *alloc; \ + \ + /* Custom callback functions */ \ + struct cmc_callbacks_stack *callbacks; \ + }; \ + \ + /* Stack Iterator */ \ + struct SNAME##_iter \ + { \ + /* Target stack */ \ + struct SNAME *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; \ + }; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + struct SNAME *PFX##_new(size_t capacity); \ + struct SNAME *PFX##_new_custom(size_t capacity, \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_stack *callbacks); \ + void PFX##_clear(struct SNAME *_stack_, void (*deallocator)(V)); \ + void PFX##_free(struct SNAME *_stack_, void (*deallocator)(V)); \ + /* Customization of Allocation and Callbacks */ \ + void PFX##_customize(struct SNAME *_stack_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_stack *callbacks); \ + /* Collection Input and Output */ \ + bool PFX##_push(struct SNAME *_stack_, V element); \ + bool PFX##_pop(struct SNAME *_stack_); \ + /* Element Access */ \ + V PFX##_top(struct SNAME *_stack_); \ + /* Collection State */ \ + bool PFX##_contains(struct SNAME *_stack_, V element, \ + int (*comparator)(V, V)); \ + bool PFX##_empty(struct SNAME *_stack_); \ + bool PFX##_full(struct SNAME *_stack_); \ + size_t PFX##_count(struct SNAME *_stack_); \ + size_t PFX##_capacity(struct SNAME *_stack_); \ + /* Collection Utility */ \ + bool PFX##_resize(struct SNAME *_stack_, size_t capacity); \ + struct SNAME *PFX##_copy_of(struct SNAME *_stack_, V (*copy_func)(V)); \ + bool PFX##_equals(struct SNAME *_stack1_, struct SNAME *_stack2_, \ + int (*comparator)(V, V)); \ + struct cmc_string PFX##_to_string(struct SNAME *_stack_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ + void PFX##_iter_free(struct SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(struct SNAME##_iter *iter); \ + bool PFX##_iter_end(struct SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(struct SNAME##_iter *iter); \ + void PFX##_iter_to_end(struct SNAME##_iter *iter); \ + bool PFX##_iter_next(struct SNAME##_iter *iter); \ + bool PFX##_iter_prev(struct SNAME##_iter *iter); \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + V PFX##_iter_value(struct SNAME##_iter *iter); \ + V *PFX##_iter_rvalue(struct SNAME##_iter *iter); \ size_t PFX##_iter_index(struct SNAME##_iter *iter); -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Source - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_STACK_SOURCE(PFX, SNAME, V) \ - \ - /* Implementation Detail Functions */ \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_stack_); \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_stack_); \ - \ - struct SNAME *PFX##_new(size_t capacity) \ - { \ - struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ - \ - if (capacity < 1) \ - return NULL; \ - \ - struct SNAME *_stack_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_stack_) \ - return NULL; \ - \ - _stack_->buffer = alloc->calloc(capacity, sizeof(V)); \ - \ - if (!_stack_->buffer) \ - { \ - alloc->free(_stack_); \ - return NULL; \ - } \ - \ - _stack_->capacity = capacity; \ - _stack_->count = 0; \ - \ - _stack_->it_start = PFX##_impl_it_start; \ - _stack_->it_end = PFX##_impl_it_end; \ - \ - _stack_->alloc = alloc; \ - _stack_->callbacks = NULL; \ - \ - return _stack_; \ - } \ - \ - struct SNAME *PFX##_new_custom(size_t capacity, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_stack *callbacks) \ - { \ - if (capacity < 1) \ - return NULL; \ - \ - if (!alloc) \ - alloc = &cmc_alloc_node_default; \ - \ - struct SNAME *_stack_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_stack_) \ - return NULL; \ - \ - _stack_->buffer = alloc->calloc(capacity, sizeof(V)); \ - \ - if (!_stack_->buffer) \ - { \ - alloc->free(_stack_); \ - return NULL; \ - } \ - \ - _stack_->capacity = capacity; \ - _stack_->count = 0; \ - \ - _stack_->it_start = PFX##_impl_it_start; \ - _stack_->it_end = PFX##_impl_it_end; \ - \ - _stack_->alloc = alloc; \ - _stack_->callbacks = callbacks; \ - \ - return _stack_; \ - } \ - \ - void PFX##_clear(struct 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(struct SNAME *_stack_, void (*deallocator)(V)) \ - { \ - _stack_->alloc->free(_stack_->buffer); \ - \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _stack_->count; i++) \ - deallocator(_stack_->buffer[i]); \ - } \ - \ - _stack_->alloc->free(_stack_); \ - } \ - \ - void PFX##_customize(struct SNAME *_stack_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_stack *callbacks) \ - { \ - if (alloc) \ - _stack_->alloc = alloc; \ - \ - if (callbacks) \ - _stack_->callbacks = callbacks; \ - } \ - \ - bool PFX##_push(struct SNAME *_stack_, V element) \ - { \ - if (PFX##_full(_stack_)) \ - { \ - if (!PFX##_resize(_stack_, PFX##_capacity(_stack_) * 2)) \ - return false; \ - } \ - \ - _stack_->buffer[_stack_->count++] = element; \ - \ - return true; \ - } \ - \ - bool PFX##_pop(struct SNAME *_stack_) \ - { \ - if (PFX##_empty(_stack_)) \ - return false; \ - \ - _stack_->buffer[--_stack_->count] = (V){0}; \ - \ - return true; \ - } \ - \ - V PFX##_top(struct SNAME *_stack_) \ - { \ - if (PFX##_empty(_stack_)) \ - return (V){0}; \ - \ - return _stack_->buffer[_stack_->count - 1]; \ - } \ - \ - bool PFX##_contains(struct 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(struct SNAME *_stack_) \ - { \ - return _stack_->count == 0; \ - } \ - \ - bool PFX##_full(struct SNAME *_stack_) \ - { \ - return _stack_->count >= _stack_->capacity; \ - } \ - \ - size_t PFX##_count(struct SNAME *_stack_) \ - { \ - return _stack_->count; \ - } \ - \ - size_t PFX##_capacity(struct SNAME *_stack_) \ - { \ - return _stack_->capacity; \ - } \ - \ - bool PFX##_resize(struct SNAME *_stack_, size_t capacity) \ - { \ - if (PFX##_capacity(_stack_) == capacity) \ - return true; \ - \ - if (capacity < PFX##_count(_stack_)) \ - return false; \ - \ - V *new_buffer = _stack_->alloc->realloc(_stack_->buffer, sizeof(V) * capacity); \ - \ - if (!new_buffer) \ - return false; \ - \ - _stack_->buffer = new_buffer; \ - _stack_->capacity = capacity; \ - \ - return true; \ - } \ - \ - struct SNAME *PFX##_copy_of(struct SNAME *_stack_, V (*copy_func)(V)) \ - { \ - struct 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(struct SNAME *_stack1_, struct 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; \ - } \ - \ - struct cmc_string PFX##_to_string(struct SNAME *_stack_) \ - { \ - struct cmc_string str; \ - struct SNAME *s_ = _stack_; \ - \ - int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_stack, \ - #SNAME, #V, s_, s_->buffer, s_->capacity, s_->count, \ - s_->alloc, s_->callbacks); \ - \ - if (n < 0 || n == (int)cmc_string_len) \ - return (struct cmc_string){0}; \ - \ - str.s[n] = '\0'; \ - \ - return str; \ - } \ - \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ - { \ - struct SNAME##_iter *iter = target->alloc->malloc(sizeof(struct SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(struct SNAME##_iter *iter) \ - { \ - iter->target->alloc->free(iter); \ - } \ - \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct 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(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(struct 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(struct SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = 0; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - } \ - } \ - \ - bool PFX##_iter_next(struct 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(struct 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(struct 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(struct 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(struct 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(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){0}; \ - \ - return iter->target->buffer[iter->cursor]; \ - } \ - \ - V *PFX##_iter_rvalue(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->target->buffer[iter->cursor]); \ - } \ - \ - size_t PFX##_iter_index(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return 0; \ - \ - return iter->target->count - 1 - iter->cursor; \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_stack_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _stack_); \ - PFX##_iter_to_start(&iter); \ - \ - return iter; \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_stack_) \ - { \ - struct 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 struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_stack_); \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_stack_); \ + \ + struct SNAME *PFX##_new(size_t capacity) \ + { \ + struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ + \ + if (capacity < 1) \ + return NULL; \ + \ + struct SNAME *_stack_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_stack_) \ + return NULL; \ + \ + _stack_->buffer = alloc->calloc(capacity, sizeof(V)); \ + \ + if (!_stack_->buffer) \ + { \ + alloc->free(_stack_); \ + return NULL; \ + } \ + \ + _stack_->capacity = capacity; \ + _stack_->count = 0; \ + \ + _stack_->it_start = PFX##_impl_it_start; \ + _stack_->it_end = PFX##_impl_it_end; \ + \ + _stack_->alloc = alloc; \ + _stack_->callbacks = NULL; \ + \ + return _stack_; \ + } \ + \ + struct SNAME *PFX##_new_custom(size_t capacity, \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_stack *callbacks) \ + { \ + if (capacity < 1) \ + return NULL; \ + \ + if (!alloc) \ + alloc = &cmc_alloc_node_default; \ + \ + struct SNAME *_stack_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_stack_) \ + return NULL; \ + \ + _stack_->buffer = alloc->calloc(capacity, sizeof(V)); \ + \ + if (!_stack_->buffer) \ + { \ + alloc->free(_stack_); \ + return NULL; \ + } \ + \ + _stack_->capacity = capacity; \ + _stack_->count = 0; \ + \ + _stack_->it_start = PFX##_impl_it_start; \ + _stack_->it_end = PFX##_impl_it_end; \ + \ + _stack_->alloc = alloc; \ + _stack_->callbacks = callbacks; \ + \ + return _stack_; \ + } \ + \ + void PFX##_clear(struct 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(struct SNAME *_stack_, void (*deallocator)(V)) \ + { \ + _stack_->alloc->free(_stack_->buffer); \ + \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _stack_->count; i++) \ + deallocator(_stack_->buffer[i]); \ + } \ + \ + _stack_->alloc->free(_stack_); \ + } \ + \ + void PFX##_customize(struct SNAME *_stack_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_stack *callbacks) \ + { \ + if (alloc) \ + _stack_->alloc = alloc; \ + \ + if (callbacks) \ + _stack_->callbacks = callbacks; \ + } \ + \ + bool PFX##_push(struct SNAME *_stack_, V element) \ + { \ + if (PFX##_full(_stack_)) \ + { \ + if (!PFX##_resize(_stack_, PFX##_capacity(_stack_) * 2)) \ + return false; \ + } \ + \ + _stack_->buffer[_stack_->count++] = element; \ + \ + return true; \ + } \ + \ + bool PFX##_pop(struct SNAME *_stack_) \ + { \ + if (PFX##_empty(_stack_)) \ + return false; \ + \ + _stack_->buffer[--_stack_->count] = (V){ 0 }; \ + \ + return true; \ + } \ + \ + V PFX##_top(struct SNAME *_stack_) \ + { \ + if (PFX##_empty(_stack_)) \ + return (V){ 0 }; \ + \ + return _stack_->buffer[_stack_->count - 1]; \ + } \ + \ + bool PFX##_contains(struct 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(struct SNAME *_stack_) \ + { \ + return _stack_->count == 0; \ + } \ + \ + bool PFX##_full(struct SNAME *_stack_) \ + { \ + return _stack_->count >= _stack_->capacity; \ + } \ + \ + size_t PFX##_count(struct SNAME *_stack_) \ + { \ + return _stack_->count; \ + } \ + \ + size_t PFX##_capacity(struct SNAME *_stack_) \ + { \ + return _stack_->capacity; \ + } \ + \ + bool PFX##_resize(struct SNAME *_stack_, size_t capacity) \ + { \ + if (PFX##_capacity(_stack_) == capacity) \ + return true; \ + \ + if (capacity < PFX##_count(_stack_)) \ + return false; \ + \ + V *new_buffer = \ + _stack_->alloc->realloc(_stack_->buffer, sizeof(V) * capacity); \ + \ + if (!new_buffer) \ + return false; \ + \ + _stack_->buffer = new_buffer; \ + _stack_->capacity = capacity; \ + \ + return true; \ + } \ + \ + struct SNAME *PFX##_copy_of(struct SNAME *_stack_, V (*copy_func)(V)) \ + { \ + struct 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(struct SNAME *_stack1_, struct 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; \ + } \ + \ + struct cmc_string PFX##_to_string(struct SNAME *_stack_) \ + { \ + struct cmc_string str; \ + struct SNAME *s_ = _stack_; \ + \ + int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_stack, #SNAME, \ + #V, s_, s_->buffer, s_->capacity, s_->count, \ + s_->alloc, s_->callbacks); \ + \ + if (n < 0 || n == (int)cmc_string_len) \ + return (struct cmc_string){ 0 }; \ + \ + str.s[n] = '\0'; \ + \ + return str; \ + } \ + \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ + { \ + struct SNAME##_iter *iter = \ + target->alloc->malloc(sizeof(struct SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + void PFX##_iter_free(struct SNAME##_iter *iter) \ + { \ + iter->target->alloc->free(iter); \ + } \ + \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct 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(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + bool PFX##_iter_end(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + void PFX##_iter_to_start(struct 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(struct SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = 0; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + } \ + } \ + \ + bool PFX##_iter_next(struct 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(struct 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(struct 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(struct 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(struct 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(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return (V){ 0 }; \ + \ + return iter->target->buffer[iter->cursor]; \ + } \ + \ + V *PFX##_iter_rvalue(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return NULL; \ + \ + return &(iter->target->buffer[iter->cursor]); \ + } \ + \ + size_t PFX##_iter_index(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return 0; \ + \ + return iter->target->count - 1 - iter->cursor; \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_stack_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _stack_); \ + PFX##_iter_to_start(&iter); \ + \ + return iter; \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_stack_) \ + { \ + struct 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 8090420..316cb74 100644 --- a/src/cmc/treemap.h +++ b/src/cmc/treemap.h @@ -21,13 +21,13 @@ #include #include -#include #include +#include #include -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Core functionalities of the C Macro Collections Library - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ #ifndef CMC_CORE_H #define CMC_CORE_H @@ -46,7 +46,8 @@ static const size_t cmc_string_len = 400; /** * struct cmc_alloc_node * - * Custom allocation node. Allows collections to use custom allocation functions. + * Custom allocation node. Allows collections to use custom allocation + * functions. */ struct cmc_alloc_node { @@ -56,13 +57,14 @@ struct cmc_alloc_node void (*free)(void *); }; -static struct cmc_alloc_node cmc_alloc_node_default = {malloc, calloc, realloc, free}; +static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, + free }; #endif /* CMC_CORE_H */ -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * TreeMap specific - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ /* to_string format */ static const char *cmc_string_fmt_treemap = "struct %s<%s, %s> " "at %p { " @@ -97,1030 +99,1043 @@ struct cmc_callbacks_treemap #define CMC_WRAPGEN_TREEMAP_SOURCE(PFX, SNAME, K, V) \ CMC_GENERATE_TREEMAP_SOURCE(PFX, SNAME, K, V) -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Header - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_TREEMAP_HEADER(PFX, SNAME, K, V) \ - \ - /* Treemap Structure */ \ - struct SNAME \ - { \ - /* Root node */ \ - struct SNAME##_node *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 (*it_start)(struct SNAME *); \ - \ - /* Function that returns an iterator to the end of the treemap */ \ - struct SNAME##_iter (*it_end)(struct SNAME *); \ - \ - /* Custom allocation functions */ \ - struct cmc_alloc_node *alloc; \ - \ - /* Custom callback functions */ \ - struct cmc_callbacks_treemap *callbacks; \ - }; \ - \ - /* Treemap Node */ \ - struct SNAME##_node \ - { \ - /* 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 *right; \ - \ - /* Left child node or subtree */ \ - struct SNAME##_node *left; \ - \ - /* Parent node */ \ - struct SNAME##_node *parent; \ - }; \ - \ - /* Treemap Iterator */ \ - struct SNAME##_iter \ - { \ - /* Target treemap */ \ - struct SNAME *target; \ - \ - /* Cursor's current node */ \ - struct SNAME##_node *cursor; \ - \ - /* The first node in the iteration */ \ - struct SNAME##_node *first; \ - \ - /* The last node in the iteration */ \ - struct SNAME##_node *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; \ - }; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - struct SNAME *PFX##_new(int (*compare)(K, K)); \ - struct SNAME *PFX##_new_custom(int (*compare)(K, K), struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_treemap *callbacks); \ - void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)); \ - void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)); \ - /* Customization of Allocation and Callbacks */ \ - void PFX##_customize(struct SNAME *_map_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_treemap *callbacks); \ - /* Collection Input and Output */ \ - bool PFX##_insert(struct SNAME *_map_, K key, V value); \ - bool PFX##_update(struct SNAME *_map_, K key, V new_value, V *old_value); \ - bool PFX##_remove(struct SNAME *_map_, K key, V *out_value); \ - /* Element Access */ \ - bool PFX##_max(struct SNAME *_map_, K *key, V *value); \ - bool PFX##_min(struct SNAME *_map_, K *key, V *value); \ - V PFX##_get(struct SNAME *_map_, K key); \ - V *PFX##_get_ref(struct SNAME *_map_, K key); \ - /* Collection State */ \ - bool PFX##_contains(struct SNAME *_map_, K key); \ - bool PFX##_empty(struct SNAME *_map_); \ - size_t PFX##_count(struct SNAME *_map_); \ - /* Collection Utility */ \ - struct SNAME *PFX##_copy_of(struct SNAME *_map_, K (*key_copy_func)(K), \ - V (*value_copy_func)(V)); \ - bool PFX##_equals(struct SNAME *_map1_, struct SNAME *_map2_, int (*value_comparator)(V, V)); \ - struct cmc_string PFX##_to_string(struct SNAME *_map_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ - void PFX##_iter_free(struct SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(struct SNAME##_iter *iter); \ - bool PFX##_iter_end(struct SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(struct SNAME##_iter *iter); \ - void PFX##_iter_to_end(struct SNAME##_iter *iter); \ - bool PFX##_iter_next(struct SNAME##_iter *iter); \ - bool PFX##_iter_prev(struct SNAME##_iter *iter); \ - bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - K PFX##_iter_key(struct SNAME##_iter *iter); \ - V PFX##_iter_value(struct SNAME##_iter *iter); \ - V *PFX##_iter_rvalue(struct SNAME##_iter *iter); \ + * ------------------------------------------------------------------------- */ +#define CMC_GENERATE_TREEMAP_HEADER(PFX, SNAME, K, V) \ + \ + /* Treemap Structure */ \ + struct SNAME \ + { \ + /* Root node */ \ + struct SNAME##_node *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 (*it_start)(struct SNAME *); \ + \ + /* Function that returns an iterator to the end of the treemap */ \ + struct SNAME##_iter (*it_end)(struct SNAME *); \ + \ + /* Custom allocation functions */ \ + struct cmc_alloc_node *alloc; \ + \ + /* Custom callback functions */ \ + struct cmc_callbacks_treemap *callbacks; \ + }; \ + \ + /* Treemap Node */ \ + struct SNAME##_node \ + { \ + /* 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 *right; \ + \ + /* Left child node or subtree */ \ + struct SNAME##_node *left; \ + \ + /* Parent node */ \ + struct SNAME##_node *parent; \ + }; \ + \ + /* Treemap Iterator */ \ + struct SNAME##_iter \ + { \ + /* Target treemap */ \ + struct SNAME *target; \ + \ + /* Cursor's current node */ \ + struct SNAME##_node *cursor; \ + \ + /* The first node in the iteration */ \ + struct SNAME##_node *first; \ + \ + /* The last node in the iteration */ \ + struct SNAME##_node *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; \ + }; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + struct SNAME *PFX##_new(int (*compare)(K, K)); \ + struct SNAME *PFX##_new_custom(int (*compare)(K, K), \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_treemap *callbacks); \ + void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)); \ + void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)); \ + /* Customization of Allocation and Callbacks */ \ + void PFX##_customize(struct SNAME *_map_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_treemap *callbacks); \ + /* Collection Input and Output */ \ + bool PFX##_insert(struct SNAME *_map_, K key, V value); \ + bool PFX##_update(struct SNAME *_map_, K key, V new_value, V *old_value); \ + bool PFX##_remove(struct SNAME *_map_, K key, V *out_value); \ + /* Element Access */ \ + bool PFX##_max(struct SNAME *_map_, K *key, V *value); \ + bool PFX##_min(struct SNAME *_map_, K *key, V *value); \ + V PFX##_get(struct SNAME *_map_, K key); \ + V *PFX##_get_ref(struct SNAME *_map_, K key); \ + /* Collection State */ \ + bool PFX##_contains(struct SNAME *_map_, K key); \ + bool PFX##_empty(struct SNAME *_map_); \ + size_t PFX##_count(struct SNAME *_map_); \ + /* Collection Utility */ \ + struct SNAME *PFX##_copy_of(struct SNAME *_map_, K (*key_copy_func)(K), \ + V (*value_copy_func)(V)); \ + bool PFX##_equals(struct SNAME *_map1_, struct SNAME *_map2_, \ + int (*value_comparator)(V, V)); \ + struct cmc_string PFX##_to_string(struct SNAME *_map_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ + void PFX##_iter_free(struct SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(struct SNAME##_iter *iter); \ + bool PFX##_iter_end(struct SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(struct SNAME##_iter *iter); \ + void PFX##_iter_to_end(struct SNAME##_iter *iter); \ + bool PFX##_iter_next(struct SNAME##_iter *iter); \ + bool PFX##_iter_prev(struct SNAME##_iter *iter); \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + K PFX##_iter_key(struct SNAME##_iter *iter); \ + V PFX##_iter_value(struct SNAME##_iter *iter); \ + V *PFX##_iter_rvalue(struct SNAME##_iter *iter); \ size_t PFX##_iter_index(struct SNAME##_iter *iter); -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Source - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_TREEMAP_SOURCE(PFX, SNAME, K, V) \ - \ - /* Implementation Detail Functions */ \ - static struct SNAME##_node *PFX##_impl_new_node(K key, V value); \ - static struct SNAME##_node *PFX##_impl_get_node(struct SNAME *_map_, K key); \ - static unsigned char PFX##_impl_h(struct SNAME##_node *node); \ - static unsigned char PFX##_impl_hupdate(struct SNAME##_node *node); \ - static void PFX##_impl_rotate_right(struct SNAME##_node **Z); \ - static void PFX##_impl_rotate_left(struct SNAME##_node **Z); \ - static void PFX##_impl_rebalance(struct SNAME *_map_, struct SNAME##_node *node); \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_map_); \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_map_); \ - \ - struct SNAME *PFX##_new(int (*compare)(K, K)) \ - { \ - struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ - \ - struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_map_) \ - return NULL; \ - \ - _map_->count = 0; \ - _map_->root = NULL; \ - _map_->cmp = compare; \ - \ - _map_->it_start = PFX##_impl_it_start; \ - _map_->it_end = PFX##_impl_it_end; \ - \ - _map_->alloc = alloc; \ - _map_->callbacks = NULL; \ - \ - return _map_; \ - } \ - \ - struct SNAME *PFX##_new_custom(int (*compare)(K, K), struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_treemap *callbacks) \ - { \ - if (!alloc) \ - alloc = &cmc_alloc_node_default; \ - \ - struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_map_) \ - return NULL; \ - \ - _map_->count = 0; \ - _map_->root = NULL; \ - _map_->cmp = compare; \ - \ - _map_->it_start = PFX##_impl_it_start; \ - _map_->it_end = PFX##_impl_it_end; \ - \ - _map_->alloc = alloc; \ - _map_->callbacks = callbacks; \ - \ - return _map_; \ - } \ - \ - void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - struct SNAME##_node *scan = _map_->root; \ - struct SNAME##_node *up = NULL; \ - \ - while (scan != NULL) \ - { \ - if (scan->left != NULL) \ - { \ - struct SNAME##_node *left = scan->left; \ - \ - scan->left = up; \ - up = scan; \ - scan = left; \ - } \ - else if (scan->right != NULL) \ - { \ - struct SNAME##_node *right = scan->right; \ - \ - scan->left = up; \ - scan->right = NULL; \ - up = scan; \ - scan = right; \ - } \ - else \ - { \ - if (up == NULL) \ - { \ - if (deallocator) \ - deallocator(scan->key, scan->value); \ - \ - free(scan); \ - scan = NULL; \ - } \ - \ - while (up != NULL) \ - { \ - if (deallocator) \ - deallocator(scan->key, scan->value); \ - \ - free(scan); \ - \ - if (up->right != NULL) \ - { \ - scan = up->right; \ - up->right = NULL; \ - break; \ - } \ - else \ - { \ - scan = up; \ - up = up->left; \ - } \ - } \ - } \ - } \ - \ - _map_->count = 0; \ - _map_->root = NULL; \ - } \ - \ - void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - PFX##_clear(_map_, deallocator); \ - \ - free(_map_); \ - } \ - \ - bool PFX##_insert(struct SNAME *_map_, K key, V value) \ - { \ - if (PFX##_empty(_map_)) \ - { \ - _map_->root = PFX##_impl_new_node(key, value); \ - \ - if (!_map_->root) \ - return false; \ - } \ - else \ - { \ - struct SNAME##_node *scan = _map_->root; \ - struct SNAME##_node *parent = scan; \ - \ - while (scan != NULL) \ - { \ - parent = scan; \ - \ - if (_map_->cmp(scan->key, key) > 0) \ - scan = scan->left; \ - else if (_map_->cmp(scan->key, key) < 0) \ - scan = scan->right; \ - else \ - return false; \ - } \ - \ - struct SNAME##_node *node; \ - \ - if (_map_->cmp(parent->key, key) > 0) \ - { \ - parent->left = PFX##_impl_new_node(key, value); \ - \ - if (!parent->left) \ - return false; \ - \ - parent->left->parent = parent; \ - node = parent->left; \ - } \ - else \ - { \ - parent->right = PFX##_impl_new_node(key, value); \ - \ - if (!parent->right) \ - return false; \ - \ - parent->right->parent = parent; \ - node = parent->right; \ - } \ - \ - PFX##_impl_rebalance(_map_, node); \ - } \ - \ - _map_->count++; \ - \ - return true; \ - } \ - \ - bool PFX##_update(struct SNAME *_map_, K key, V new_value, V *old_value) \ - { \ - struct SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ - \ - if (!node) \ - return false; \ - \ - if (old_value) \ - *old_value = node->value; \ - \ - node->value = new_value; \ - \ - return true; \ - } \ - \ - bool PFX##_remove(struct SNAME *_map_, K key, V *out_value) \ - { \ - struct SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ - \ - if (!node) \ - return false; \ - \ - if (out_value) \ - *out_value = node->value; \ - \ - struct SNAME##_node *temp = NULL, *unbalanced = NULL; \ - \ - bool is_root = node->parent == NULL; \ - \ - if (node->left == NULL && node->right == NULL) \ - { \ - if (is_root) \ - _map_->root = NULL; \ - else \ - { \ - unbalanced = node->parent; \ - \ - if (node->parent->right == node) \ - node->parent->right = NULL; \ - else \ - node->parent->left = NULL; \ - } \ - \ - free(node); \ - } \ - else if (node->left == NULL) \ - { \ - if (is_root) \ - { \ - _map_->root = node->right; \ - _map_->root->parent = NULL; \ - } \ - else \ - { \ - unbalanced = node->parent; \ - \ - node->right->parent = node->parent; \ - \ - if (node->parent->right == node) \ - node->parent->right = node->right; \ - else \ - node->parent->left = node->right; \ - } \ - \ - free(node); \ - } \ - else if (node->right == NULL) \ - { \ - if (is_root) \ - { \ - _map_->root = node->left; \ - _map_->root->parent = NULL; \ - } \ - else \ - { \ - unbalanced = node->parent; \ - \ - node->left->parent = node->parent; \ - \ - if (node->parent->right == node) \ - node->parent->right = node->left; \ - else \ - node->parent->left = node->left; \ - } \ - \ - free(node); \ - } \ - else \ - { \ - temp = node->right; \ - while (temp->left != NULL) \ - temp = temp->left; \ - \ - K temp_key = temp->key; \ - V temp_val = temp->value; \ - \ - unbalanced = temp->parent; \ - \ - if (temp->left == NULL && temp->right == NULL) \ - { \ - if (temp->parent->right == temp) \ - temp->parent->right = NULL; \ - else \ - temp->parent->left = NULL; \ - } \ - else if (temp->left == NULL) \ - { \ - temp->right->parent = temp->parent; \ - \ - if (temp->parent->right == temp) \ - temp->parent->right = temp->right; \ - else \ - temp->parent->left = temp->right; \ - } \ - else if (temp->right == NULL) \ - { \ - temp->left->parent = temp->parent; \ - \ - if (temp->parent->right == temp) \ - temp->parent->right = temp->left; \ - else \ - temp->parent->left = temp->left; \ - } \ - \ - free(temp); \ - \ - node->key = temp_key; \ - node->value = temp_val; \ - } \ - \ - if (unbalanced != NULL) \ - PFX##_impl_rebalance(_map_, unbalanced); \ - \ - _map_->count--; \ - \ - if (_map_->count == 0) \ - _map_->root = NULL; \ - \ - return true; \ - } \ - \ - bool PFX##_max(struct SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - struct SNAME##_node *scan = _map_->root; \ - \ - while (scan->right != NULL) \ - scan = scan->right; \ - \ - *key = scan->key; \ - *value = scan->value; \ - \ - return true; \ - } \ - \ - bool PFX##_min(struct SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - struct SNAME##_node *scan = _map_->root; \ - \ - while (scan->left != NULL) \ - scan = scan->left; \ - \ - *key = scan->key; \ - *value = scan->value; \ - \ - return true; \ - } \ - \ - V PFX##_get(struct SNAME *_map_, K key) \ - { \ - struct SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ - \ - if (!node) \ - return (V){0}; \ - \ - return node->value; \ - } \ - \ - V *PFX##_get_ref(struct SNAME *_map_, K key) \ - { \ - struct SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ - \ - if (!node) \ - return NULL; \ - \ - return &(node->value); \ - } \ - \ - bool PFX##_contains(struct SNAME *_map_, K key) \ - { \ - struct SNAME##_node *scan = _map_->root; \ - \ - while (scan != NULL) \ - { \ - if (_map_->cmp(scan->key, key) > 0) \ - scan = scan->left; \ - else if (_map_->cmp(scan->key, key) < 0) \ - scan = scan->right; \ - else \ - return true; \ - } \ - \ - return false; \ - } \ - \ - bool PFX##_empty(struct SNAME *_map_) \ - { \ - return _map_->count == 0; \ - } \ - \ - size_t PFX##_count(struct SNAME *_map_) \ - { \ - return _map_->count; \ - } \ - \ - struct SNAME *PFX##_copy_of(struct SNAME *_map_, K (*key_copy_func)(K), \ - V (*value_copy_func)(V)) \ - { \ - struct SNAME *result = PFX##_new(_map_->cmp); \ - \ - if (!result) \ - return NULL; \ - \ - struct 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(struct SNAME *_map1_, struct SNAME *_map2_, int (*value_comparator)(V, V)) \ - { \ - if (PFX##_count(_map1_) != PFX##_count(_map2_)) \ - return false; \ - \ - struct SNAME##_iter iter; \ - PFX##_iter_init(&iter, _map1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - struct SNAME##_node *node = PFX##_impl_get_node(_map2_, PFX##_iter_key(&iter)); \ - \ - if (node == NULL) \ - return false; \ - \ - if (value_comparator) \ - { \ - if (value_comparator(node->value, PFX##_iter_value(&iter)) != 0) \ - return false; \ - } \ - } \ - \ - return true; \ - } \ - \ - struct cmc_string PFX##_to_string(struct SNAME *_map_) \ - { \ - struct cmc_string str; \ - struct SNAME *m_ = _map_; \ - \ - int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_treemap, \ - #SNAME, #K, #V, m_, m_->root, m_->count, m_->cmp, \ - m_->alloc, m_->callbacks); \ - \ - if (n < 0 || n == (int)cmc_string_len) \ - return (struct cmc_string){0}; \ - \ - str.s[n] = '\0'; \ - \ - return str; \ - } \ - \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ - { \ - struct SNAME##_iter *iter = malloc(sizeof(struct SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(struct SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ - { \ - memset(iter, 0, sizeof(struct SNAME##_iter)); \ - \ - iter->target = target; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - \ - iter->cursor = target->root; \ - \ - if (!PFX##_empty(target)) \ - { \ - while (iter->cursor->left != NULL) \ - iter->cursor = iter->cursor->left; \ - \ - iter->first = iter->cursor; \ - \ - iter->last = target->root; \ - while (iter->last->right != NULL) \ - iter->last = iter->last->right; \ - } \ - } \ - \ - bool PFX##_iter_start(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(struct SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - iter->cursor = iter->first; \ - } \ - } \ - \ - void PFX##_iter_to_end(struct SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - iter->cursor = iter->last; \ - } \ - } \ - \ - bool PFX##_iter_next(struct SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->cursor == iter->last) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - if (iter->cursor->right != NULL) \ - { \ - iter->cursor = iter->cursor->right; \ - \ - while (iter->cursor->left != NULL) \ - iter->cursor = iter->cursor->left; \ - \ - iter->index++; \ - \ - return true; \ - } \ - \ - while (true) \ - { \ - if (iter->cursor->parent->left == iter->cursor) \ - { \ - iter->cursor = iter->cursor->parent; \ - \ - iter->index++; \ - \ - return true; \ - } \ - \ - iter->cursor = iter->cursor->parent; \ - } \ - } \ - \ - bool PFX##_iter_prev(struct SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->cursor == iter->first) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - if (iter->cursor->left != NULL) \ - { \ - iter->cursor = iter->cursor->left; \ - \ - while (iter->cursor->right != NULL) \ - iter->cursor = iter->cursor->right; \ - \ - iter->index--; \ - \ - return true; \ - } \ - \ - while (true) \ - { \ - if (iter->cursor->parent->right == iter->cursor) \ - { \ - iter->cursor = iter->cursor->parent; \ - \ - iter->index--; \ - \ - return true; \ - } \ - \ - iter->cursor = iter->cursor->parent; \ - } \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->cursor == iter->last) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ - return false; \ - \ - iter->index += steps; \ - \ - 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(struct SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->cursor == iter->first) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index < steps) \ - return false; \ - \ - iter->index -= steps; \ - \ - 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(struct 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(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (K){0}; \ - \ - return iter->cursor->key; \ - } \ - \ - V PFX##_iter_value(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){0}; \ - \ - return iter->cursor->value; \ - } \ - \ - V *PFX##_iter_rvalue(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->cursor->value); \ - } \ - \ - size_t PFX##_iter_index(struct SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - static struct SNAME##_node *PFX##_impl_new_node(K key, V value) \ - { \ - struct SNAME##_node *node = malloc(sizeof(struct SNAME##_node)); \ - \ - if (!node) \ - return NULL; \ - \ - node->key = key; \ - node->value = value; \ - node->right = NULL; \ - node->left = NULL; \ - node->parent = NULL; \ - node->height = 0; \ - \ - return node; \ - } \ - \ - static struct SNAME##_node *PFX##_impl_get_node(struct SNAME *_map_, K key) \ - { \ - if (PFX##_empty(_map_)) \ - return NULL; \ - \ - struct SNAME##_node *scan = _map_->root; \ - \ - while (scan != NULL) \ - { \ - if (_map_->cmp(scan->key, key) > 0) \ - scan = scan->left; \ - else if (_map_->cmp(scan->key, key) < 0) \ - scan = scan->right; \ - else \ - return scan; \ - } \ - \ - return NULL; \ - } \ - \ - static unsigned char PFX##_impl_h(struct SNAME##_node *node) \ - { \ - if (node == NULL) \ - return 0; \ - \ - return node->height; \ - } \ - \ - static unsigned char PFX##_impl_hupdate(struct SNAME##_node *node) \ - { \ - if (node == NULL) \ - return 0; \ - \ - unsigned char h_l = PFX##_impl_h(node->left); \ - unsigned char h_r = PFX##_impl_h(node->right); \ - \ - return 1 + (h_l > h_r ? h_l : h_r); \ - } \ - \ - static void PFX##_impl_rotate_right(struct SNAME##_node **Z) \ - { \ - struct SNAME##_node *root = *Z; \ - struct SNAME##_node *new_root = root->left; \ - \ - if (root->parent != NULL) \ - { \ - if (root->parent->left == root) \ - root->parent->left = new_root; \ - else \ - root->parent->right = new_root; \ - } \ - \ - new_root->parent = root->parent; \ - \ - root->parent = new_root; \ - root->left = new_root->right; \ - \ - if (root->left) \ - root->left->parent = root; \ - \ - new_root->right = root; \ - \ - root->height = PFX##_impl_hupdate(root); \ - new_root->height = PFX##_impl_hupdate(new_root); \ - \ - *Z = new_root; \ - } \ - \ - static void PFX##_impl_rotate_left(struct SNAME##_node **Z) \ - { \ - struct SNAME##_node *root = *Z; \ - struct SNAME##_node *new_root = root->right; \ - \ - if (root->parent != NULL) \ - { \ - if (root->parent->right == root) \ - root->parent->right = new_root; \ - else \ - root->parent->left = new_root; \ - } \ - \ - new_root->parent = root->parent; \ - \ - root->parent = new_root; \ - root->right = new_root->left; \ - \ - if (root->right) \ - root->right->parent = root; \ - \ - new_root->left = root; \ - \ - root->height = PFX##_impl_hupdate(root); \ - new_root->height = PFX##_impl_hupdate(new_root); \ - \ - *Z = new_root; \ - } \ - \ - static void PFX##_impl_rebalance(struct SNAME *_map_, struct SNAME##_node *node) \ - { \ - struct SNAME##_node *scan = node, *child = NULL; \ - \ - int balance; \ - bool is_root = false; \ - \ - while (scan != NULL) \ - { \ - if (scan->parent == NULL) \ - is_root = true; \ - \ - scan->height = PFX##_impl_hupdate(scan); \ - balance = PFX##_impl_h(scan->right) - PFX##_impl_h(scan->left); \ - \ - if (balance >= 2) \ - { \ - child = scan->right; \ - \ - if (PFX##_impl_h(child->right) < PFX##_impl_h(child->left)) \ - PFX##_impl_rotate_right(&(scan->right)); \ - \ - PFX##_impl_rotate_left(&scan); \ - } \ - else if (balance <= -2) \ - { \ - child = scan->left; \ - \ - if (PFX##_impl_h(child->left) < PFX##_impl_h(child->right)) \ - PFX##_impl_rotate_left(&(scan->left)); \ - \ - PFX##_impl_rotate_right(&scan); \ - } \ - \ - if (is_root) \ - { \ - _map_->root = scan; \ - is_root = false; \ - } \ - \ - scan = scan->parent; \ - } \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_map_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _map_); \ - \ - return iter; \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_map_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _map_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ + * ------------------------------------------------------------------------- */ +#define CMC_GENERATE_TREEMAP_SOURCE(PFX, SNAME, K, V) \ + \ + /* Implementation Detail Functions */ \ + static struct SNAME##_node *PFX##_impl_new_node(K key, V value); \ + static struct SNAME##_node *PFX##_impl_get_node(struct SNAME *_map_, \ + K key); \ + static unsigned char PFX##_impl_h(struct SNAME##_node *node); \ + static unsigned char PFX##_impl_hupdate(struct SNAME##_node *node); \ + static void PFX##_impl_rotate_right(struct SNAME##_node **Z); \ + static void PFX##_impl_rotate_left(struct SNAME##_node **Z); \ + static void PFX##_impl_rebalance(struct SNAME *_map_, \ + struct SNAME##_node *node); \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_map_); \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_map_); \ + \ + struct SNAME *PFX##_new(int (*compare)(K, K)) \ + { \ + struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ + \ + struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_map_) \ + return NULL; \ + \ + _map_->count = 0; \ + _map_->root = NULL; \ + _map_->cmp = compare; \ + \ + _map_->it_start = PFX##_impl_it_start; \ + _map_->it_end = PFX##_impl_it_end; \ + \ + _map_->alloc = alloc; \ + _map_->callbacks = NULL; \ + \ + return _map_; \ + } \ + \ + struct SNAME *PFX##_new_custom(int (*compare)(K, K), \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_treemap *callbacks) \ + { \ + if (!alloc) \ + alloc = &cmc_alloc_node_default; \ + \ + struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_map_) \ + return NULL; \ + \ + _map_->count = 0; \ + _map_->root = NULL; \ + _map_->cmp = compare; \ + \ + _map_->it_start = PFX##_impl_it_start; \ + _map_->it_end = PFX##_impl_it_end; \ + \ + _map_->alloc = alloc; \ + _map_->callbacks = callbacks; \ + \ + return _map_; \ + } \ + \ + void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)) \ + { \ + struct SNAME##_node *scan = _map_->root; \ + struct SNAME##_node *up = NULL; \ + \ + while (scan != NULL) \ + { \ + if (scan->left != NULL) \ + { \ + struct SNAME##_node *left = scan->left; \ + \ + scan->left = up; \ + up = scan; \ + scan = left; \ + } \ + else if (scan->right != NULL) \ + { \ + struct SNAME##_node *right = scan->right; \ + \ + scan->left = up; \ + scan->right = NULL; \ + up = scan; \ + scan = right; \ + } \ + else \ + { \ + if (up == NULL) \ + { \ + if (deallocator) \ + deallocator(scan->key, scan->value); \ + \ + free(scan); \ + scan = NULL; \ + } \ + \ + while (up != NULL) \ + { \ + if (deallocator) \ + deallocator(scan->key, scan->value); \ + \ + free(scan); \ + \ + if (up->right != NULL) \ + { \ + scan = up->right; \ + up->right = NULL; \ + break; \ + } \ + else \ + { \ + scan = up; \ + up = up->left; \ + } \ + } \ + } \ + } \ + \ + _map_->count = 0; \ + _map_->root = NULL; \ + } \ + \ + void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)) \ + { \ + PFX##_clear(_map_, deallocator); \ + \ + free(_map_); \ + } \ + \ + bool PFX##_insert(struct SNAME *_map_, K key, V value) \ + { \ + if (PFX##_empty(_map_)) \ + { \ + _map_->root = PFX##_impl_new_node(key, value); \ + \ + if (!_map_->root) \ + return false; \ + } \ + else \ + { \ + struct SNAME##_node *scan = _map_->root; \ + struct SNAME##_node *parent = scan; \ + \ + while (scan != NULL) \ + { \ + parent = scan; \ + \ + if (_map_->cmp(scan->key, key) > 0) \ + scan = scan->left; \ + else if (_map_->cmp(scan->key, key) < 0) \ + scan = scan->right; \ + else \ + return false; \ + } \ + \ + struct SNAME##_node *node; \ + \ + if (_map_->cmp(parent->key, key) > 0) \ + { \ + parent->left = PFX##_impl_new_node(key, value); \ + \ + if (!parent->left) \ + return false; \ + \ + parent->left->parent = parent; \ + node = parent->left; \ + } \ + else \ + { \ + parent->right = PFX##_impl_new_node(key, value); \ + \ + if (!parent->right) \ + return false; \ + \ + parent->right->parent = parent; \ + node = parent->right; \ + } \ + \ + PFX##_impl_rebalance(_map_, node); \ + } \ + \ + _map_->count++; \ + \ + return true; \ + } \ + \ + bool PFX##_update(struct SNAME *_map_, K key, V new_value, V *old_value) \ + { \ + struct SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ + \ + if (!node) \ + return false; \ + \ + if (old_value) \ + *old_value = node->value; \ + \ + node->value = new_value; \ + \ + return true; \ + } \ + \ + bool PFX##_remove(struct SNAME *_map_, K key, V *out_value) \ + { \ + struct SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ + \ + if (!node) \ + return false; \ + \ + if (out_value) \ + *out_value = node->value; \ + \ + struct SNAME##_node *temp = NULL, *unbalanced = NULL; \ + \ + bool is_root = node->parent == NULL; \ + \ + if (node->left == NULL && node->right == NULL) \ + { \ + if (is_root) \ + _map_->root = NULL; \ + else \ + { \ + unbalanced = node->parent; \ + \ + if (node->parent->right == node) \ + node->parent->right = NULL; \ + else \ + node->parent->left = NULL; \ + } \ + \ + free(node); \ + } \ + else if (node->left == NULL) \ + { \ + if (is_root) \ + { \ + _map_->root = node->right; \ + _map_->root->parent = NULL; \ + } \ + else \ + { \ + unbalanced = node->parent; \ + \ + node->right->parent = node->parent; \ + \ + if (node->parent->right == node) \ + node->parent->right = node->right; \ + else \ + node->parent->left = node->right; \ + } \ + \ + free(node); \ + } \ + else if (node->right == NULL) \ + { \ + if (is_root) \ + { \ + _map_->root = node->left; \ + _map_->root->parent = NULL; \ + } \ + else \ + { \ + unbalanced = node->parent; \ + \ + node->left->parent = node->parent; \ + \ + if (node->parent->right == node) \ + node->parent->right = node->left; \ + else \ + node->parent->left = node->left; \ + } \ + \ + free(node); \ + } \ + else \ + { \ + temp = node->right; \ + while (temp->left != NULL) \ + temp = temp->left; \ + \ + K temp_key = temp->key; \ + V temp_val = temp->value; \ + \ + unbalanced = temp->parent; \ + \ + if (temp->left == NULL && temp->right == NULL) \ + { \ + if (temp->parent->right == temp) \ + temp->parent->right = NULL; \ + else \ + temp->parent->left = NULL; \ + } \ + else if (temp->left == NULL) \ + { \ + temp->right->parent = temp->parent; \ + \ + if (temp->parent->right == temp) \ + temp->parent->right = temp->right; \ + else \ + temp->parent->left = temp->right; \ + } \ + else if (temp->right == NULL) \ + { \ + temp->left->parent = temp->parent; \ + \ + if (temp->parent->right == temp) \ + temp->parent->right = temp->left; \ + else \ + temp->parent->left = temp->left; \ + } \ + \ + free(temp); \ + \ + node->key = temp_key; \ + node->value = temp_val; \ + } \ + \ + if (unbalanced != NULL) \ + PFX##_impl_rebalance(_map_, unbalanced); \ + \ + _map_->count--; \ + \ + if (_map_->count == 0) \ + _map_->root = NULL; \ + \ + return true; \ + } \ + \ + bool PFX##_max(struct SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + struct SNAME##_node *scan = _map_->root; \ + \ + while (scan->right != NULL) \ + scan = scan->right; \ + \ + *key = scan->key; \ + *value = scan->value; \ + \ + return true; \ + } \ + \ + bool PFX##_min(struct SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + struct SNAME##_node *scan = _map_->root; \ + \ + while (scan->left != NULL) \ + scan = scan->left; \ + \ + *key = scan->key; \ + *value = scan->value; \ + \ + return true; \ + } \ + \ + V PFX##_get(struct SNAME *_map_, K key) \ + { \ + struct SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ + \ + if (!node) \ + return (V){ 0 }; \ + \ + return node->value; \ + } \ + \ + V *PFX##_get_ref(struct SNAME *_map_, K key) \ + { \ + struct SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ + \ + if (!node) \ + return NULL; \ + \ + return &(node->value); \ + } \ + \ + bool PFX##_contains(struct SNAME *_map_, K key) \ + { \ + struct SNAME##_node *scan = _map_->root; \ + \ + while (scan != NULL) \ + { \ + if (_map_->cmp(scan->key, key) > 0) \ + scan = scan->left; \ + else if (_map_->cmp(scan->key, key) < 0) \ + scan = scan->right; \ + else \ + return true; \ + } \ + \ + return false; \ + } \ + \ + bool PFX##_empty(struct SNAME *_map_) \ + { \ + return _map_->count == 0; \ + } \ + \ + size_t PFX##_count(struct SNAME *_map_) \ + { \ + return _map_->count; \ + } \ + \ + struct SNAME *PFX##_copy_of(struct SNAME *_map_, K (*key_copy_func)(K), \ + V (*value_copy_func)(V)) \ + { \ + struct SNAME *result = PFX##_new(_map_->cmp); \ + \ + if (!result) \ + return NULL; \ + \ + struct 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(struct SNAME *_map1_, struct SNAME *_map2_, \ + int (*value_comparator)(V, V)) \ + { \ + if (PFX##_count(_map1_) != PFX##_count(_map2_)) \ + return false; \ + \ + struct SNAME##_iter iter; \ + PFX##_iter_init(&iter, _map1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); \ + PFX##_iter_next(&iter)) \ + { \ + struct SNAME##_node *node = \ + PFX##_impl_get_node(_map2_, PFX##_iter_key(&iter)); \ + \ + if (node == NULL) \ + return false; \ + \ + if (value_comparator) \ + { \ + if (value_comparator(node->value, PFX##_iter_value(&iter)) != \ + 0) \ + return false; \ + } \ + } \ + \ + return true; \ + } \ + \ + struct cmc_string PFX##_to_string(struct SNAME *_map_) \ + { \ + struct cmc_string str; \ + struct SNAME *m_ = _map_; \ + \ + int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_treemap, \ + #SNAME, #K, #V, m_, m_->root, m_->count, m_->cmp, \ + m_->alloc, m_->callbacks); \ + \ + if (n < 0 || n == (int)cmc_string_len) \ + return (struct cmc_string){ 0 }; \ + \ + str.s[n] = '\0'; \ + \ + return str; \ + } \ + \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ + { \ + struct SNAME##_iter *iter = malloc(sizeof(struct SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + void PFX##_iter_free(struct SNAME##_iter *iter) \ + { \ + free(iter); \ + } \ + \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ + { \ + memset(iter, 0, sizeof(struct SNAME##_iter)); \ + \ + iter->target = target; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + \ + iter->cursor = target->root; \ + \ + if (!PFX##_empty(target)) \ + { \ + while (iter->cursor->left != NULL) \ + iter->cursor = iter->cursor->left; \ + \ + iter->first = iter->cursor; \ + \ + iter->last = target->root; \ + while (iter->last->right != NULL) \ + iter->last = iter->last->right; \ + } \ + } \ + \ + bool PFX##_iter_start(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + bool PFX##_iter_end(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + void PFX##_iter_to_start(struct SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + iter->cursor = iter->first; \ + } \ + } \ + \ + void PFX##_iter_to_end(struct SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->index = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + iter->cursor = iter->last; \ + } \ + } \ + \ + bool PFX##_iter_next(struct SNAME##_iter *iter) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->cursor == iter->last) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + if (iter->cursor->right != NULL) \ + { \ + iter->cursor = iter->cursor->right; \ + \ + while (iter->cursor->left != NULL) \ + iter->cursor = iter->cursor->left; \ + \ + iter->index++; \ + \ + return true; \ + } \ + \ + while (true) \ + { \ + if (iter->cursor->parent->left == iter->cursor) \ + { \ + iter->cursor = iter->cursor->parent; \ + \ + iter->index++; \ + \ + return true; \ + } \ + \ + iter->cursor = iter->cursor->parent; \ + } \ + } \ + \ + bool PFX##_iter_prev(struct SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor == iter->first) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + if (iter->cursor->left != NULL) \ + { \ + iter->cursor = iter->cursor->left; \ + \ + while (iter->cursor->right != NULL) \ + iter->cursor = iter->cursor->right; \ + \ + iter->index--; \ + \ + return true; \ + } \ + \ + while (true) \ + { \ + if (iter->cursor->parent->right == iter->cursor) \ + { \ + iter->cursor = iter->cursor->parent; \ + \ + iter->index--; \ + \ + return true; \ + } \ + \ + iter->cursor = iter->cursor->parent; \ + } \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->cursor == iter->last) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ + return false; \ + \ + iter->index += steps; \ + \ + 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(struct SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor == iter->first) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index < steps) \ + return false; \ + \ + iter->index -= steps; \ + \ + 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(struct 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(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return (K){ 0 }; \ + \ + return iter->cursor->key; \ + } \ + \ + V PFX##_iter_value(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return (V){ 0 }; \ + \ + return iter->cursor->value; \ + } \ + \ + V *PFX##_iter_rvalue(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return NULL; \ + \ + return &(iter->cursor->value); \ + } \ + \ + size_t PFX##_iter_index(struct SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + static struct SNAME##_node *PFX##_impl_new_node(K key, V value) \ + { \ + struct SNAME##_node *node = malloc(sizeof(struct SNAME##_node)); \ + \ + if (!node) \ + return NULL; \ + \ + node->key = key; \ + node->value = value; \ + node->right = NULL; \ + node->left = NULL; \ + node->parent = NULL; \ + node->height = 0; \ + \ + return node; \ + } \ + \ + static struct SNAME##_node *PFX##_impl_get_node(struct SNAME *_map_, \ + K key) \ + { \ + if (PFX##_empty(_map_)) \ + return NULL; \ + \ + struct SNAME##_node *scan = _map_->root; \ + \ + while (scan != NULL) \ + { \ + if (_map_->cmp(scan->key, key) > 0) \ + scan = scan->left; \ + else if (_map_->cmp(scan->key, key) < 0) \ + scan = scan->right; \ + else \ + return scan; \ + } \ + \ + return NULL; \ + } \ + \ + static unsigned char PFX##_impl_h(struct SNAME##_node *node) \ + { \ + if (node == NULL) \ + return 0; \ + \ + return node->height; \ + } \ + \ + static unsigned char PFX##_impl_hupdate(struct SNAME##_node *node) \ + { \ + if (node == NULL) \ + return 0; \ + \ + unsigned char h_l = PFX##_impl_h(node->left); \ + unsigned char h_r = PFX##_impl_h(node->right); \ + \ + return 1 + (h_l > h_r ? h_l : h_r); \ + } \ + \ + static void PFX##_impl_rotate_right(struct SNAME##_node **Z) \ + { \ + struct SNAME##_node *root = *Z; \ + struct SNAME##_node *new_root = root->left; \ + \ + if (root->parent != NULL) \ + { \ + if (root->parent->left == root) \ + root->parent->left = new_root; \ + else \ + root->parent->right = new_root; \ + } \ + \ + new_root->parent = root->parent; \ + \ + root->parent = new_root; \ + root->left = new_root->right; \ + \ + if (root->left) \ + root->left->parent = root; \ + \ + new_root->right = root; \ + \ + root->height = PFX##_impl_hupdate(root); \ + new_root->height = PFX##_impl_hupdate(new_root); \ + \ + *Z = new_root; \ + } \ + \ + static void PFX##_impl_rotate_left(struct SNAME##_node **Z) \ + { \ + struct SNAME##_node *root = *Z; \ + struct SNAME##_node *new_root = root->right; \ + \ + if (root->parent != NULL) \ + { \ + if (root->parent->right == root) \ + root->parent->right = new_root; \ + else \ + root->parent->left = new_root; \ + } \ + \ + new_root->parent = root->parent; \ + \ + root->parent = new_root; \ + root->right = new_root->left; \ + \ + if (root->right) \ + root->right->parent = root; \ + \ + new_root->left = root; \ + \ + root->height = PFX##_impl_hupdate(root); \ + new_root->height = PFX##_impl_hupdate(new_root); \ + \ + *Z = new_root; \ + } \ + \ + static void PFX##_impl_rebalance(struct SNAME *_map_, \ + struct SNAME##_node *node) \ + { \ + struct SNAME##_node *scan = node, *child = NULL; \ + \ + int balance; \ + bool is_root = false; \ + \ + while (scan != NULL) \ + { \ + if (scan->parent == NULL) \ + is_root = true; \ + \ + scan->height = PFX##_impl_hupdate(scan); \ + balance = PFX##_impl_h(scan->right) - PFX##_impl_h(scan->left); \ + \ + if (balance >= 2) \ + { \ + child = scan->right; \ + \ + if (PFX##_impl_h(child->right) < PFX##_impl_h(child->left)) \ + PFX##_impl_rotate_right(&(scan->right)); \ + \ + PFX##_impl_rotate_left(&scan); \ + } \ + else if (balance <= -2) \ + { \ + child = scan->left; \ + \ + if (PFX##_impl_h(child->left) < PFX##_impl_h(child->right)) \ + PFX##_impl_rotate_left(&(scan->left)); \ + \ + PFX##_impl_rotate_right(&scan); \ + } \ + \ + if (is_root) \ + { \ + _map_->root = scan; \ + is_root = false; \ + } \ + \ + scan = scan->parent; \ + } \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_map_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _map_); \ + \ + return iter; \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_map_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _map_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_TREEMAP_H */ diff --git a/src/cmc/treeset.h b/src/cmc/treeset.h index 294ed53..20ac037 100644 --- a/src/cmc/treeset.h +++ b/src/cmc/treeset.h @@ -21,13 +21,13 @@ #include #include -#include #include +#include #include -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Core functionalities of the C Macro Collections Library - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ #ifndef CMC_CORE_H #define CMC_CORE_H @@ -46,7 +46,8 @@ static const size_t cmc_string_len = 400; /** * struct cmc_alloc_node * - * Custom allocation node. Allows collections to use custom allocation functions. + * Custom allocation node. Allows collections to use custom allocation + * functions. */ struct cmc_alloc_node { @@ -56,13 +57,14 @@ struct cmc_alloc_node void (*free)(void *); }; -static struct cmc_alloc_node cmc_alloc_node_default = {malloc, calloc, realloc, free}; +static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc, realloc, + free }; #endif /* CMC_CORE_H */ -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * TreeSet specific - ------------------------------------------------------------------------------------------------ */ + * ------------------------------------------------------------------------- */ /* to_string format */ static const char *cmc_string_fmt_treeset = "struct %s<%s> " "at %p { " @@ -97,1174 +99,1200 @@ struct cmc_callbacks_treeset #define CMC_WRAPGEN_TREESET_SOURCE(PFX, SNAME, K, V) \ CMC_GENERATE_TREESET_SOURCE(PFX, SNAME, V) -/* ------------------------------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- * Header - ------------------------------------------------------------------------------------------------ */ -#define CMC_GENERATE_TREESET_HEADER(PFX, SNAME, V) \ - \ - /* Treeset Structure */ \ - struct SNAME \ - { \ - /* Root node */ \ - struct SNAME##_node *root; \ - \ - /* Current amount of elements */ \ - size_t count; \ - \ - /* Element comparison function */ \ - int (*cmp)(V, V); \ - \ - /* Function that returns an iterator to the start of the treeset */ \ - struct SNAME##_iter (*it_start)(struct SNAME *); \ - \ - /* Function that returns an iterator to the end of the treeset */ \ - struct SNAME##_iter (*it_end)(struct SNAME *); \ - \ - /* Custom allocation functions */ \ - struct cmc_alloc_node *alloc; \ - \ - /* Custom callback functions */ \ - struct cmc_callbacks_treeset *callbacks; \ - }; \ - \ - /* Treeset Node */ \ - struct SNAME##_node \ - { \ - /* Node element */ \ - 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 *right; \ - \ - /* Left child node or subtree */ \ - struct SNAME##_node *left; \ - \ - /* Parent node */ \ - struct SNAME##_node *parent; \ - }; \ - \ - /* Treeset Iterator */ \ - struct SNAME##_iter \ - { \ - /* Target treeset */ \ - struct SNAME *target; \ - \ - /* Cursor's current node */ \ - struct SNAME##_node *cursor; \ - \ - /* The first node in the iteration */ \ - struct SNAME##_node *first; \ - \ - /* The last node in the iteration */ \ - struct SNAME##_node *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; \ - }; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - struct SNAME *PFX##_new(int (*compare)(V, V)); \ - struct SNAME *PFX##_new_custom(int (*compare)(V, V), struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_treeset *callbacks); \ - void PFX##_clear(struct SNAME *_set_, void (*deallocator)(V)); \ - void PFX##_free(struct SNAME *_set_, void (*deallocator)(V)); \ - /* Customization of Allocation and Callbacks */ \ - void PFX##_customize(struct SNAME *_set_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_treeset *callbacks); \ - /* Collection Input and Output */ \ - bool PFX##_insert(struct SNAME *_set_, V element); \ - bool PFX##_remove(struct SNAME *_set_, V element); \ - /* Element Access */ \ - bool PFX##_max(struct SNAME *_set_, V *value); \ - bool PFX##_min(struct SNAME *_set_, V *value); \ - /* Collection State */ \ - bool PFX##_contains(struct SNAME *_set_, V element); \ - bool PFX##_empty(struct SNAME *_set_); \ - size_t PFX##_count(struct SNAME *_set_); \ - /* Collection Utility */ \ - struct SNAME *PFX##_copy_of(struct SNAME *_set_, V (*copy_func)(V)); \ - bool PFX##_equals(struct SNAME *_set1_, struct SNAME *_set2_); \ - struct cmc_string PFX##_to_string(struct SNAME *_set_); \ - \ - /* Set Operations */ \ - struct SNAME *PFX##_union(struct SNAME *_set1_, struct SNAME *_set2_); \ - struct SNAME *PFX##_intersection(struct SNAME *_set1_, struct SNAME *_set2_); \ - struct SNAME *PFX##_difference(struct SNAME *_set1_, struct SNAME *_set2_); \ - struct SNAME *PFX##_symmetric_difference(struct SNAME *_set1_, struct SNAME *_set2_); \ - bool PFX##_is_subset(struct SNAME *_set1_, struct SNAME *_set2_); \ - bool PFX##_is_superset(struct SNAME *_set1_, struct SNAME *_set2_); \ - bool PFX##_is_proper_subset(struct SNAME *_set1_, struct SNAME *_set2_); \ - bool PFX##_is_proper_superset(struct SNAME *_set1_, struct SNAME *_set2_); \ - bool PFX##_is_disjointset(struct SNAME *_set1_, struct SNAME *_set2_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ - void PFX##_iter_free(struct SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(struct SNAME##_iter *iter); \ - bool PFX##_iter_end(struct SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(struct SNAME##_iter *iter); \ - void PFX##_iter_to_end(struct SNAME##_iter *iter); \ - bool PFX##_iter_next(struct SNAME##_iter *iter); \ - bool PFX##_iter_prev(struct SNAME##_iter *iter); \ - bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - V PFX##_iter_value(struct SNAME##_iter *iter); \ - size_t PFX##_iter_index(struct 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_TREESET_HEADER(PFX, SNAME, V) \ + \ + /* Treeset Structure */ \ + struct SNAME \ + { \ + /* Root node */ \ + struct SNAME##_node *root; \ + \ + /* Current amount of elements */ \ + size_t count; \ + \ + /* Element comparison function */ \ + int (*cmp)(V, V); \ + \ + /* Function that returns an iterator to the start of the treeset */ \ + struct SNAME##_iter (*it_start)(struct SNAME *); \ + \ + /* Function that returns an iterator to the end of the treeset */ \ + struct SNAME##_iter (*it_end)(struct SNAME *); \ + \ + /* Custom allocation functions */ \ + struct cmc_alloc_node *alloc; \ + \ + /* Custom callback functions */ \ + struct cmc_callbacks_treeset *callbacks; \ + }; \ + \ + /* Treeset Node */ \ + struct SNAME##_node \ + { \ + /* Node element */ \ + 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 *right; \ + \ + /* Left child node or subtree */ \ + struct SNAME##_node *left; \ + \ + /* Parent node */ \ + struct SNAME##_node *parent; \ + }; \ + \ + /* Treeset Iterator */ \ + struct SNAME##_iter \ + { \ + /* Target treeset */ \ + struct SNAME *target; \ + \ + /* Cursor's current node */ \ + struct SNAME##_node *cursor; \ + \ + /* The first node in the iteration */ \ + struct SNAME##_node *first; \ + \ + /* The last node in the iteration */ \ + struct SNAME##_node *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; \ + }; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + struct SNAME *PFX##_new(int (*compare)(V, V)); \ + struct SNAME *PFX##_new_custom(int (*compare)(V, V), \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_treeset *callbacks); \ + void PFX##_clear(struct SNAME *_set_, void (*deallocator)(V)); \ + void PFX##_free(struct SNAME *_set_, void (*deallocator)(V)); \ + /* Customization of Allocation and Callbacks */ \ + void PFX##_customize(struct SNAME *_set_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_treeset *callbacks); \ + /* Collection Input and Output */ \ + bool PFX##_insert(struct SNAME *_set_, V element); \ + bool PFX##_remove(struct SNAME *_set_, V element); \ + /* Element Access */ \ + bool PFX##_max(struct SNAME *_set_, V *value); \ + bool PFX##_min(struct SNAME *_set_, V *value); \ + /* Collection State */ \ + bool PFX##_contains(struct SNAME *_set_, V element); \ + bool PFX##_empty(struct SNAME *_set_); \ + size_t PFX##_count(struct SNAME *_set_); \ + /* Collection Utility */ \ + struct SNAME *PFX##_copy_of(struct SNAME *_set_, V (*copy_func)(V)); \ + bool PFX##_equals(struct SNAME *_set1_, struct SNAME *_set2_); \ + struct cmc_string PFX##_to_string(struct SNAME *_set_); \ + \ + /* Set Operations */ \ + struct SNAME *PFX##_union(struct SNAME *_set1_, struct SNAME *_set2_); \ + struct SNAME *PFX##_intersection(struct SNAME *_set1_, \ + struct SNAME *_set2_); \ + struct SNAME *PFX##_difference(struct SNAME *_set1_, \ + struct SNAME *_set2_); \ + struct SNAME *PFX##_symmetric_difference(struct SNAME *_set1_, \ + struct SNAME *_set2_); \ + bool PFX##_is_subset(struct SNAME *_set1_, struct SNAME *_set2_); \ + bool PFX##_is_superset(struct SNAME *_set1_, struct SNAME *_set2_); \ + bool PFX##_is_proper_subset(struct SNAME *_set1_, struct SNAME *_set2_); \ + bool PFX##_is_proper_superset(struct SNAME *_set1_, struct SNAME *_set2_); \ + bool PFX##_is_disjointset(struct SNAME *_set1_, struct SNAME *_set2_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ + void PFX##_iter_free(struct SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(struct SNAME##_iter *iter); \ + bool PFX##_iter_end(struct SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(struct SNAME##_iter *iter); \ + void PFX##_iter_to_end(struct SNAME##_iter *iter); \ + bool PFX##_iter_next(struct SNAME##_iter *iter); \ + bool PFX##_iter_prev(struct SNAME##_iter *iter); \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + V PFX##_iter_value(struct SNAME##_iter *iter); \ + size_t PFX##_iter_index(struct 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 CMC_GENERATE_TREESET_SOURCE(PFX, SNAME, V) \ - \ - /* Implementation Detail Functions */ \ - static struct SNAME##_node *PFX##_impl_new_node(V element); \ - static struct SNAME##_node *PFX##_impl_get_node(struct SNAME *_set_, V element); \ - static unsigned char PFX##_impl_h(struct SNAME##_node *node); \ - static unsigned char PFX##_impl_hupdate(struct SNAME##_node *node); \ - static void PFX##_impl_rotate_right(struct SNAME##_node **Z); \ - static void PFX##_impl_rotate_left(struct SNAME##_node **Z); \ - static void PFX##_impl_rebalance(struct SNAME *_set_, struct SNAME##_node *node); \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_set_); \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_set_); \ - \ - struct SNAME *PFX##_new(int (*compare)(V, V)) \ - { \ - struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ - \ - struct SNAME *_set_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_set_) \ - return NULL; \ - \ - _set_->count = 0; \ - _set_->root = NULL; \ - _set_->cmp = compare; \ - \ - _set_->it_start = PFX##_impl_it_start; \ - _set_->it_end = PFX##_impl_it_end; \ - \ - _set_->alloc = alloc; \ - _set_->callbacks = NULL; \ - \ - return _set_; \ - } \ - \ - struct SNAME *PFX##_new_custom(int (*compare)(V, V), struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_treeset *callbacks) \ - { \ - if (!alloc) \ - alloc = &cmc_alloc_node_default; \ - \ - struct SNAME *_set_ = alloc->malloc(sizeof(struct SNAME)); \ - \ - if (!_set_) \ - return NULL; \ - \ - _set_->count = 0; \ - _set_->root = NULL; \ - _set_->cmp = compare; \ - \ - _set_->it_start = PFX##_impl_it_start; \ - _set_->it_end = PFX##_impl_it_end; \ - \ - _set_->alloc = alloc; \ - _set_->callbacks = callbacks; \ - \ - return _set_; \ - } \ - \ - void PFX##_clear(struct SNAME *_set_, void (*deallocator)(V)) \ - { \ - struct SNAME##_node *scan = _set_->root; \ - struct SNAME##_node *up = NULL; \ - \ - while (scan != NULL) \ - { \ - if (scan->left != NULL) \ - { \ - struct SNAME##_node *left = scan->left; \ - \ - scan->left = up; \ - up = scan; \ - scan = left; \ - } \ - else if (scan->right != NULL) \ - { \ - struct SNAME##_node *right = scan->right; \ - \ - scan->left = up; \ - scan->right = NULL; \ - up = scan; \ - scan = right; \ - } \ - else \ - { \ - if (up == NULL) \ - { \ - if (deallocator) \ - deallocator(scan->value); \ - \ - free(scan); \ - scan = NULL; \ - } \ - \ - while (up != NULL) \ - { \ - if (deallocator) \ - deallocator(scan->value); \ - \ - free(scan); \ - \ - if (up->right != NULL) \ - { \ - scan = up->right; \ - up->right = NULL; \ - break; \ - } \ - else \ - { \ - scan = up; \ - up = up->left; \ - } \ - } \ - } \ - } \ - \ - _set_->count = 0; \ - _set_->root = NULL; \ - } \ - \ - void PFX##_free(struct SNAME *_set_, void (*deallocator)(V)) \ - { \ - PFX##_clear(_set_, deallocator); \ - \ - free(_set_); \ - } \ - \ - bool PFX##_insert(struct SNAME *_set_, V element) \ - { \ - if (PFX##_empty(_set_)) \ - { \ - _set_->root = PFX##_impl_new_node(element); \ - \ - if (!_set_->root) \ - return false; \ - } \ - else \ - { \ - struct SNAME##_node *scan = _set_->root; \ - struct SNAME##_node *parent = scan; \ - \ - while (scan != NULL) \ - { \ - parent = scan; \ - \ - if (_set_->cmp(scan->value, element) > 0) \ - scan = scan->left; \ - else if (_set_->cmp(scan->value, element) < 0) \ - scan = scan->right; \ - else \ - return false; \ - } \ - \ - struct SNAME##_node *node; \ - \ - if (_set_->cmp(parent->value, element) > 0) \ - { \ - parent->left = PFX##_impl_new_node(element); \ - \ - if (!parent->left) \ - return false; \ - \ - parent->left->parent = parent; \ - node = parent->left; \ - } \ - else \ - { \ - parent->right = PFX##_impl_new_node(element); \ - \ - if (!parent->right) \ - return false; \ - \ - parent->right->parent = parent; \ - node = parent->right; \ - } \ - \ - PFX##_impl_rebalance(_set_, node); \ - } \ - \ - _set_->count++; \ - \ - return true; \ - } \ - \ - bool PFX##_remove(struct SNAME *_set_, V element) \ - { \ - struct SNAME##_node *node = PFX##_impl_get_node(_set_, element); \ - \ - if (!node) \ - return false; \ - \ - struct SNAME##_node *temp = NULL, *unbalanced = NULL; \ - \ - bool is_root = node->parent == NULL; \ - \ - if (node->left == NULL && node->right == NULL) \ - { \ - if (is_root) \ - _set_->root = NULL; \ - else \ - { \ - unbalanced = node->parent; \ - \ - if (node->parent->right == node) \ - node->parent->right = NULL; \ - else \ - node->parent->left = NULL; \ - } \ - \ - free(node); \ - } \ - else if (node->left == NULL) \ - { \ - if (is_root) \ - { \ - _set_->root = node->right; \ - _set_->root->parent = NULL; \ - } \ - else \ - { \ - unbalanced = node->parent; \ - \ - node->right->parent = node->parent; \ - \ - if (node->parent->right == node) \ - node->parent->right = node->right; \ - else \ - node->parent->left = node->right; \ - } \ - \ - free(node); \ - } \ - else if (node->right == NULL) \ - { \ - if (is_root) \ - { \ - _set_->root = node->left; \ - _set_->root->parent = NULL; \ - } \ - else \ - { \ - unbalanced = node->parent; \ - \ - node->left->parent = node->parent; \ - \ - if (node->parent->right == node) \ - node->parent->right = node->left; \ - else \ - node->parent->left = node->left; \ - } \ - \ - free(node); \ - } \ - else \ - { \ - temp = node->right; \ - while (temp->left != NULL) \ - temp = temp->left; \ - \ - V temp_value = temp->value; \ - \ - unbalanced = temp->parent; \ - \ - if (temp->left == NULL && temp->right == NULL) \ - { \ - if (temp->parent->right == temp) \ - temp->parent->right = NULL; \ - else \ - temp->parent->left = NULL; \ - } \ - else if (temp->left == NULL) \ - { \ - temp->right->parent = temp->parent; \ - \ - if (temp->parent->right == temp) \ - temp->parent->right = temp->right; \ - else \ - temp->parent->left = temp->right; \ - } \ - else if (temp->right == NULL) \ - { \ - temp->left->parent = temp->parent; \ - \ - if (temp->parent->right == temp) \ - temp->parent->right = temp->left; \ - else \ - temp->parent->left = temp->left; \ - } \ - \ - free(temp); \ - \ - node->value = temp_value; \ - } \ - \ - if (unbalanced != NULL) \ - PFX##_impl_rebalance(_set_, unbalanced); \ - \ - _set_->count--; \ - \ - if (_set_->count == 0) \ - _set_->root = NULL; \ - \ - return true; \ - } \ - \ - bool PFX##_max(struct SNAME *_set_, V *value) \ - { \ - if (PFX##_empty(_set_)) \ - return false; \ - \ - struct SNAME##_node *scan = _set_->root; \ - \ - while (scan->right != NULL) \ - scan = scan->right; \ - \ - *value = scan->value; \ - \ - return true; \ - } \ - \ - bool PFX##_min(struct SNAME *_set_, V *value) \ - { \ - if (PFX##_empty(_set_)) \ - return false; \ - \ - struct SNAME##_node *scan = _set_->root; \ - \ - while (scan->left != NULL) \ - scan = scan->left; \ - \ - *value = scan->value; \ - \ - return true; \ - } \ - \ - bool PFX##_contains(struct SNAME *_set_, V element) \ - { \ - struct SNAME##_node *scan = _set_->root; \ - \ - while (scan != NULL) \ - { \ - if (_set_->cmp(scan->value, element) > 0) \ - scan = scan->left; \ - else if (_set_->cmp(scan->value, element) < 0) \ - scan = scan->right; \ - else \ - return true; \ - } \ - \ - return false; \ - } \ - \ - bool PFX##_empty(struct SNAME *_set_) \ - { \ - return _set_->count == 0; \ - } \ - \ - size_t PFX##_count(struct SNAME *_set_) \ - { \ - return _set_->count; \ - } \ - \ - struct SNAME *PFX##_copy_of(struct SNAME *_set_, V (*copy_func)(V)) \ - { \ - struct SNAME *result = PFX##_new(_set_->cmp); \ - \ - if (!result) \ - return NULL; \ - \ - struct SNAME##_iter iter; \ - PFX##_iter_init(&iter, _set_); \ - \ - if (!PFX##_empty(_set_)) \ - { \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - if (copy_func) \ - PFX##_insert(result, copy_func(PFX##_iter_value(&iter))); \ - else \ - PFX##_insert(result, PFX##_iter_value(&iter)); \ - } \ - } \ - \ - return result; \ - } \ - \ - bool PFX##_equals(struct SNAME *_set1_, struct SNAME *_set2_) \ - { \ - if (PFX##_count(_set1_) != PFX##_count(_set2_)) \ - return false; \ - \ - struct 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_node(_set2_, PFX##_iter_value(&iter)) == NULL) \ - return false; \ - } \ - \ - return true; \ - } \ - \ - struct cmc_string PFX##_to_string(struct SNAME *_set_) \ - { \ - struct cmc_string str; \ - struct SNAME *s_ = _set_; \ - \ - int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_treeset, \ - #SNAME, #V, s_, s_->root, s_->count, s_->cmp, \ - s_->alloc, s_->callbacks); \ - \ - if (n < 0 || n == (int)cmc_string_len) \ - return (struct cmc_string){0}; \ - \ - str.s[n] = '\0'; \ - \ - return str; \ - } \ - \ - struct SNAME *PFX##_union(struct SNAME *_set1_, struct SNAME *_set2_) \ - { \ - struct SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ - \ - if (!_set_r_) \ - return NULL; \ - \ - struct 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_; \ - } \ - \ - struct SNAME *PFX##_intersection(struct SNAME *_set1_, struct SNAME *_set2_) \ - { \ - struct SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ - \ - if (!_set_r_) \ - return NULL; \ - \ - struct SNAME *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; \ - struct SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \ - \ - struct 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_node(_set_B_, value) != NULL) \ - PFX##_insert(_set_r_, value); \ - } \ - \ - return _set_r_; \ - } \ - \ - struct SNAME *PFX##_difference(struct SNAME *_set1_, struct SNAME *_set2_) \ - { \ - struct SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ - \ - if (!_set_r_) \ - return NULL; \ - \ - struct 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_node(_set2_, value) == NULL) \ - PFX##_insert(_set_r_, value); \ - } \ - \ - return _set_r_; \ - } \ - \ - struct SNAME *PFX##_symmetric_difference(struct SNAME *_set1_, struct SNAME *_set2_) \ - { \ - struct SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ - \ - if (!_set_r_) \ - return NULL; \ - \ - struct 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)) \ - { \ - V value = PFX##_iter_value(&iter1); \ - \ - if (PFX##_impl_get_node(_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_node(_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(struct SNAME *_set1_, struct 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; \ - \ - struct 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(struct SNAME *_set1_, struct 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(struct SNAME *_set1_, struct 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; \ - } \ - \ - struct 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(struct SNAME *_set1_, struct 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(struct SNAME *_set1_, struct SNAME *_set2_) \ - { \ - /* The intersection of an empty set with any other set will result in an empty */ \ - /* set */ \ - if (PFX##_empty(_set1_)) \ - return true; \ - \ - struct 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; \ - } \ - \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ - { \ - struct SNAME##_iter *iter = malloc(sizeof(struct SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(struct SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ - { \ - memset(iter, 0, sizeof(struct SNAME##_iter)); \ - \ - iter->target = target; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - \ - iter->cursor = target->root; \ - \ - if (!PFX##_empty(target)) \ - { \ - while (iter->cursor->left != NULL) \ - iter->cursor = iter->cursor->left; \ - \ - iter->first = iter->cursor; \ - \ - iter->last = target->root; \ - while (iter->last->right != NULL) \ - iter->last = iter->last->right; \ - } \ - } \ - \ - bool PFX##_iter_start(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(struct SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(struct SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - iter->cursor = iter->first; \ - } \ - } \ - \ - void PFX##_iter_to_end(struct SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - iter->cursor = iter->last; \ - } \ - } \ - \ - bool PFX##_iter_next(struct SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->cursor == iter->last) \ - { \ - iter->end = true; \ - return true; \ - } \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - if (iter->cursor->right != NULL) \ - { \ - iter->cursor = iter->cursor->right; \ - \ - while (iter->cursor->left != NULL) \ - iter->cursor = iter->cursor->left; \ - \ - iter->index++; \ - \ - return true; \ - } \ - \ - while (true) \ - { \ - if (iter->cursor->parent->left == iter->cursor) \ - { \ - iter->cursor = iter->cursor->parent; \ - \ - iter->index++; \ - \ - return true; \ - } \ - \ - iter->cursor = iter->cursor->parent; \ - } \ - } \ - \ - bool PFX##_iter_prev(struct SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->cursor == iter->first) \ - { \ - iter->start = true; \ - \ - return true; \ - } \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - if (iter->cursor->left != NULL) \ - { \ - iter->cursor = iter->cursor->left; \ - \ - while (iter->cursor->right != NULL) \ - iter->cursor = iter->cursor->right; \ - \ - iter->index--; \ - \ - return true; \ - } \ - \ - while (true) \ - { \ - if (iter->cursor->parent->right == iter->cursor) \ - { \ - iter->cursor = iter->cursor->parent; \ - \ - iter->index--; \ - \ - return true; \ - } \ - \ - iter->cursor = iter->cursor->parent; \ - } \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->cursor == iter->last) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ - return false; \ - \ - iter->index += steps; \ - \ - 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(struct SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->cursor == iter->first) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index < steps) \ - return false; \ - \ - iter->index -= steps; \ - \ - 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(struct 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(struct SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){0}; \ - \ - return iter->cursor->value; \ - } \ - \ - size_t PFX##_iter_index(struct SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - static struct SNAME##_node *PFX##_impl_new_node(V element) \ - { \ - struct SNAME##_node *node = malloc(sizeof(struct SNAME##_node)); \ - \ - if (!node) \ - return NULL; \ - \ - node->value = element; \ - node->right = NULL; \ - node->left = NULL; \ - node->parent = NULL; \ - node->height = 0; \ - \ - return node; \ - } \ - \ - static struct SNAME##_node *PFX##_impl_get_node(struct SNAME *_set_, V element) \ - { \ - if (PFX##_empty(_set_)) \ - return NULL; \ - \ - struct SNAME##_node *scan = _set_->root; \ - \ - while (scan != NULL) \ - { \ - if (_set_->cmp(scan->value, element) > 0) \ - scan = scan->left; \ - else if (_set_->cmp(scan->value, element) < 0) \ - scan = scan->right; \ - else \ - return scan; \ - } \ - \ - return NULL; \ - } \ - \ - static unsigned char PFX##_impl_h(struct SNAME##_node *node) \ - { \ - if (node == NULL) \ - return 0; \ - \ - return node->height; \ - } \ - \ - static unsigned char PFX##_impl_hupdate(struct SNAME##_node *node) \ - { \ - if (node == NULL) \ - return 0; \ - \ - unsigned char h_l = PFX##_impl_h(node->left); \ - unsigned char h_r = PFX##_impl_h(node->right); \ - \ - return 1 + (h_l > h_r ? h_l : h_r); \ - } \ - \ - static void PFX##_impl_rotate_right(struct SNAME##_node **Z) \ - { \ - struct SNAME##_node *root = *Z; \ - struct SNAME##_node *new_root = root->left; \ - \ - if (root->parent != NULL) \ - { \ - if (root->parent->left == root) \ - root->parent->left = new_root; \ - else \ - root->parent->right = new_root; \ - } \ - \ - new_root->parent = root->parent; \ - \ - root->parent = new_root; \ - root->left = new_root->right; \ - \ - if (root->left) \ - root->left->parent = root; \ - \ - new_root->right = root; \ - \ - root->height = PFX##_impl_hupdate(root); \ - new_root->height = PFX##_impl_hupdate(new_root); \ - \ - *Z = new_root; \ - } \ - \ - static void PFX##_impl_rotate_left(struct SNAME##_node **Z) \ - { \ - struct SNAME##_node *root = *Z; \ - struct SNAME##_node *new_root = root->right; \ - \ - if (root->parent != NULL) \ - { \ - if (root->parent->right == root) \ - root->parent->right = new_root; \ - else \ - root->parent->left = new_root; \ - } \ - \ - new_root->parent = root->parent; \ - \ - root->parent = new_root; \ - root->right = new_root->left; \ - \ - if (root->right) \ - root->right->parent = root; \ - \ - new_root->left = root; \ - \ - root->height = PFX##_impl_hupdate(root); \ - new_root->height = PFX##_impl_hupdate(new_root); \ - \ - *Z = new_root; \ - } \ - \ - static void PFX##_impl_rebalance(struct SNAME *_set_, struct SNAME##_node *node) \ - { \ - struct SNAME##_node *scan = node, *child = NULL; \ - \ - int balance; \ - bool is_root = false; \ - \ - while (scan != NULL) \ - { \ - if (scan->parent == NULL) \ - is_root = true; \ - \ - scan->height = PFX##_impl_hupdate(scan); \ - balance = PFX##_impl_h(scan->right) - PFX##_impl_h(scan->left); \ - \ - if (balance >= 2) \ - { \ - child = scan->right; \ - \ - if (PFX##_impl_h(child->right) < PFX##_impl_h(child->left)) \ - PFX##_impl_rotate_right(&(scan->right)); \ - \ - PFX##_impl_rotate_left(&scan); \ - } \ - else if (balance <= -2) \ - { \ - child = scan->left; \ - \ - if (PFX##_impl_h(child->left) < PFX##_impl_h(child->right)) \ - PFX##_impl_rotate_left(&(scan->left)); \ - \ - PFX##_impl_rotate_right(&scan); \ - } \ - \ - if (is_root) \ - { \ - _set_->root = scan; \ - is_root = false; \ - } \ - \ - scan = scan->parent; \ - } \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_set_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _set_); \ - \ - return iter; \ - } \ - \ - static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_set_) \ - { \ - struct SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _set_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ + * ------------------------------------------------------------------------- */ +#define CMC_GENERATE_TREESET_SOURCE(PFX, SNAME, V) \ + \ + /* Implementation Detail Functions */ \ + static struct SNAME##_node *PFX##_impl_new_node(V element); \ + static struct SNAME##_node *PFX##_impl_get_node(struct SNAME *_set_, \ + V element); \ + static unsigned char PFX##_impl_h(struct SNAME##_node *node); \ + static unsigned char PFX##_impl_hupdate(struct SNAME##_node *node); \ + static void PFX##_impl_rotate_right(struct SNAME##_node **Z); \ + static void PFX##_impl_rotate_left(struct SNAME##_node **Z); \ + static void PFX##_impl_rebalance(struct SNAME *_set_, \ + struct SNAME##_node *node); \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_set_); \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_set_); \ + \ + struct SNAME *PFX##_new(int (*compare)(V, V)) \ + { \ + struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ + \ + struct SNAME *_set_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_set_) \ + return NULL; \ + \ + _set_->count = 0; \ + _set_->root = NULL; \ + _set_->cmp = compare; \ + \ + _set_->it_start = PFX##_impl_it_start; \ + _set_->it_end = PFX##_impl_it_end; \ + \ + _set_->alloc = alloc; \ + _set_->callbacks = NULL; \ + \ + return _set_; \ + } \ + \ + struct SNAME *PFX##_new_custom(int (*compare)(V, V), \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_treeset *callbacks) \ + { \ + if (!alloc) \ + alloc = &cmc_alloc_node_default; \ + \ + struct SNAME *_set_ = alloc->malloc(sizeof(struct SNAME)); \ + \ + if (!_set_) \ + return NULL; \ + \ + _set_->count = 0; \ + _set_->root = NULL; \ + _set_->cmp = compare; \ + \ + _set_->it_start = PFX##_impl_it_start; \ + _set_->it_end = PFX##_impl_it_end; \ + \ + _set_->alloc = alloc; \ + _set_->callbacks = callbacks; \ + \ + return _set_; \ + } \ + \ + void PFX##_clear(struct SNAME *_set_, void (*deallocator)(V)) \ + { \ + struct SNAME##_node *scan = _set_->root; \ + struct SNAME##_node *up = NULL; \ + \ + while (scan != NULL) \ + { \ + if (scan->left != NULL) \ + { \ + struct SNAME##_node *left = scan->left; \ + \ + scan->left = up; \ + up = scan; \ + scan = left; \ + } \ + else if (scan->right != NULL) \ + { \ + struct SNAME##_node *right = scan->right; \ + \ + scan->left = up; \ + scan->right = NULL; \ + up = scan; \ + scan = right; \ + } \ + else \ + { \ + if (up == NULL) \ + { \ + if (deallocator) \ + deallocator(scan->value); \ + \ + free(scan); \ + scan = NULL; \ + } \ + \ + while (up != NULL) \ + { \ + if (deallocator) \ + deallocator(scan->value); \ + \ + free(scan); \ + \ + if (up->right != NULL) \ + { \ + scan = up->right; \ + up->right = NULL; \ + break; \ + } \ + else \ + { \ + scan = up; \ + up = up->left; \ + } \ + } \ + } \ + } \ + \ + _set_->count = 0; \ + _set_->root = NULL; \ + } \ + \ + void PFX##_free(struct SNAME *_set_, void (*deallocator)(V)) \ + { \ + PFX##_clear(_set_, deallocator); \ + \ + free(_set_); \ + } \ + \ + bool PFX##_insert(struct SNAME *_set_, V element) \ + { \ + if (PFX##_empty(_set_)) \ + { \ + _set_->root = PFX##_impl_new_node(element); \ + \ + if (!_set_->root) \ + return false; \ + } \ + else \ + { \ + struct SNAME##_node *scan = _set_->root; \ + struct SNAME##_node *parent = scan; \ + \ + while (scan != NULL) \ + { \ + parent = scan; \ + \ + if (_set_->cmp(scan->value, element) > 0) \ + scan = scan->left; \ + else if (_set_->cmp(scan->value, element) < 0) \ + scan = scan->right; \ + else \ + return false; \ + } \ + \ + struct SNAME##_node *node; \ + \ + if (_set_->cmp(parent->value, element) > 0) \ + { \ + parent->left = PFX##_impl_new_node(element); \ + \ + if (!parent->left) \ + return false; \ + \ + parent->left->parent = parent; \ + node = parent->left; \ + } \ + else \ + { \ + parent->right = PFX##_impl_new_node(element); \ + \ + if (!parent->right) \ + return false; \ + \ + parent->right->parent = parent; \ + node = parent->right; \ + } \ + \ + PFX##_impl_rebalance(_set_, node); \ + } \ + \ + _set_->count++; \ + \ + return true; \ + } \ + \ + bool PFX##_remove(struct SNAME *_set_, V element) \ + { \ + struct SNAME##_node *node = PFX##_impl_get_node(_set_, element); \ + \ + if (!node) \ + return false; \ + \ + struct SNAME##_node *temp = NULL, *unbalanced = NULL; \ + \ + bool is_root = node->parent == NULL; \ + \ + if (node->left == NULL && node->right == NULL) \ + { \ + if (is_root) \ + _set_->root = NULL; \ + else \ + { \ + unbalanced = node->parent; \ + \ + if (node->parent->right == node) \ + node->parent->right = NULL; \ + else \ + node->parent->left = NULL; \ + } \ + \ + free(node); \ + } \ + else if (node->left == NULL) \ + { \ + if (is_root) \ + { \ + _set_->root = node->right; \ + _set_->root->parent = NULL; \ + } \ + else \ + { \ + unbalanced = node->parent; \ + \ + node->right->parent = node->parent; \ + \ + if (node->parent->right == node) \ + node->parent->right = node->right; \ + else \ + node->parent->left = node->right; \ + } \ + \ + free(node); \ + } \ + else if (node->right == NULL) \ + { \ + if (is_root) \ + { \ + _set_->root = node->left; \ + _set_->root->parent = NULL; \ + } \ + else \ + { \ + unbalanced = node->parent; \ + \ + node->left->parent = node->parent; \ + \ + if (node->parent->right == node) \ + node->parent->right = node->left; \ + else \ + node->parent->left = node->left; \ + } \ + \ + free(node); \ + } \ + else \ + { \ + temp = node->right; \ + while (temp->left != NULL) \ + temp = temp->left; \ + \ + V temp_value = temp->value; \ + \ + unbalanced = temp->parent; \ + \ + if (temp->left == NULL && temp->right == NULL) \ + { \ + if (temp->parent->right == temp) \ + temp->parent->right = NULL; \ + else \ + temp->parent->left = NULL; \ + } \ + else if (temp->left == NULL) \ + { \ + temp->right->parent = temp->parent; \ + \ + if (temp->parent->right == temp) \ + temp->parent->right = temp->right; \ + else \ + temp->parent->left = temp->right; \ + } \ + else if (temp->right == NULL) \ + { \ + temp->left->parent = temp->parent; \ + \ + if (temp->parent->right == temp) \ + temp->parent->right = temp->left; \ + else \ + temp->parent->left = temp->left; \ + } \ + \ + free(temp); \ + \ + node->value = temp_value; \ + } \ + \ + if (unbalanced != NULL) \ + PFX##_impl_rebalance(_set_, unbalanced); \ + \ + _set_->count--; \ + \ + if (_set_->count == 0) \ + _set_->root = NULL; \ + \ + return true; \ + } \ + \ + bool PFX##_max(struct SNAME *_set_, V *value) \ + { \ + if (PFX##_empty(_set_)) \ + return false; \ + \ + struct SNAME##_node *scan = _set_->root; \ + \ + while (scan->right != NULL) \ + scan = scan->right; \ + \ + *value = scan->value; \ + \ + return true; \ + } \ + \ + bool PFX##_min(struct SNAME *_set_, V *value) \ + { \ + if (PFX##_empty(_set_)) \ + return false; \ + \ + struct SNAME##_node *scan = _set_->root; \ + \ + while (scan->left != NULL) \ + scan = scan->left; \ + \ + *value = scan->value; \ + \ + return true; \ + } \ + \ + bool PFX##_contains(struct SNAME *_set_, V element) \ + { \ + struct SNAME##_node *scan = _set_->root; \ + \ + while (scan != NULL) \ + { \ + if (_set_->cmp(scan->value, element) > 0) \ + scan = scan->left; \ + else if (_set_->cmp(scan->value, element) < 0) \ + scan = scan->right; \ + else \ + return true; \ + } \ + \ + return false; \ + } \ + \ + bool PFX##_empty(struct SNAME *_set_) \ + { \ + return _set_->count == 0; \ + } \ + \ + size_t PFX##_count(struct SNAME *_set_) \ + { \ + return _set_->count; \ + } \ + \ + struct SNAME *PFX##_copy_of(struct SNAME *_set_, V (*copy_func)(V)) \ + { \ + struct SNAME *result = PFX##_new(_set_->cmp); \ + \ + if (!result) \ + return NULL; \ + \ + struct SNAME##_iter iter; \ + PFX##_iter_init(&iter, _set_); \ + \ + if (!PFX##_empty(_set_)) \ + { \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); \ + PFX##_iter_next(&iter)) \ + { \ + if (copy_func) \ + PFX##_insert(result, copy_func(PFX##_iter_value(&iter))); \ + else \ + PFX##_insert(result, PFX##_iter_value(&iter)); \ + } \ + } \ + \ + return result; \ + } \ + \ + bool PFX##_equals(struct SNAME *_set1_, struct SNAME *_set2_) \ + { \ + if (PFX##_count(_set1_) != PFX##_count(_set2_)) \ + return false; \ + \ + struct 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_node(_set2_, PFX##_iter_value(&iter)) == NULL) \ + return false; \ + } \ + \ + return true; \ + } \ + \ + struct cmc_string PFX##_to_string(struct SNAME *_set_) \ + { \ + struct cmc_string str; \ + struct SNAME *s_ = _set_; \ + \ + int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_treeset, \ + #SNAME, #V, s_, s_->root, s_->count, s_->cmp, \ + s_->alloc, s_->callbacks); \ + \ + if (n < 0 || n == (int)cmc_string_len) \ + return (struct cmc_string){ 0 }; \ + \ + str.s[n] = '\0'; \ + \ + return str; \ + } \ + \ + struct SNAME *PFX##_union(struct SNAME *_set1_, struct SNAME *_set2_) \ + { \ + struct SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ + \ + if (!_set_r_) \ + return NULL; \ + \ + struct 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_; \ + } \ + \ + struct SNAME *PFX##_intersection(struct SNAME *_set1_, \ + struct SNAME *_set2_) \ + { \ + struct SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ + \ + if (!_set_r_) \ + return NULL; \ + \ + struct SNAME *_set_A_ = \ + _set1_->count < _set2_->count ? _set1_ : _set2_; \ + struct SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \ + \ + struct 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_node(_set_B_, value) != NULL) \ + PFX##_insert(_set_r_, value); \ + } \ + \ + return _set_r_; \ + } \ + \ + struct SNAME *PFX##_difference(struct SNAME *_set1_, struct SNAME *_set2_) \ + { \ + struct SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ + \ + if (!_set_r_) \ + return NULL; \ + \ + struct 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_node(_set2_, value) == NULL) \ + PFX##_insert(_set_r_, value); \ + } \ + \ + return _set_r_; \ + } \ + \ + struct SNAME *PFX##_symmetric_difference(struct SNAME *_set1_, \ + struct SNAME *_set2_) \ + { \ + struct SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ + \ + if (!_set_r_) \ + return NULL; \ + \ + struct 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)) \ + { \ + V value = PFX##_iter_value(&iter1); \ + \ + if (PFX##_impl_get_node(_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_node(_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(struct SNAME *_set1_, struct 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; \ + \ + struct 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(struct SNAME *_set1_, struct 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(struct SNAME *_set1_, struct 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; \ + } \ + \ + struct 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(struct SNAME *_set1_, struct 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(struct SNAME *_set1_, struct SNAME *_set2_) \ + { \ + /* The intersection of an empty set with any other set will result */ \ + /* in an empty set */ \ + if (PFX##_empty(_set1_)) \ + return true; \ + \ + struct 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; \ + } \ + \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ + { \ + struct SNAME##_iter *iter = malloc(sizeof(struct SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + void PFX##_iter_free(struct SNAME##_iter *iter) \ + { \ + free(iter); \ + } \ + \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ + { \ + memset(iter, 0, sizeof(struct SNAME##_iter)); \ + \ + iter->target = target; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + \ + iter->cursor = target->root; \ + \ + if (!PFX##_empty(target)) \ + { \ + while (iter->cursor->left != NULL) \ + iter->cursor = iter->cursor->left; \ + \ + iter->first = iter->cursor; \ + \ + iter->last = target->root; \ + while (iter->last->right != NULL) \ + iter->last = iter->last->right; \ + } \ + } \ + \ + bool PFX##_iter_start(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + bool PFX##_iter_end(struct SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + void PFX##_iter_to_start(struct SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + iter->cursor = iter->first; \ + } \ + } \ + \ + void PFX##_iter_to_end(struct SNAME##_iter *iter) \ + { \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->index = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + iter->cursor = iter->last; \ + } \ + } \ + \ + bool PFX##_iter_next(struct SNAME##_iter *iter) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->cursor == iter->last) \ + { \ + iter->end = true; \ + return true; \ + } \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + if (iter->cursor->right != NULL) \ + { \ + iter->cursor = iter->cursor->right; \ + \ + while (iter->cursor->left != NULL) \ + iter->cursor = iter->cursor->left; \ + \ + iter->index++; \ + \ + return true; \ + } \ + \ + while (true) \ + { \ + if (iter->cursor->parent->left == iter->cursor) \ + { \ + iter->cursor = iter->cursor->parent; \ + \ + iter->index++; \ + \ + return true; \ + } \ + \ + iter->cursor = iter->cursor->parent; \ + } \ + } \ + \ + bool PFX##_iter_prev(struct SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor == iter->first) \ + { \ + iter->start = true; \ + \ + return true; \ + } \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + if (iter->cursor->left != NULL) \ + { \ + iter->cursor = iter->cursor->left; \ + \ + while (iter->cursor->right != NULL) \ + iter->cursor = iter->cursor->right; \ + \ + iter->index--; \ + \ + return true; \ + } \ + \ + while (true) \ + { \ + if (iter->cursor->parent->right == iter->cursor) \ + { \ + iter->cursor = iter->cursor->parent; \ + \ + iter->index--; \ + \ + return true; \ + } \ + \ + iter->cursor = iter->cursor->parent; \ + } \ + } \ + \ + /* Returns true only if the iterator moved */ \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->cursor == iter->last) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ + return false; \ + \ + iter->index += steps; \ + \ + 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(struct SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor == iter->first) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index < steps) \ + return false; \ + \ + iter->index -= steps; \ + \ + 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(struct 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(struct SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return (V){ 0 }; \ + \ + return iter->cursor->value; \ + } \ + \ + size_t PFX##_iter_index(struct SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + static struct SNAME##_node *PFX##_impl_new_node(V element) \ + { \ + struct SNAME##_node *node = malloc(sizeof(struct SNAME##_node)); \ + \ + if (!node) \ + return NULL; \ + \ + node->value = element; \ + node->right = NULL; \ + node->left = NULL; \ + node->parent = NULL; \ + node->height = 0; \ + \ + return node; \ + } \ + \ + static struct SNAME##_node *PFX##_impl_get_node(struct SNAME *_set_, \ + V element) \ + { \ + if (PFX##_empty(_set_)) \ + return NULL; \ + \ + struct SNAME##_node *scan = _set_->root; \ + \ + while (scan != NULL) \ + { \ + if (_set_->cmp(scan->value, element) > 0) \ + scan = scan->left; \ + else if (_set_->cmp(scan->value, element) < 0) \ + scan = scan->right; \ + else \ + return scan; \ + } \ + \ + return NULL; \ + } \ + \ + static unsigned char PFX##_impl_h(struct SNAME##_node *node) \ + { \ + if (node == NULL) \ + return 0; \ + \ + return node->height; \ + } \ + \ + static unsigned char PFX##_impl_hupdate(struct SNAME##_node *node) \ + { \ + if (node == NULL) \ + return 0; \ + \ + unsigned char h_l = PFX##_impl_h(node->left); \ + unsigned char h_r = PFX##_impl_h(node->right); \ + \ + return 1 + (h_l > h_r ? h_l : h_r); \ + } \ + \ + static void PFX##_impl_rotate_right(struct SNAME##_node **Z) \ + { \ + struct SNAME##_node *root = *Z; \ + struct SNAME##_node *new_root = root->left; \ + \ + if (root->parent != NULL) \ + { \ + if (root->parent->left == root) \ + root->parent->left = new_root; \ + else \ + root->parent->right = new_root; \ + } \ + \ + new_root->parent = root->parent; \ + \ + root->parent = new_root; \ + root->left = new_root->right; \ + \ + if (root->left) \ + root->left->parent = root; \ + \ + new_root->right = root; \ + \ + root->height = PFX##_impl_hupdate(root); \ + new_root->height = PFX##_impl_hupdate(new_root); \ + \ + *Z = new_root; \ + } \ + \ + static void PFX##_impl_rotate_left(struct SNAME##_node **Z) \ + { \ + struct SNAME##_node *root = *Z; \ + struct SNAME##_node *new_root = root->right; \ + \ + if (root->parent != NULL) \ + { \ + if (root->parent->right == root) \ + root->parent->right = new_root; \ + else \ + root->parent->left = new_root; \ + } \ + \ + new_root->parent = root->parent; \ + \ + root->parent = new_root; \ + root->right = new_root->left; \ + \ + if (root->right) \ + root->right->parent = root; \ + \ + new_root->left = root; \ + \ + root->height = PFX##_impl_hupdate(root); \ + new_root->height = PFX##_impl_hupdate(new_root); \ + \ + *Z = new_root; \ + } \ + \ + static void PFX##_impl_rebalance(struct SNAME *_set_, \ + struct SNAME##_node *node) \ + { \ + struct SNAME##_node *scan = node, *child = NULL; \ + \ + int balance; \ + bool is_root = false; \ + \ + while (scan != NULL) \ + { \ + if (scan->parent == NULL) \ + is_root = true; \ + \ + scan->height = PFX##_impl_hupdate(scan); \ + balance = PFX##_impl_h(scan->right) - PFX##_impl_h(scan->left); \ + \ + if (balance >= 2) \ + { \ + child = scan->right; \ + \ + if (PFX##_impl_h(child->right) < PFX##_impl_h(child->left)) \ + PFX##_impl_rotate_right(&(scan->right)); \ + \ + PFX##_impl_rotate_left(&scan); \ + } \ + else if (balance <= -2) \ + { \ + child = scan->left; \ + \ + if (PFX##_impl_h(child->left) < PFX##_impl_h(child->right)) \ + PFX##_impl_rotate_left(&(scan->left)); \ + \ + PFX##_impl_rotate_right(&scan); \ + } \ + \ + if (is_root) \ + { \ + _set_->root = scan; \ + is_root = false; \ + } \ + \ + scan = scan->parent; \ + } \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_set_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _set_); \ + \ + return iter; \ + } \ + \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_set_) \ + { \ + struct SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _set_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_TREESET_H */ diff --git a/src/utl/assert.h b/src/utl/assert.h index d4348dd..80540f2 100644 --- a/src/utl/assert.h +++ b/src/utl/assert.h @@ -72,18 +72,17 @@ static bool cmc_assert_state = true; /** * expression : An expression that is expected to be evaluated to true. */ -#define cmc_assert(expression) \ - do \ - { \ - const char *str = #expression; \ - if (!(expression)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }\n", \ - __FILE__, __func__, __LINE__, str); \ - } \ +#define cmc_assert(expression) \ + do \ + { \ + const char *str = #expression; \ + if (!(expression)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf(stderr, "Assertion Failed at %s:%s:%u for { %s }\n", \ + __FILE__, __func__, __LINE__, str); \ + } \ } while (0) /** @@ -105,26 +104,26 @@ static bool cmc_assert_state = true; (not_expected, actual) /** - * dtype : One of the data types listed at the beggining of this file (excluding ptr). - * boundary : Expected lowest possible value (excluded). - * actual : Actual value tested against the given boundary. + * dtype : One of the data types listed at the beggining of this file + * (excluding ptr). boundary : Expected lowest possible value (excluded). actual + * : Actual value tested against the given boundary. */ #define cmc_assert_greater(dtype, boundary, actual) \ CMC_ASSERT_GLUE(dtype, greater) \ (boundary, actual) /** - * dtype : One of the data types listed at the beggining of this file (excluding ptr). - * boundary : Expected lowest possible value (included). - * actual : Actual value tested against the given boundary. + * dtype : One of the data types listed at the beggining of this file + * (excluding ptr). boundary : Expected lowest possible value (included). actual + * : Actual value tested against the given boundary. */ #define cmc_assert_greater_equals(dtype, boundary, actual) \ CMC_ASSERT_GLUE(dtype, greater_equals) \ (boundary, actual) /** - * dtype : One of the data types listed at the beggining of this file (excluding ptr). - * boundary : Expected highest possible value (excluded). + * dtype : One of the data types listed at the beggining of this file + * (excluding ptr). boundary : Expected highest possible value (excluded). * actual : Actual value tested against the given boundary. */ #define cmc_assert_lesser(dtype, boundary, actual) \ @@ -132,8 +131,8 @@ static bool cmc_assert_state = true; (boundary, actual) /** - * dtype : One of the data types listed at the beggining of this file (excluding ptr). - * boundary : Expected highest possible value (included). + * dtype : One of the data types listed at the beggining of this file + * (excluding ptr). boundary : Expected highest possible value (included). * actual : Actual value tested against the given boundary. */ #define cmc_assert_lesser_equals(dtype, boundary, actual) \ @@ -141,8 +140,8 @@ static bool cmc_assert_state = true; (boundary, actual) /** - * dtype : One of the data types listed at the beggining of this file (excluding ptr). - * lower_bound : Smallest value of the expected range. + * dtype : One of the data types listed at the beggining of this file + * (excluding ptr). lower_bound : Smallest value of the expected range. * upper_bound : Highest value of the expected range. * actual : Actual value tested against the given range. * @@ -153,8 +152,8 @@ static bool cmc_assert_state = true; (lower_bound, upper_bound, actual) /** - * dtype : One of the data types listed at the beggining of this file (excluding ptr). - * lower_bound : Smallest value of the not expected range. + * dtype : One of the data types listed at the beggining of this file + * (excluding ptr). lower_bound : Smallest value of the not expected range. * upper_bound : Highest value of the not expected range. * actual : Actual value tested against the given range. * @@ -184,31 +183,34 @@ static bool cmc_assert_state = true; * * This macro can be used for any data type. Both bounds are inclusive. */ -#define cmc_assert_array_equals_any(dtype, array1, array2, comparator, from_index, to_index) \ - do \ - { \ - const char *str1__ = #array1; \ - const char *str2__ = #array2; \ - dtype *arr1__ = array1; \ - dtype *arr2__ = array2; \ - size_t from__ = from_index; \ - size_t to__ = to_index; \ - int (*cmp__)(dtype, dtype) = comparator; \ - \ - for (size_t i__ = from__; i__ <= to__; i__++) \ - { \ - if (cmp__(arr1__[i__], arr2__[i__]) != 0) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s and %s }: Arrays values are not equal at index %" PRIuMAX "\n", \ - __FILE__, __func__, __LINE__, str1__, str2__, i__); \ - \ - break; \ - } \ - } \ - \ +#define cmc_assert_array_equals_any(dtype, array1, array2, comparator, \ + from_index, to_index) \ + do \ + { \ + const char *str1__ = #array1; \ + const char *str2__ = #array2; \ + dtype *arr1__ = array1; \ + dtype *arr2__ = array2; \ + size_t from__ = from_index; \ + size_t to__ = to_index; \ + int (*cmp__)(dtype, dtype) = comparator; \ + \ + for (size_t i__ = from__; i__ <= to__; i__++) \ + { \ + if (cmp__(arr1__[i__], arr2__[i__]) != 0) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s and %s }: Arrays values are not equal at index %" PRIuMAX \ + "\n", \ + __FILE__, __func__, __LINE__, str1__, str2__, i__); \ + \ + break; \ + } \ + } \ + \ } while (0) /** @@ -226,73 +228,80 @@ static bool cmc_assert_state = true; * * This macro can be used for any data type. Both bounds are inclusive. */ -#define cmc_assert_array_within_any(dtype, array, comparator, lower_bound, upper_bound, from_index, to_index) \ - do \ - { \ - const char *str__ = #array; \ - dtype *arr__ = array; \ - dtype lower_bound___ = lower_bound; \ - dtype upper_bound___ = upper_bound; \ - size_t from__ = from_index; \ - size_t to__ = to_index; \ - int (*cmp__)(dtype, dtype) = comparator; \ - \ - for (size_t i__ = from__; i__ <= to__; i__++) \ - { \ - if (cmp__(arr__[i__], lower_bound___) < 0 || cmp__(arr__[i__], upper_bound___) > 0) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Array value not within bounds at index %" PRIuMAX "\n", \ - __FILE__, __func__, __LINE__, str__, i__); \ - \ - break; \ - } \ - } \ - \ +#define cmc_assert_array_within_any(dtype, array, comparator, lower_bound, \ + upper_bound, from_index, to_index) \ + do \ + { \ + const char *str__ = #array; \ + dtype *arr__ = array; \ + dtype lower_bound___ = lower_bound; \ + dtype upper_bound___ = upper_bound; \ + size_t from__ = from_index; \ + size_t to__ = to_index; \ + int (*cmp__)(dtype, dtype) = comparator; \ + \ + for (size_t i__ = from__; i__ <= to__; i__++) \ + { \ + if (cmp__(arr__[i__], lower_bound___) < 0 || \ + cmp__(arr__[i__], upper_bound___) > 0) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Array value not within bounds at index %" PRIuMAX \ + "\n", \ + __FILE__, __func__, __LINE__, str__, i__); \ + \ + break; \ + } \ + } \ + \ } while (0) /** * Assert that each element in the array are within bounds. * * dtype : The type of the array. - * array : Array to be checked if its elements are outside of a given range - * comparator : A function that has two 'dtype' arguments and returns -1 if the - * first is less then the second, 0 if both are equal or 1 if the - * first is greater then the second. - * lower_bound : Smallest value of the given range. + * array : Array to be checked if its elements are outside of a given + * range comparator : A function that has two 'dtype' arguments and returns -1 + * if the first is less then the second, 0 if both are equal or 1 if the first + * is greater then the second. lower_bound : Smallest value of the given range. * upper_bound : Highest value of the given range. * from_index : First index from the array to compare (inclusive). * to_index : Last index from the array to compare (inclusive). * * This macro can be used for any data type. Both bounds are inclusive. */ -#define cmc_assert_array_outside_any(dtype, array, comparator, lower_bound, upper_bound, from_index, to_index) \ - do \ - { \ - const char *str__ = #array; \ - dtype *arr__ = array; \ - dtype lower_bound___ = lower_bound; \ - dtype upper_bound___ = upper_bound; \ - size_t from__ = from_index; \ - size_t to__ = to_index; \ - int (*cmp__)(dtype, dtype) = comparator; \ - \ - for (size_t i__ = from__; i__ <= to__; i__++) \ - { \ - if (cmp__(arr__[i__], lower_bound___) >= 0 && cmp__(arr__[i__], upper_bound___) <= 0) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Array value not outside bounds at index %" PRIuMAX "\n", \ - __FILE__, __func__, __LINE__, str__, i__); \ - \ - break; \ - } \ - } \ - \ +#define cmc_assert_array_outside_any(dtype, array, comparator, lower_bound, \ + upper_bound, from_index, to_index) \ + do \ + { \ + const char *str__ = #array; \ + dtype *arr__ = array; \ + dtype lower_bound___ = lower_bound; \ + dtype upper_bound___ = upper_bound; \ + size_t from__ = from_index; \ + size_t to__ = to_index; \ + int (*cmp__)(dtype, dtype) = comparator; \ + \ + for (size_t i__ = from__; i__ <= to__; i__++) \ + { \ + if (cmp__(arr__[i__], lower_bound___) >= 0 && \ + cmp__(arr__[i__], upper_bound___) <= 0) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Array value not outside bounds at index %" PRIuMAX \ + "\n", \ + __FILE__, __func__, __LINE__, str__, i__); \ + \ + break; \ + } \ + } \ + \ } while (0) /** @@ -308,33 +317,36 @@ static bool cmc_assert_state = true; * * This macro can be used for any data type. */ -#define cmc_assert_array_sorted_any(dtype, array, comparator, from_index, to_index) \ - do \ - { \ - const char *str__ = #array; \ - dtype *arr__ = array; \ - size_t from__ = from_index; \ - size_t to__ = to_index; \ - int (*cmp__)(dtype, dtype) = comparator; \ - \ - size_t iprev__ = from__; \ - \ - for (size_t i__ = from__ + 1; i__ <= to__; i__++) \ - { \ - if (cmp__(arr__[iprev__], arr__[i__]) > 0) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not sorted when comparing indexes %" PRIuMAX " and %" PRIuMAX "\n", \ - __FILE__, __func__, __LINE__, str__, iprev__, i__); \ - \ - break; \ - } \ - \ - iprev__ = i__; \ - } \ - \ +#define cmc_assert_array_sorted_any(dtype, array, comparator, from_index, \ + to_index) \ + do \ + { \ + const char *str__ = #array; \ + dtype *arr__ = array; \ + size_t from__ = from_index; \ + size_t to__ = to_index; \ + int (*cmp__)(dtype, dtype) = comparator; \ + \ + size_t iprev__ = from__; \ + \ + for (size_t i__ = from__ + 1; i__ <= to__; i__++) \ + { \ + if (cmp__(arr__[iprev__], arr__[i__]) > 0) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not sorted when comparing indexes %" PRIuMAX \ + " and %" PRIuMAX "\n", \ + __FILE__, __func__, __LINE__, str__, iprev__, i__); \ + \ + break; \ + } \ + \ + iprev__ = i__; \ + } \ + \ } while (0) /** --------------------------------------------------------------------------- @@ -343,274 +355,300 @@ static bool cmc_assert_state = true; * * ------------------------------------------------------------------------ **/ -#define cmc_assert_equals_int8_t(expected, actual) \ - do \ - { \ - const char *str = #actual; \ - int8_t expected__ = (expected); \ - int8_t actual__ = (actual); \ - \ - if (expected__ != actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected: %" PRId8 " Actual: %" PRId8 "\n", \ - __FILE__, __func__, __LINE__, str, expected__, actual__); \ - } \ - \ +#define cmc_assert_equals_int8_t(expected, actual) \ + do \ + { \ + const char *str = #actual; \ + int8_t expected__ = (expected); \ + int8_t actual__ = (actual); \ + \ + if (expected__ != actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected: %" PRId8 \ + " Actual: %" PRId8 "\n", \ + __FILE__, __func__, __LINE__, str, expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_equals_int16_t(expected, actual) \ - do \ - { \ - const char *str = #actual; \ - int16_t expected__ = (expected); \ - int16_t actual__ = (actual); \ - \ - if (expected__ != actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected: %" PRId16 " Actual: %" PRId16 "\n", \ - __FILE__, __func__, __LINE__, str, expected__, actual__); \ - } \ - \ +#define cmc_assert_equals_int16_t(expected, actual) \ + do \ + { \ + const char *str = #actual; \ + int16_t expected__ = (expected); \ + int16_t actual__ = (actual); \ + \ + if (expected__ != actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected: %" PRId16 \ + " Actual: %" PRId16 "\n", \ + __FILE__, __func__, __LINE__, str, expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_equals_int32_t(expected, actual) \ - do \ - { \ - const char *str = #actual; \ - int32_t expected__ = (expected); \ - int32_t actual__ = (actual); \ - \ - if (expected__ != actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected: %" PRId32 " Actual: %" PRId32 "\n", \ - __FILE__, __func__, __LINE__, str, expected__, actual__); \ - } \ - \ +#define cmc_assert_equals_int32_t(expected, actual) \ + do \ + { \ + const char *str = #actual; \ + int32_t expected__ = (expected); \ + int32_t actual__ = (actual); \ + \ + if (expected__ != actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected: %" PRId32 \ + " Actual: %" PRId32 "\n", \ + __FILE__, __func__, __LINE__, str, expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_equals_int64_t(expected, actual) \ - do \ - { \ - const char *str = #actual; \ - int64_t expected__ = (expected); \ - int64_t actual__ = (actual); \ - \ - if (expected__ != actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected: %" PRId64 " Actual: %" PRId64 "\n", \ - __FILE__, __func__, __LINE__, str, expected__, actual__); \ - } \ - \ +#define cmc_assert_equals_int64_t(expected, actual) \ + do \ + { \ + const char *str = #actual; \ + int64_t expected__ = (expected); \ + int64_t actual__ = (actual); \ + \ + if (expected__ != actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected: %" PRId64 \ + " Actual: %" PRId64 "\n", \ + __FILE__, __func__, __LINE__, str, expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_equals_uint8_t(expected, actual) \ - do \ - { \ - const char *str = #actual; \ - uint8_t expected__ = (expected); \ - uint8_t actual__ = (actual); \ - \ - if (expected__ != actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected: %" PRIu8 " Actual: %" PRIu8 "\n", \ - __FILE__, __func__, __LINE__, str, expected__, actual__); \ - } \ - \ +#define cmc_assert_equals_uint8_t(expected, actual) \ + do \ + { \ + const char *str = #actual; \ + uint8_t expected__ = (expected); \ + uint8_t actual__ = (actual); \ + \ + if (expected__ != actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected: %" PRIu8 \ + " Actual: %" PRIu8 "\n", \ + __FILE__, __func__, __LINE__, str, expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_equals_uint16_t(expected, actual) \ - do \ - { \ - const char *str = #actual; \ - uint16_t expected__ = (expected); \ - uint16_t actual__ = (actual); \ - \ - if (expected__ != actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected: %" PRIu16 " Actual: %" PRIu16 "\n", \ - __FILE__, __func__, __LINE__, str, expected__, actual__); \ - } \ - \ +#define cmc_assert_equals_uint16_t(expected, actual) \ + do \ + { \ + const char *str = #actual; \ + uint16_t expected__ = (expected); \ + uint16_t actual__ = (actual); \ + \ + if (expected__ != actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected: %" PRIu16 \ + " Actual: %" PRIu16 "\n", \ + __FILE__, __func__, __LINE__, str, expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_equals_uint32_t(expected, actual) \ - do \ - { \ - const char *str = #actual; \ - uint32_t expected__ = (expected); \ - uint32_t actual__ = (actual); \ - \ - if (expected__ != actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected: %" PRIu32 " Actual: %" PRIu32 "\n", \ - __FILE__, __func__, __LINE__, str, expected__, actual__); \ - } \ - \ +#define cmc_assert_equals_uint32_t(expected, actual) \ + do \ + { \ + const char *str = #actual; \ + uint32_t expected__ = (expected); \ + uint32_t actual__ = (actual); \ + \ + if (expected__ != actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected: %" PRIu32 \ + " Actual: %" PRIu32 "\n", \ + __FILE__, __func__, __LINE__, str, expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_equals_uint64_t(expected, actual) \ - do \ - { \ - const char *str = #actual; \ - uint64_t expected__ = (expected); \ - uint64_t actual__ = (actual); \ - \ - if (expected__ != actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected: %" PRIu64 " Actual: %" PRIu64 "\n", \ - __FILE__, __func__, __LINE__, str, expected__, actual__); \ - } \ - \ +#define cmc_assert_equals_uint64_t(expected, actual) \ + do \ + { \ + const char *str = #actual; \ + uint64_t expected__ = (expected); \ + uint64_t actual__ = (actual); \ + \ + if (expected__ != actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected: %" PRIu64 \ + " Actual: %" PRIu64 "\n", \ + __FILE__, __func__, __LINE__, str, expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_equals_intmax_t(expected, actual) \ - do \ - { \ - const char *str = #actual; \ - intmax_t expected__ = (expected); \ - intmax_t actual__ = (actual); \ - \ - if (expected__ != actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected: %" PRIdMAX " Actual: %" PRIdMAX "\n", \ - __FILE__, __func__, __LINE__, str, expected__, actual__); \ - } \ - \ +#define cmc_assert_equals_intmax_t(expected, actual) \ + do \ + { \ + const char *str = #actual; \ + intmax_t expected__ = (expected); \ + intmax_t actual__ = (actual); \ + \ + if (expected__ != actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected: %" PRIdMAX \ + " Actual: %" PRIdMAX "\n", \ + __FILE__, __func__, __LINE__, str, expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_equals_uintmax_t(expected, actual) \ - do \ - { \ - const char *str = #actual; \ - uintmax_t expected__ = (expected); \ - uintmax_t actual__ = (actual); \ - \ - if (expected__ != actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected: %" PRIuMAX " Actual: %" PRIuMAX "\n", \ - __FILE__, __func__, __LINE__, str, expected__, actual__); \ - } \ - \ +#define cmc_assert_equals_uintmax_t(expected, actual) \ + do \ + { \ + const char *str = #actual; \ + uintmax_t expected__ = (expected); \ + uintmax_t actual__ = (actual); \ + \ + if (expected__ != actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected: %" PRIuMAX \ + " Actual: %" PRIuMAX "\n", \ + __FILE__, __func__, __LINE__, str, expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_equals_size_t(expected, actual) \ - do \ - { \ - const char *str = #actual; \ - size_t expected__ = (expected); \ - size_t actual__ = (actual); \ - \ - if (expected__ != actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected: %" PRIuMAX " Actual: %" PRIuMAX "\n", \ - __FILE__, __func__, __LINE__, str, expected__, actual__); \ - } \ - \ +#define cmc_assert_equals_size_t(expected, actual) \ + do \ + { \ + const char *str = #actual; \ + size_t expected__ = (expected); \ + size_t actual__ = (actual); \ + \ + if (expected__ != actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected: %" PRIuMAX \ + " Actual: %" PRIuMAX "\n", \ + __FILE__, __func__, __LINE__, str, expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_equals_float(expected, actual) \ - do \ - { \ - const char *str = #actual; \ - float expected__ = (expected); \ - float actual__ = (actual); \ - \ - if (expected__ != actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected: %f Actual: %f\n", \ - __FILE__, __func__, __LINE__, str, expected__, actual__); \ - } \ - \ +#define cmc_assert_equals_float(expected, actual) \ + do \ + { \ + const char *str = #actual; \ + float expected__ = (expected); \ + float actual__ = (actual); \ + \ + if (expected__ != actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected: %f Actual: %f\n", \ + __FILE__, __func__, __LINE__, str, expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_equals_double(expected, actual) \ - do \ - { \ - const char *str = #actual; \ - double expected__ = (expected); \ - double actual__ = (actual); \ - \ - if (expected__ != actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected: %lf Actual: %lf\n", \ - __FILE__, __func__, __LINE__, str, expected__, actual__); \ - } \ - \ +#define cmc_assert_equals_double(expected, actual) \ + do \ + { \ + const char *str = #actual; \ + double expected__ = (expected); \ + double actual__ = (actual); \ + \ + if (expected__ != actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected: %lf Actual: %lf\n", \ + __FILE__, __func__, __LINE__, str, expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_equals_ptr(expected, actual) \ - do \ - { \ - const char *str = #actual; \ - void *expected__ = (expected); \ - void *actual__ = (actual); \ - \ - if (expected__ != actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected: %p Actual: %p\n", \ - __FILE__, __func__, __LINE__, str, expected__, actual__); \ - } \ - \ +#define cmc_assert_equals_ptr(expected, actual) \ + do \ + { \ + const char *str = #actual; \ + void *expected__ = (expected); \ + void *actual__ = (actual); \ + \ + if (expected__ != actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected: %p Actual: %p\n", \ + __FILE__, __func__, __LINE__, str, expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_equals__Bool(expected, actual) \ - do \ - { \ - const char *str = #actual; \ - bool expected__ = (expected); \ - bool actual__ = (actual); \ - \ - if (expected__ != actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected: %d Actual: %d\n", \ - __FILE__, __func__, __LINE__, str, expected__, actual__); \ - } \ - \ +#define cmc_assert_equals__Bool(expected, actual) \ + do \ + { \ + const char *str = #actual; \ + bool expected__ = (expected); \ + bool actual__ = (actual); \ + \ + if (expected__ != actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected: %d Actual: %d\n", \ + __FILE__, __func__, __LINE__, str, expected__, actual__); \ + } \ + \ } while (0) /** --------------------------------------------------------------------------- @@ -619,274 +657,300 @@ static bool cmc_assert_state = true; * * ------------------------------------------------------------------------ **/ -#define cmc_assert_not_equals_int8_t(not_expected, actual) \ - do \ - { \ - const char *str = #actual; \ - int8_t not_expected__ = (not_expected); \ - int8_t actual__ = (actual); \ - \ - if (not_expected__ == actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %" PRId8 " Actual: %" PRId8 "\n", \ - __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ - } \ - \ +#define cmc_assert_not_equals_int8_t(not_expected, actual) \ + do \ + { \ + const char *str = #actual; \ + int8_t not_expected__ = (not_expected); \ + int8_t actual__ = (actual); \ + \ + if (not_expected__ == actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %" PRId8 \ + " Actual: %" PRId8 "\n", \ + __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_equals_int16_t(not_expected, actual) \ - do \ - { \ - const char *str = #actual; \ - int16_t not_expected__ = (not_expected); \ - int16_t actual__ = (actual); \ - \ - if (not_expected__ == actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %" PRId16 " Actual: %" PRId16 "\n", \ - __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ - } \ - \ +#define cmc_assert_not_equals_int16_t(not_expected, actual) \ + do \ + { \ + const char *str = #actual; \ + int16_t not_expected__ = (not_expected); \ + int16_t actual__ = (actual); \ + \ + if (not_expected__ == actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %" PRId16 \ + " Actual: %" PRId16 "\n", \ + __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_equals_int32_t(not_expected, actual) \ - do \ - { \ - const char *str = #actual; \ - int32_t not_expected__ = (not_expected); \ - int32_t actual__ = (actual); \ - \ - if (not_expected__ == actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %" PRId32 " Actual: %" PRId32 "\n", \ - __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ - } \ - \ +#define cmc_assert_not_equals_int32_t(not_expected, actual) \ + do \ + { \ + const char *str = #actual; \ + int32_t not_expected__ = (not_expected); \ + int32_t actual__ = (actual); \ + \ + if (not_expected__ == actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %" PRId32 \ + " Actual: %" PRId32 "\n", \ + __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_equals_int64_t(not_expected, actual) \ - do \ - { \ - const char *str = #actual; \ - int64_t not_expected__ = (not_expected); \ - int64_t actual__ = (actual); \ - \ - if (not_expected__ == actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %" PRId64 " Actual: %" PRId64 "\n", \ - __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ - } \ - \ +#define cmc_assert_not_equals_int64_t(not_expected, actual) \ + do \ + { \ + const char *str = #actual; \ + int64_t not_expected__ = (not_expected); \ + int64_t actual__ = (actual); \ + \ + if (not_expected__ == actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %" PRId64 \ + " Actual: %" PRId64 "\n", \ + __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_equals_uint8_t(not_expected, actual) \ - do \ - { \ - const char *str = #actual; \ - uint8_t not_expected__ = (not_expected); \ - uint8_t actual__ = (actual); \ - \ - if (not_expected__ == actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %" PRIu8 " Actual: %" PRIu8 "\n", \ - __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ - } \ - \ +#define cmc_assert_not_equals_uint8_t(not_expected, actual) \ + do \ + { \ + const char *str = #actual; \ + uint8_t not_expected__ = (not_expected); \ + uint8_t actual__ = (actual); \ + \ + if (not_expected__ == actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %" PRIu8 \ + " Actual: %" PRIu8 "\n", \ + __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_equals_uint16_t(not_expected, actual) \ - do \ - { \ - const char *str = #actual; \ - uint16_t not_expected__ = (not_expected); \ - uint16_t actual__ = (actual); \ - \ - if (not_expected__ == actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %" PRIu16 " Actual: %" PRIu16 "\n", \ - __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ - } \ - \ +#define cmc_assert_not_equals_uint16_t(not_expected, actual) \ + do \ + { \ + const char *str = #actual; \ + uint16_t not_expected__ = (not_expected); \ + uint16_t actual__ = (actual); \ + \ + if (not_expected__ == actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %" PRIu16 \ + " Actual: %" PRIu16 "\n", \ + __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_equals_uint32_t(not_expected, actual) \ - do \ - { \ - const char *str = #actual; \ - uint32_t not_expected__ = (not_expected); \ - uint32_t actual__ = (actual); \ - \ - if (not_expected__ == actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %" PRIu32 " Actual: %" PRIu32 "\n", \ - __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ - } \ - \ +#define cmc_assert_not_equals_uint32_t(not_expected, actual) \ + do \ + { \ + const char *str = #actual; \ + uint32_t not_expected__ = (not_expected); \ + uint32_t actual__ = (actual); \ + \ + if (not_expected__ == actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %" PRIu32 \ + " Actual: %" PRIu32 "\n", \ + __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_equals_uint64_t(not_expected, actual) \ - do \ - { \ - const char *str = #actual; \ - uint64_t not_expected__ = (not_expected); \ - uint64_t actual__ = (actual); \ - \ - if (not_expected__ == actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %" PRIu64 " Actual: %" PRIu64 "\n", \ - __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ - } \ - \ +#define cmc_assert_not_equals_uint64_t(not_expected, actual) \ + do \ + { \ + const char *str = #actual; \ + uint64_t not_expected__ = (not_expected); \ + uint64_t actual__ = (actual); \ + \ + if (not_expected__ == actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %" PRIu64 \ + " Actual: %" PRIu64 "\n", \ + __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_equals_intmax_t(not_expected, actual) \ - do \ - { \ - const char *str = #actual; \ - intmax_t not_expected__ = (not_expected); \ - intmax_t actual__ = (actual); \ - \ - if (not_expected__ == actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %" PRIdMAX " Actual: %" PRIdMAX "\n", \ - __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ - } \ - \ +#define cmc_assert_not_equals_intmax_t(not_expected, actual) \ + do \ + { \ + const char *str = #actual; \ + intmax_t not_expected__ = (not_expected); \ + intmax_t actual__ = (actual); \ + \ + if (not_expected__ == actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %" PRIdMAX \ + " Actual: %" PRIdMAX "\n", \ + __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_equals_uintmax_t(not_expected, actual) \ - do \ - { \ - const char *str = #actual; \ - uintmax_t not_expected__ = (not_expected); \ - uintmax_t actual__ = (actual); \ - \ - if (not_expected__ == actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %" PRIuMAX " Actual: %" PRIuMAX "\n", \ - __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ - } \ - \ +#define cmc_assert_not_equals_uintmax_t(not_expected, actual) \ + do \ + { \ + const char *str = #actual; \ + uintmax_t not_expected__ = (not_expected); \ + uintmax_t actual__ = (actual); \ + \ + if (not_expected__ == actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %" PRIuMAX \ + " Actual: %" PRIuMAX "\n", \ + __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_equals_size_t(not_expected, actual) \ - do \ - { \ - const char *str = #actual; \ - size_t not_expected__ = (not_expected); \ - size_t actual__ = (actual); \ - \ - if (not_expected__ == actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %" PRIuMAX " Actual: %" PRIuMAX "\n", \ - __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ - } \ - \ +#define cmc_assert_not_equals_size_t(not_expected, actual) \ + do \ + { \ + const char *str = #actual; \ + size_t not_expected__ = (not_expected); \ + size_t actual__ = (actual); \ + \ + if (not_expected__ == actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %" PRIuMAX \ + " Actual: %" PRIuMAX "\n", \ + __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_equals_float(not_expected, actual) \ - do \ - { \ - const char *str = #actual; \ - float not_expected__ = (not_expected); \ - float actual__ = (actual); \ - \ - if (not_expected__ == actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %f Actual: %f\n", \ - __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ - } \ - \ +#define cmc_assert_not_equals_float(not_expected, actual) \ + do \ + { \ + const char *str = #actual; \ + float not_expected__ = (not_expected); \ + float actual__ = (actual); \ + \ + if (not_expected__ == actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %f Actual: %f\n", \ + __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_equals_double(not_expected, actual) \ - do \ - { \ - const char *str = #actual; \ - double not_expected__ = (not_expected); \ - double actual__ = (actual); \ - \ - if (not_expected__ == actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %lf Actual: %lf\n", \ - __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ - } \ - \ +#define cmc_assert_not_equals_double(not_expected, actual) \ + do \ + { \ + const char *str = #actual; \ + double not_expected__ = (not_expected); \ + double actual__ = (actual); \ + \ + if (not_expected__ == actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %lf Actual: %lf\n", \ + __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_equals_ptr(not_expected, actual) \ - do \ - { \ - const char *str = #actual; \ - void *not_expected__ = (not_expected); \ - void *actual__ = (actual); \ - \ - if (not_expected__ == actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %p Actual: %p\n", \ - __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ - } \ - \ +#define cmc_assert_not_equals_ptr(not_expected, actual) \ + do \ + { \ + const char *str = #actual; \ + void *not_expected__ = (not_expected); \ + void *actual__ = (actual); \ + \ + if (not_expected__ == actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %p Actual: %p\n", \ + __FILE__, __func__, __LINE__, str, not_expected__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_equals__Bool(expected, actual) \ - do \ - { \ - const char *str = #actual; \ - bool expected__ = (expected); \ - bool actual__ = (actual); \ - \ - if (expected__ == actual__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %d Actual: %d\n", \ - __FILE__, __func__, __LINE__, str, expected__, actual__); \ - } \ - \ +#define cmc_assert_not_equals__Bool(expected, actual) \ + do \ + { \ + const char *str = #actual; \ + bool expected__ = (expected); \ + bool actual__ = (actual); \ + \ + if (expected__ == actual__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected: %d Actual: %d\n", \ + __FILE__, __func__, __LINE__, str, expected__, actual__); \ + } \ + \ } while (0) /** --------------------------------------------------------------------------- @@ -895,238 +959,262 @@ static bool cmc_assert_state = true; * * ------------------------------------------------------------------------ **/ -#define cmc_assert_greater_int8_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - int8_t boundary__ = (boundary); \ - int8_t actual__ = (actual); \ - \ - if (actual__ <= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %" PRId8 " Actual: %" PRId8 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_int8_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + int8_t boundary__ = (boundary); \ + int8_t actual__ = (actual); \ + \ + if (actual__ <= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %" PRId8 \ + " Actual: %" PRId8 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_greater_int16_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - int16_t boundary__ = (boundary); \ - int16_t actual__ = (actual); \ - \ - if (actual__ <= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %" PRId16 " Actual: %" PRId16 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_int16_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + int16_t boundary__ = (boundary); \ + int16_t actual__ = (actual); \ + \ + if (actual__ <= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %" PRId16 \ + " Actual: %" PRId16 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_greater_int32_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - int32_t boundary__ = (boundary); \ - int32_t actual__ = (actual); \ - \ - if (actual__ <= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %" PRId32 " Actual: %" PRId32 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_int32_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + int32_t boundary__ = (boundary); \ + int32_t actual__ = (actual); \ + \ + if (actual__ <= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %" PRId32 \ + " Actual: %" PRId32 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_greater_int64_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - int64_t boundary__ = (boundary); \ - int64_t actual__ = (actual); \ - \ - if (actual__ <= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %" PRId64 " Actual: %" PRId64 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_int64_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + int64_t boundary__ = (boundary); \ + int64_t actual__ = (actual); \ + \ + if (actual__ <= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %" PRId64 \ + " Actual: %" PRId64 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_greater_uint8_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - uint8_t boundary__ = (boundary); \ - uint8_t actual__ = (actual); \ - \ - if (actual__ <= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %" PRIu8 " Actual: %" PRIu8 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_uint8_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + uint8_t boundary__ = (boundary); \ + uint8_t actual__ = (actual); \ + \ + if (actual__ <= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %" PRIu8 \ + " Actual: %" PRIu8 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_greater_uint16_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - uint16_t boundary__ = (boundary); \ - uint16_t actual__ = (actual); \ - \ - if (actual__ <= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %" PRIu16 " Actual: %" PRIu16 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_uint16_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + uint16_t boundary__ = (boundary); \ + uint16_t actual__ = (actual); \ + \ + if (actual__ <= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %" PRIu16 \ + " Actual: %" PRIu16 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_greater_uint32_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - uint32_t boundary__ = (boundary); \ - uint32_t actual__ = (actual); \ - \ - if (actual__ <= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %" PRIu32 " Actual: %" PRIu32 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_uint32_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + uint32_t boundary__ = (boundary); \ + uint32_t actual__ = (actual); \ + \ + if (actual__ <= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %" PRIu32 \ + " Actual: %" PRIu32 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_greater_uint64_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - uint64_t boundary__ = (boundary); \ - uint64_t actual__ = (actual); \ - \ - if (actual__ <= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %" PRIu64 " Actual: %" PRIu64 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_uint64_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + uint64_t boundary__ = (boundary); \ + uint64_t actual__ = (actual); \ + \ + if (actual__ <= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %" PRIu64 \ + " Actual: %" PRIu64 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_greater_intmax_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - intmax_t boundary__ = (boundary); \ - intmax_t actual__ = (actual); \ - \ - if (actual__ <= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %" PRIdMAX " Actual: %" PRIdMAX "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_intmax_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + intmax_t boundary__ = (boundary); \ + intmax_t actual__ = (actual); \ + \ + if (actual__ <= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %" PRIdMAX \ + " Actual: %" PRIdMAX "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_greater_uintmax_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - uintmax_t boundary__ = (boundary); \ - uintmax_t actual__ = (actual); \ - \ - if (actual__ <= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %" PRIuMAX " Actual: %" PRIuMAX "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_uintmax_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + uintmax_t boundary__ = (boundary); \ + uintmax_t actual__ = (actual); \ + \ + if (actual__ <= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %" PRIuMAX \ + " Actual: %" PRIuMAX "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_greater_size_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - size_t boundary__ = (boundary); \ - size_t actual__ = (actual); \ - \ - if (actual__ <= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %" PRIuMAX " Actual: %" PRIuMAX "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_size_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + size_t boundary__ = (boundary); \ + size_t actual__ = (actual); \ + \ + if (actual__ <= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %" PRIuMAX \ + " Actual: %" PRIuMAX "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_greater_float(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - float boundary__ = (boundary); \ - float actual__ = (actual); \ - \ - if (actual__ <= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %f Actual: %f\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_float(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + float boundary__ = (boundary); \ + float actual__ = (actual); \ + \ + if (actual__ <= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %f Actual: %f\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_greater_double(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - double boundary__ = (boundary); \ - double actual__ = (actual); \ - \ - if (actual__ <= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %lf Actual: %lf\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_double(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + double boundary__ = (boundary); \ + double actual__ = (actual); \ + \ + if (actual__ <= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater: %lf Actual: %lf\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) /** --------------------------------------------------------------------------- @@ -1135,238 +1223,262 @@ static bool cmc_assert_state = true; * * ------------------------------------------------------------------------ **/ -#define cmc_assert_greater_equals_int8_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - int8_t boundary__ = (boundary); \ - int8_t actual__ = (actual); \ - \ - if (actual__ < boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %" PRId8 " Actual: %" PRId8 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_equals_int8_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + int8_t boundary__ = (boundary); \ + int8_t actual__ = (actual); \ + \ + if (actual__ < boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %" PRId8 \ + " Actual: %" PRId8 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_greater_equals_int16_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - int16_t boundary__ = (boundary); \ - int16_t actual__ = (actual); \ - \ - if (actual__ < boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %" PRId16 " Actual: %" PRId16 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_equals_int16_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + int16_t boundary__ = (boundary); \ + int16_t actual__ = (actual); \ + \ + if (actual__ < boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %" PRId16 \ + " Actual: %" PRId16 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_greater_equals_int32_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - int32_t boundary__ = (boundary); \ - int32_t actual__ = (actual); \ - \ - if (actual__ < boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %" PRId32 " Actual: %" PRId32 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_equals_int32_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + int32_t boundary__ = (boundary); \ + int32_t actual__ = (actual); \ + \ + if (actual__ < boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %" PRId32 \ + " Actual: %" PRId32 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_greater_equals_int64_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - int64_t boundary__ = (boundary); \ - int64_t actual__ = (actual); \ - \ - if (actual__ < boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %" PRId64 " Actual: %" PRId64 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_equals_int64_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + int64_t boundary__ = (boundary); \ + int64_t actual__ = (actual); \ + \ + if (actual__ < boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %" PRId64 \ + " Actual: %" PRId64 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_greater_equals_uint8_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - uint8_t boundary__ = (boundary); \ - uint8_t actual__ = (actual); \ - \ - if (actual__ < boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %" PRIu8 " Actual: %" PRIu8 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_equals_uint8_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + uint8_t boundary__ = (boundary); \ + uint8_t actual__ = (actual); \ + \ + if (actual__ < boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %" PRIu8 \ + " Actual: %" PRIu8 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_greater_equals_uint16_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - uint16_t boundary__ = (boundary); \ - uint16_t actual__ = (actual); \ - \ - if (actual__ < boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %" PRIu16 " Actual: %" PRIu16 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_equals_uint16_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + uint16_t boundary__ = (boundary); \ + uint16_t actual__ = (actual); \ + \ + if (actual__ < boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %" PRIu16 \ + " Actual: %" PRIu16 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_greater_equals_uint32_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - uint32_t boundary__ = (boundary); \ - uint32_t actual__ = (actual); \ - \ - if (actual__ < boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %" PRIu32 " Actual: %" PRIu32 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_equals_uint32_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + uint32_t boundary__ = (boundary); \ + uint32_t actual__ = (actual); \ + \ + if (actual__ < boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %" PRIu32 \ + " Actual: %" PRIu32 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_greater_equals_uint64_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - uint64_t boundary__ = (boundary); \ - uint64_t actual__ = (actual); \ - \ - if (actual__ < boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %" PRIu64 " Actual: %" PRIu64 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_equals_uint64_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + uint64_t boundary__ = (boundary); \ + uint64_t actual__ = (actual); \ + \ + if (actual__ < boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %" PRIu64 \ + " Actual: %" PRIu64 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_greater_equals_intmax_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - intmax_t boundary__ = (boundary); \ - intmax_t actual__ = (actual); \ - \ - if (actual__ < boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %" PRIdMAX " Actual: %" PRIdMAX "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_equals_intmax_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + intmax_t boundary__ = (boundary); \ + intmax_t actual__ = (actual); \ + \ + if (actual__ < boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %" PRIdMAX \ + " Actual: %" PRIdMAX "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_greater_equals_uintmax_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - uintmax_t boundary__ = (boundary); \ - uintmax_t actual__ = (actual); \ - \ - if (actual__ < boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %" PRIuMAX " Actual: %" PRIuMAX "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_equals_uintmax_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + uintmax_t boundary__ = (boundary); \ + uintmax_t actual__ = (actual); \ + \ + if (actual__ < boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %" PRIuMAX \ + " Actual: %" PRIuMAX "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_greater_equals_size_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - size_t boundary__ = (boundary); \ - size_t actual__ = (actual); \ - \ - if (actual__ < boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %" PRIuMAX " Actual: %" PRIuMAX "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_equals_size_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + size_t boundary__ = (boundary); \ + size_t actual__ = (actual); \ + \ + if (actual__ < boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %" PRIuMAX \ + " Actual: %" PRIuMAX "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_greater_equals_float(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - float boundary__ = (boundary); \ - float actual__ = (actual); \ - \ - if (actual__ < boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %f Actual: %f\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_equals_float(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + float boundary__ = (boundary); \ + float actual__ = (actual); \ + \ + if (actual__ < boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %f Actual: %f\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_greater_equals_double(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - double boundary__ = (boundary); \ - double actual__ = (actual); \ - \ - if (actual__ < boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %lf Actual: %lf\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_greater_equals_double(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + double boundary__ = (boundary); \ + double actual__ = (actual); \ + \ + if (actual__ < boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Greater or Equals: %lf Actual: %lf\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) /** --------------------------------------------------------------------------- @@ -1375,238 +1487,262 @@ static bool cmc_assert_state = true; * * ------------------------------------------------------------------------ **/ -#define cmc_assert_lesser_int8_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - int8_t boundary__ = (boundary); \ - int8_t actual__ = (actual); \ - \ - if (actual__ >= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %" PRId8 " Actual: %" PRId8 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_int8_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + int8_t boundary__ = (boundary); \ + int8_t actual__ = (actual); \ + \ + if (actual__ >= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %" PRId8 \ + " Actual: %" PRId8 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_lesser_int16_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - int16_t boundary__ = (boundary); \ - int16_t actual__ = (actual); \ - \ - if (actual__ >= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %" PRId16 " Actual: %" PRId16 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_int16_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + int16_t boundary__ = (boundary); \ + int16_t actual__ = (actual); \ + \ + if (actual__ >= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %" PRId16 \ + " Actual: %" PRId16 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_lesser_int32_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - int32_t boundary__ = (boundary); \ - int32_t actual__ = (actual); \ - \ - if (actual__ >= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %" PRId32 " Actual: %" PRId32 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_int32_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + int32_t boundary__ = (boundary); \ + int32_t actual__ = (actual); \ + \ + if (actual__ >= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %" PRId32 \ + " Actual: %" PRId32 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_lesser_int64_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - int64_t boundary__ = (boundary); \ - int64_t actual__ = (actual); \ - \ - if (actual__ >= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %" PRId64 " Actual: %" PRId64 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_int64_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + int64_t boundary__ = (boundary); \ + int64_t actual__ = (actual); \ + \ + if (actual__ >= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %" PRId64 \ + " Actual: %" PRId64 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_lesser_uint8_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - uint8_t boundary__ = (boundary); \ - uint8_t actual__ = (actual); \ - \ - if (actual__ >= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %" PRIu8 " Actual: %" PRIu8 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_uint8_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + uint8_t boundary__ = (boundary); \ + uint8_t actual__ = (actual); \ + \ + if (actual__ >= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %" PRIu8 \ + " Actual: %" PRIu8 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_lesser_uint16_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - uint16_t boundary__ = (boundary); \ - uint16_t actual__ = (actual); \ - \ - if (actual__ >= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %" PRIu16 " Actual: %" PRIu16 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_uint16_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + uint16_t boundary__ = (boundary); \ + uint16_t actual__ = (actual); \ + \ + if (actual__ >= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %" PRIu16 \ + " Actual: %" PRIu16 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_lesser_uint32_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - uint32_t boundary__ = (boundary); \ - uint32_t actual__ = (actual); \ - \ - if (actual__ >= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %" PRIu32 " Actual: %" PRIu32 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_uint32_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + uint32_t boundary__ = (boundary); \ + uint32_t actual__ = (actual); \ + \ + if (actual__ >= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %" PRIu32 \ + " Actual: %" PRIu32 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_lesser_uint64_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - uint64_t boundary__ = (boundary); \ - uint64_t actual__ = (actual); \ - \ - if (actual__ >= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %" PRIu64 " Actual: %" PRIu64 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_uint64_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + uint64_t boundary__ = (boundary); \ + uint64_t actual__ = (actual); \ + \ + if (actual__ >= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %" PRIu64 \ + " Actual: %" PRIu64 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_lesser_intmax_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - intmax_t boundary__ = (boundary); \ - intmax_t actual__ = (actual); \ - \ - if (actual__ >= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %" PRIdMAX " Actual: %" PRIdMAX "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_intmax_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + intmax_t boundary__ = (boundary); \ + intmax_t actual__ = (actual); \ + \ + if (actual__ >= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %" PRIdMAX \ + " Actual: %" PRIdMAX "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_lesser_uintmax_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - uintmax_t boundary__ = (boundary); \ - uintmax_t actual__ = (actual); \ - \ - if (actual__ >= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %" PRIuMAX " Actual: %" PRIuMAX "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_uintmax_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + uintmax_t boundary__ = (boundary); \ + uintmax_t actual__ = (actual); \ + \ + if (actual__ >= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %" PRIuMAX \ + " Actual: %" PRIuMAX "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_lesser_size_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - size_t boundary__ = (boundary); \ - size_t actual__ = (actual); \ - \ - if (actual__ >= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %" PRIuMAX " Actual: %" PRIuMAX "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_size_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + size_t boundary__ = (boundary); \ + size_t actual__ = (actual); \ + \ + if (actual__ >= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %" PRIuMAX \ + " Actual: %" PRIuMAX "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_lesser_float(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - float boundary__ = (boundary); \ - float actual__ = (actual); \ - \ - if (actual__ >= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %f Actual: %f\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_float(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + float boundary__ = (boundary); \ + float actual__ = (actual); \ + \ + if (actual__ >= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %f Actual: %f\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_lesser_double(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - double boundary__ = (boundary); \ - double actual__ = (actual); \ - \ - if (actual__ >= boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %lf Actual: %lf\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_double(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + double boundary__ = (boundary); \ + double actual__ = (actual); \ + \ + if (actual__ >= boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser: %lf Actual: %lf\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) /** --------------------------------------------------------------------------- @@ -1615,238 +1751,262 @@ static bool cmc_assert_state = true; * * ------------------------------------------------------------------------ **/ -#define cmc_assert_lesser_equals_int8_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - int8_t boundary__ = (boundary); \ - int8_t actual__ = (actual); \ - \ - if (actual__ > boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %" PRId8 " Actual: %" PRId8 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_equals_int8_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + int8_t boundary__ = (boundary); \ + int8_t actual__ = (actual); \ + \ + if (actual__ > boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %" PRId8 \ + " Actual: %" PRId8 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_lesser_equals_int16_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - int16_t boundary__ = (boundary); \ - int16_t actual__ = (actual); \ - \ - if (actual__ > boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %" PRId16 " Actual: %" PRId16 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_equals_int16_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + int16_t boundary__ = (boundary); \ + int16_t actual__ = (actual); \ + \ + if (actual__ > boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %" PRId16 \ + " Actual: %" PRId16 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_lesser_equals_int32_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - int32_t boundary__ = (boundary); \ - int32_t actual__ = (actual); \ - \ - if (actual__ > boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %" PRId32 " Actual: %" PRId32 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_equals_int32_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + int32_t boundary__ = (boundary); \ + int32_t actual__ = (actual); \ + \ + if (actual__ > boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %" PRId32 \ + " Actual: %" PRId32 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_lesser_equals_int64_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - int64_t boundary__ = (boundary); \ - int64_t actual__ = (actual); \ - \ - if (actual__ > boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %" PRId64 " Actual: %" PRId64 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_equals_int64_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + int64_t boundary__ = (boundary); \ + int64_t actual__ = (actual); \ + \ + if (actual__ > boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %" PRId64 \ + " Actual: %" PRId64 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_lesser_equals_uint8_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - uint8_t boundary__ = (boundary); \ - uint8_t actual__ = (actual); \ - \ - if (actual__ > boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %" PRIu8 " Actual: %" PRIu8 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_equals_uint8_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + uint8_t boundary__ = (boundary); \ + uint8_t actual__ = (actual); \ + \ + if (actual__ > boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %" PRIu8 \ + " Actual: %" PRIu8 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_lesser_equals_uint16_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - uint16_t boundary__ = (boundary); \ - uint16_t actual__ = (actual); \ - \ - if (actual__ > boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %" PRIu16 " Actual: %" PRIu16 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_equals_uint16_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + uint16_t boundary__ = (boundary); \ + uint16_t actual__ = (actual); \ + \ + if (actual__ > boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %" PRIu16 \ + " Actual: %" PRIu16 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_lesser_equals_uint32_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - uint32_t boundary__ = (boundary); \ - uint32_t actual__ = (actual); \ - \ - if (actual__ > boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %" PRIu32 " Actual: %" PRIu32 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_equals_uint32_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + uint32_t boundary__ = (boundary); \ + uint32_t actual__ = (actual); \ + \ + if (actual__ > boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %" PRIu32 \ + " Actual: %" PRIu32 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_lesser_equals_uint64_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - uint64_t boundary__ = (boundary); \ - uint64_t actual__ = (actual); \ - \ - if (actual__ > boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %" PRIu64 " Actual: %" PRIu64 "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_equals_uint64_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + uint64_t boundary__ = (boundary); \ + uint64_t actual__ = (actual); \ + \ + if (actual__ > boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %" PRIu64 \ + " Actual: %" PRIu64 "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_lesser_equals_intmax_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - intmax_t boundary__ = (boundary); \ - intmax_t actual__ = (actual); \ - \ - if (actual__ > boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %" PRIdMAX " Actual: %" PRIdMAX "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_equals_intmax_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + intmax_t boundary__ = (boundary); \ + intmax_t actual__ = (actual); \ + \ + if (actual__ > boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %" PRIdMAX \ + " Actual: %" PRIdMAX "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_lesser_equals_uintmax_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - uintmax_t boundary__ = (boundary); \ - uintmax_t actual__ = (actual); \ - \ - if (actual__ > boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %" PRIuMAX " Actual: %" PRIuMAX "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_equals_uintmax_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + uintmax_t boundary__ = (boundary); \ + uintmax_t actual__ = (actual); \ + \ + if (actual__ > boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %" PRIuMAX \ + " Actual: %" PRIuMAX "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_lesser_equals_size_t(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - size_t boundary__ = (boundary); \ - size_t actual__ = (actual); \ - \ - if (actual__ > boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %" PRIuMAX " Actual: %" PRIuMAX "\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_equals_size_t(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + size_t boundary__ = (boundary); \ + size_t actual__ = (actual); \ + \ + if (actual__ > boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %" PRIuMAX \ + " Actual: %" PRIuMAX "\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_lesser_equals_float(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - float boundary__ = (boundary); \ - float actual__ = (actual); \ - \ - if (actual__ > boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %f Actual: %f\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_equals_float(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + float boundary__ = (boundary); \ + float actual__ = (actual); \ + \ + if (actual__ > boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %f Actual: %f\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_lesser_equals_double(boundary, actual) \ - do \ - { \ - const char *str = #actual; \ - double boundary__ = (boundary); \ - double actual__ = (actual); \ - \ - if (actual__ > boundary__) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %lf Actual: %lf\n", \ - __FILE__, __func__, __LINE__, str, boundary__, actual__); \ - } \ - \ +#define cmc_assert_lesser_equals_double(boundary, actual) \ + do \ + { \ + const char *str = #actual; \ + double boundary__ = (boundary); \ + double actual__ = (actual); \ + \ + if (actual__ > boundary__) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Lesser or Equals: %lf Actual: %lf\n", \ + __FILE__, __func__, __LINE__, str, boundary__, actual__); \ + } \ + \ } while (0) /** --------------------------------------------------------------------------- @@ -1855,251 +2015,288 @@ static bool cmc_assert_state = true; * * ------------------------------------------------------------------------ **/ -#define cmc_assert_in_range_int8_t(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - int8_t lower_bound__ = (lower_bound); \ - int8_t upper_bound__ = (upper_bound); \ - int8_t actual__ = (actual); \ - \ - if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%" PRId8 ", %" PRId8 "] Actual: %" PRId8 "\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_in_range_int8_t(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + int8_t lower_bound__ = (lower_bound); \ + int8_t upper_bound__ = (upper_bound); \ + int8_t actual__ = (actual); \ + \ + if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%" PRId8 \ + ", %" PRId8 "] Actual: %" PRId8 "\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_in_range_int16_t(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - int16_t lower_bound__ = (lower_bound); \ - int16_t upper_bound__ = (upper_bound); \ - int16_t actual__ = (actual); \ - \ - if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%" PRId16 ", %" PRId16 "] Actual: %" PRId16 "\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_in_range_int16_t(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + int16_t lower_bound__ = (lower_bound); \ + int16_t upper_bound__ = (upper_bound); \ + int16_t actual__ = (actual); \ + \ + if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%" PRId16 \ + ", %" PRId16 "] Actual: %" PRId16 "\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_in_range_int32_t(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - int32_t lower_bound__ = (lower_bound); \ - int32_t upper_bound__ = (upper_bound); \ - int32_t actual__ = (actual); \ - \ - if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%" PRId32 ", %" PRId32 "] Actual: %" PRId32 "\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_in_range_int32_t(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + int32_t lower_bound__ = (lower_bound); \ + int32_t upper_bound__ = (upper_bound); \ + int32_t actual__ = (actual); \ + \ + if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%" PRId32 \ + ", %" PRId32 "] Actual: %" PRId32 "\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_in_range_int64_t(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - int64_t lower_bound__ = (lower_bound); \ - int64_t upper_bound__ = (upper_bound); \ - int64_t actual__ = (actual); \ - \ - if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%" PRId32 ", %" PRId32 "] Actual: %" PRId32 "\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_in_range_int64_t(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + int64_t lower_bound__ = (lower_bound); \ + int64_t upper_bound__ = (upper_bound); \ + int64_t actual__ = (actual); \ + \ + if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%" PRId32 \ + ", %" PRId32 "] Actual: %" PRId32 "\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_in_range_uint8_t(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - uint8_t lower_bound__ = (lower_bound); \ - uint8_t upper_bound__ = (upper_bound); \ - uint8_t actual__ = (actual); \ - \ - if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%" PRIu8 ", %" PRIu8 "] Actual: %" PRIu8 "\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_in_range_uint8_t(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + uint8_t lower_bound__ = (lower_bound); \ + uint8_t upper_bound__ = (upper_bound); \ + uint8_t actual__ = (actual); \ + \ + if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%" PRIu8 \ + ", %" PRIu8 "] Actual: %" PRIu8 "\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_in_range_uint16_t(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - uint16_t lower_bound__ = (lower_bound); \ - uint16_t upper_bound__ = (upper_bound); \ - uint16_t actual__ = (actual); \ - \ - if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%" PRIu16 ", %" PRIu16 "] Actual: %" PRIu16 "\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_in_range_uint16_t(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + uint16_t lower_bound__ = (lower_bound); \ + uint16_t upper_bound__ = (upper_bound); \ + uint16_t actual__ = (actual); \ + \ + if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%" PRIu16 \ + ", %" PRIu16 "] Actual: %" PRIu16 "\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_in_range_uint32_t(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - uint32_t lower_bound__ = (lower_bound); \ - uint32_t upper_bound__ = (upper_bound); \ - uint32_t actual__ = (actual); \ - \ - if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%" PRIu32 ", %" PRIu32 "] Actual: %" PRIu32 "\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_in_range_uint32_t(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + uint32_t lower_bound__ = (lower_bound); \ + uint32_t upper_bound__ = (upper_bound); \ + uint32_t actual__ = (actual); \ + \ + if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%" PRIu32 \ + ", %" PRIu32 "] Actual: %" PRIu32 "\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_in_range_uint64_t(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - uint64_t lower_bound__ = (lower_bound); \ - uint64_t upper_bound__ = (upper_bound); \ - uint64_t actual__ = (actual); \ - \ - if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%" PRIu64 ", %" PRIu64 "] Actual: %" PRIu64 "\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_in_range_uint64_t(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + uint64_t lower_bound__ = (lower_bound); \ + uint64_t upper_bound__ = (upper_bound); \ + uint64_t actual__ = (actual); \ + \ + if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%" PRIu64 \ + ", %" PRIu64 "] Actual: %" PRIu64 "\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_in_range_intmax_t(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - intmax_t lower_bound__ = (lower_bound); \ - intmax_t upper_bound__ = (upper_bound); \ - intmax_t actual__ = (actual); \ - \ - if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%" PRIdMAX ", %" PRIdMAX "] Actual: %" PRIdMAX "\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_in_range_intmax_t(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + intmax_t lower_bound__ = (lower_bound); \ + intmax_t upper_bound__ = (upper_bound); \ + intmax_t actual__ = (actual); \ + \ + if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%" PRIdMAX \ + ", %" PRIdMAX "] Actual: %" PRIdMAX "\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_in_range_uintmax_t(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - uintmax_t lower_bound__ = (lower_bound); \ - uintmax_t upper_bound__ = (upper_bound); \ - uintmax_t actual__ = (actual); \ - \ - if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%" PRIuMAX ", %" PRIuMAX "] Actual: %" PRIuMAX "\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_in_range_uintmax_t(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + uintmax_t lower_bound__ = (lower_bound); \ + uintmax_t upper_bound__ = (upper_bound); \ + uintmax_t actual__ = (actual); \ + \ + if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%" PRIuMAX \ + ", %" PRIuMAX "] Actual: %" PRIuMAX "\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_in_range_size_t(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - size_t lower_bound__ = (lower_bound); \ - size_t upper_bound__ = (upper_bound); \ - size_t actual__ = (actual); \ - \ - if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%" PRIuMAX ", %" PRIuMAX "] Actual: %" PRIuMAX "\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_in_range_size_t(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + size_t lower_bound__ = (lower_bound); \ + size_t upper_bound__ = (upper_bound); \ + size_t actual__ = (actual); \ + \ + if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%" PRIuMAX \ + ", %" PRIuMAX "] Actual: %" PRIuMAX "\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_in_range_float(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - float lower_bound__ = (lower_bound); \ - float upper_bound__ = (upper_bound); \ - float actual__ = (actual); \ - \ - if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%f, %f] Actual: %f\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_in_range_float(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + float lower_bound__ = (lower_bound); \ + float upper_bound__ = (upper_bound); \ + float actual__ = (actual); \ + \ + if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%f, %f] Actual: %f\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_in_range_double(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - double lower_bound__ = (lower_bound); \ - double upper_bound__ = (upper_bound); \ - double actual__ = (actual); \ - \ - if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%lf, %lf] Actual: %lf\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_in_range_double(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + double lower_bound__ = (lower_bound); \ + double upper_bound__ = (upper_bound); \ + double actual__ = (actual); \ + \ + if ((actual__) < (lower_bound__) || (actual__) > (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Expected Range: [%lf, %lf] Actual: %lf\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) /** --------------------------------------------------------------------------- @@ -2108,251 +2305,288 @@ static bool cmc_assert_state = true; * * ------------------------------------------------------------------------ **/ -#define cmc_assert_not_in_range_int8_t(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - int8_t lower_bound__ = (lower_bound); \ - int8_t upper_bound__ = (upper_bound); \ - int8_t actual__ = (actual); \ - \ - if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%" PRId8 ", %" PRId8 "] Actual: %" PRId8 "\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_not_in_range_int8_t(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + int8_t lower_bound__ = (lower_bound); \ + int8_t upper_bound__ = (upper_bound); \ + int8_t actual__ = (actual); \ + \ + if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%" PRId8 \ + ", %" PRId8 "] Actual: %" PRId8 "\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_in_range_int16_t(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - int16_t lower_bound__ = (lower_bound); \ - int16_t upper_bound__ = (upper_bound); \ - int16_t actual__ = (actual); \ - \ - if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%" PRId16 ", %" PRId16 "] Actual: %" PRId16 "\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_not_in_range_int16_t(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + int16_t lower_bound__ = (lower_bound); \ + int16_t upper_bound__ = (upper_bound); \ + int16_t actual__ = (actual); \ + \ + if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%" PRId16 \ + ", %" PRId16 "] Actual: %" PRId16 "\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_in_range_int32_t(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - int32_t lower_bound__ = (lower_bound); \ - int32_t upper_bound__ = (upper_bound); \ - int32_t actual__ = (actual); \ - \ - if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%" PRId32 ", %" PRId32 "] Actual: %" PRId32 "\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_not_in_range_int32_t(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + int32_t lower_bound__ = (lower_bound); \ + int32_t upper_bound__ = (upper_bound); \ + int32_t actual__ = (actual); \ + \ + if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%" PRId32 \ + ", %" PRId32 "] Actual: %" PRId32 "\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_in_range_int64_t(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - int64_t lower_bound__ = (lower_bound); \ - int64_t upper_bound__ = (upper_bound); \ - int64_t actual__ = (actual); \ - \ - if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%" PRId32 ", %" PRId32 "] Actual: %" PRId32 "\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_not_in_range_int64_t(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + int64_t lower_bound__ = (lower_bound); \ + int64_t upper_bound__ = (upper_bound); \ + int64_t actual__ = (actual); \ + \ + if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%" PRId32 \ + ", %" PRId32 "] Actual: %" PRId32 "\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_in_range_uint8_t(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - uint8_t lower_bound__ = (lower_bound); \ - uint8_t upper_bound__ = (upper_bound); \ - uint8_t actual__ = (actual); \ - \ - if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%" PRIu8 ", %" PRIu8 "] Actual: %" PRIu8 "\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_not_in_range_uint8_t(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + uint8_t lower_bound__ = (lower_bound); \ + uint8_t upper_bound__ = (upper_bound); \ + uint8_t actual__ = (actual); \ + \ + if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%" PRIu8 \ + ", %" PRIu8 "] Actual: %" PRIu8 "\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_in_range_uint16_t(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - uint16_t lower_bound__ = (lower_bound); \ - uint16_t upper_bound__ = (upper_bound); \ - uint16_t actual__ = (actual); \ - \ - if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%" PRIu16 ", %" PRIu16 "] Actual: %" PRIu16 "\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_not_in_range_uint16_t(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + uint16_t lower_bound__ = (lower_bound); \ + uint16_t upper_bound__ = (upper_bound); \ + uint16_t actual__ = (actual); \ + \ + if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%" PRIu16 \ + ", %" PRIu16 "] Actual: %" PRIu16 "\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_in_range_uint32_t(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - uint32_t lower_bound__ = (lower_bound); \ - uint32_t upper_bound__ = (upper_bound); \ - uint32_t actual__ = (actual); \ - \ - if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%" PRIu32 ", %" PRIu32 "] Actual: %" PRIu32 "\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_not_in_range_uint32_t(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + uint32_t lower_bound__ = (lower_bound); \ + uint32_t upper_bound__ = (upper_bound); \ + uint32_t actual__ = (actual); \ + \ + if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%" PRIu32 \ + ", %" PRIu32 "] Actual: %" PRIu32 "\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_in_range_uint64_t(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - uint64_t lower_bound__ = (lower_bound); \ - uint64_t upper_bound__ = (upper_bound); \ - uint64_t actual__ = (actual); \ - \ - if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%" PRIu64 ", %" PRIu64 "] Actual: %" PRIu64 "\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_not_in_range_uint64_t(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + uint64_t lower_bound__ = (lower_bound); \ + uint64_t upper_bound__ = (upper_bound); \ + uint64_t actual__ = (actual); \ + \ + if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%" PRIu64 \ + ", %" PRIu64 "] Actual: %" PRIu64 "\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_in_range_intmax_t(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - intmax_t lower_bound__ = (lower_bound); \ - intmax_t upper_bound__ = (upper_bound); \ - intmax_t actual__ = (actual); \ - \ - if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%" PRIdMAX ", %" PRIdMAX "] Actual: %" PRIdMAX "\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_not_in_range_intmax_t(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + intmax_t lower_bound__ = (lower_bound); \ + intmax_t upper_bound__ = (upper_bound); \ + intmax_t actual__ = (actual); \ + \ + if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%" PRIdMAX \ + ", %" PRIdMAX "] Actual: %" PRIdMAX "\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_in_range_uintmax_t(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - uintmax_t lower_bound__ = (lower_bound); \ - uintmax_t upper_bound__ = (upper_bound); \ - uintmax_t actual__ = (actual); \ - \ - if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%" PRIuMAX ", %" PRIuMAX "] Actual: %" PRIuMAX "\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_not_in_range_uintmax_t(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + uintmax_t lower_bound__ = (lower_bound); \ + uintmax_t upper_bound__ = (upper_bound); \ + uintmax_t actual__ = (actual); \ + \ + if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%" PRIuMAX \ + ", %" PRIuMAX "] Actual: %" PRIuMAX "\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_in_range_size_t(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - size_t lower_bound__ = (lower_bound); \ - size_t upper_bound__ = (upper_bound); \ - size_t actual__ = (actual); \ - \ - if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%" PRIuMAX ", %" PRIuMAX "] Actual: %" PRIuMAX "\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_not_in_range_size_t(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + size_t lower_bound__ = (lower_bound); \ + size_t upper_bound__ = (upper_bound); \ + size_t actual__ = (actual); \ + \ + if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%" PRIuMAX \ + ", %" PRIuMAX "] Actual: %" PRIuMAX "\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_in_range_float(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - float lower_bound__ = (lower_bound); \ - float upper_bound__ = (upper_bound); \ - float actual__ = (actual); \ - \ - if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%f, %f] Actual: %f\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_not_in_range_float(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + float lower_bound__ = (lower_bound); \ + float upper_bound__ = (upper_bound); \ + float actual__ = (actual); \ + \ + if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%f, %f] Actual: %f\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) -#define cmc_assert_not_in_range_double(lower_bound, upper_bound, actual) \ - do \ - { \ - const char *str = #actual; \ - double lower_bound__ = (lower_bound); \ - double upper_bound__ = (upper_bound); \ - double actual__ = (actual); \ - \ - if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ - { \ - cmc_assert_state = false; \ - \ - fprintf(stderr, \ - "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%lf, %lf] Actual: %lf\n", \ - __FILE__, __func__, __LINE__, str, lower_bound__, upper_bound__, actual__); \ - } \ - \ +#define cmc_assert_not_in_range_double(lower_bound, upper_bound, actual) \ + do \ + { \ + const char *str = #actual; \ + double lower_bound__ = (lower_bound); \ + double upper_bound__ = (upper_bound); \ + double actual__ = (actual); \ + \ + if ((actual__) >= (lower_bound__) && (actual__) <= (upper_bound__)) \ + { \ + cmc_assert_state = false; \ + \ + fprintf( \ + stderr, \ + "Assertion Failed at %s:%s:%u for { %s }: Not Expected Range: [%lf, %lf] Actual: %lf\n", \ + __FILE__, __func__, __LINE__, str, lower_bound__, \ + upper_bound__, actual__); \ + } \ + \ } while (0) #endif /* CMC_ASSERT_H */ diff --git a/src/utl/foreach.h b/src/utl/foreach.h index d62291a..8d57a22 100644 --- a/src/utl/foreach.h +++ b/src/utl/foreach.h @@ -11,22 +11,32 @@ #ifndef CMC_FOR_EACH_H #define CMC_FOR_EACH_H -#define CMC_FOR_EACH(PFX, SNAME, TARGET, BODY) \ - do \ - { \ - for (struct 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 (struct SNAME##_iter iter = (TARGET)->it_start(TARGET); \ + !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + BODY; \ + } \ } while (0) -#define CMC_FOR_EACH_REV(PFX, SNAME, TARGET, BODY) \ - do \ - { \ - for (struct 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 (struct SNAME##_iter iter = (TARGET)->it_end(TARGET); \ + !PFX##_iter_start(&iter); PFX##_iter_prev(&iter)) \ + { \ + BODY; \ + } \ } while (0) +#define CMC_FOREACH(PFX, SNAME, ITERNAME, TARGET) \ + for (struct SNAME##_iter ITERNAME = (TARGET)->it_start(TARGET); \ + !PFX##_iter_end(&ITERNAME); PFX##_iter_next(&ITERNAME)) + +#define CMC_FOREACH_REV(PFX, SNAME, ITERNAME, TARGET) \ + for (struct SNAME##_iter ITERNAME = (TARGET)->it_end(TARGET); \ + !PFX##_iter_start(&ITERNAME); PFX##_iter_prev(&ITERNAME)) + #endif /* CMC_FOR_EACH_H */ diff --git a/src/utl/log.h b/src/utl/log.h index c636307..2f05e68 100644 --- a/src/utl/log.h +++ b/src/utl/log.h @@ -59,16 +59,18 @@ #ifndef CMC_LOG_H #define CMC_LOG_H -#include -#include #include #include +#include +#include -static const char *cmc_log_names[] = {"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"}; +static const char *cmc_log_names[] = { "TRACE", "DEBUG", "INFO", + "WARN", "ERROR", "FATAL" }; #ifdef CMC_LOG_COLOR -static const char *cmc_log_color[] = {"\x1b[94m", "\x1b[36m", "\x1b[32m", "\x1b[33m", "\x1b[31m", "\x1b[35m"}; +static const char *cmc_log_color[] = { "\x1b[94m", "\x1b[36m", "\x1b[32m", + "\x1b[33m", "\x1b[31m", "\x1b[35m" }; #endif @@ -81,7 +83,7 @@ static struct FILE *file; /* File for Output */ bool enabled; /* Logging enabled */ -} cmc_log_config = {0, 0, true, true, NULL, true}; +} cmc_log_config = { 0, 0, true, true, NULL, true }; enum cmc_log_type { @@ -93,21 +95,29 @@ enum cmc_log_type CMC_LOG_FATAL = 6 }; -#define cmc_log_trace(fmt, ...) cmc_log(CMC_LOG_TRACE, __FILE__, __func__, __LINE__, fmt, __VA_ARGS__) -#define cmc_log_debug(fmt, ...) cmc_log(CMC_LOG_DEBUG, __FILE__, __func__, __LINE__, fmt, __VA_ARGS__) -#define cmc_log_info(fmt, ...) cmc_log(CMC_LOG_INFO, __FILE__, __func__, __LINE__, fmt, __VA_ARGS__) -#define cmc_log_warn(fmt, ...) cmc_log(CMC_LOG_WARN, __FILE__, __func__, __LINE__, fmt, __VA_ARGS__) -#define cmc_log_error(fmt, ...) cmc_log(CMC_LOG_ERROR, __FILE__, __func__, __LINE__, fmt, __VA_ARGS__) -#define cmc_log_fatal(fmt, ...) cmc_log(CMC_LOG_FATAL, __FILE__, __func__, __LINE__, fmt, __VA_ARGS__) +#define cmc_log_trace(fmt, ...) \ + cmc_log(CMC_LOG_TRACE, __FILE__, __func__, __LINE__, fmt, __VA_ARGS__) +#define cmc_log_debug(fmt, ...) \ + cmc_log(CMC_LOG_DEBUG, __FILE__, __func__, __LINE__, fmt, __VA_ARGS__) +#define cmc_log_info(fmt, ...) \ + cmc_log(CMC_LOG_INFO, __FILE__, __func__, __LINE__, fmt, __VA_ARGS__) +#define cmc_log_warn(fmt, ...) \ + cmc_log(CMC_LOG_WARN, __FILE__, __func__, __LINE__, fmt, __VA_ARGS__) +#define cmc_log_error(fmt, ...) \ + cmc_log(CMC_LOG_ERROR, __FILE__, __func__, __LINE__, fmt, __VA_ARGS__) +#define cmc_log_fatal(fmt, ...) \ + cmc_log(CMC_LOG_FATAL, __FILE__, __func__, __LINE__, fmt, __VA_ARGS__) -static void cmc_log(enum cmc_log_type log, const char *filename, const char *funcname, int line, const char *fmt, ...) +static void cmc_log(enum cmc_log_type log, const char *filename, + const char *funcname, int line, const char *fmt, ...) { if (!cmc_log_config.enabled) return; if (cmc_log_config.tenabled) { - if (cmc_log_config.tlevel < 0 && ((int)log * -1) < cmc_log_config.tlevel) + if (cmc_log_config.tlevel < 0 && + ((int)log * -1) < cmc_log_config.tlevel) return; else if (cmc_log_config.tlevel > 0 && (int)log < cmc_log_config.tlevel) return; @@ -121,13 +131,11 @@ static void cmc_log(enum cmc_log_type log, const char *filename, const char *fun time[strftime(time, sizeof(time), "%H:%M:%S", lt)] = '\0'; #ifdef CMC_LOG_COLOR - fprintf(stderr, - "%s %s%5s\x1b[0m \x1b[90m%s at %s:%d:\x1b[0m ", - time, cmc_log_color[i], cmc_log_names[i], filename, funcname, line); + fprintf(stderr, "%s %s%5s\x1b[0m \x1b[90m%s at %s:%d:\x1b[0m ", time, + cmc_log_color[i], cmc_log_names[i], filename, funcname, line); #else - fprintf(stderr, - "%s %5s %s at %s:%d: ", - time, cmc_log_names[i], filename, funcname, line); + fprintf(stderr, "%s %5s %s at %s:%d: ", time, cmc_log_names[i], + filename, funcname, line); #endif va_list args; @@ -141,7 +149,8 @@ static void cmc_log(enum cmc_log_type log, const char *filename, const char *fun if (cmc_log_config.file && cmc_log_config.fenabled) { - if (cmc_log_config.flevel < 0 && ((int)log * -1) < cmc_log_config.flevel) + if (cmc_log_config.flevel < 0 && + ((int)log * -1) < cmc_log_config.flevel) return; else if (cmc_log_config.flevel > 0 && (int)log < cmc_log_config.flevel) return; @@ -154,7 +163,8 @@ static void cmc_log(enum cmc_log_type log, const char *filename, const char *fun char time[32]; time[strftime(time, sizeof(time), "%Y-%m-%d %H:%M:%S", lt)] = '\0'; - fprintf(cmc_log_config.file, "%s %5s %s at %s:%d: ", time, cmc_log_names[i], filename, funcname, line); + fprintf(cmc_log_config.file, "%s %5s %s at %s:%d: ", time, + cmc_log_names[i], filename, funcname, line); va_list file_args; va_start(file_args, fmt); diff --git a/src/utl/test.h b/src/utl/test.h index f3cd1b0..c56d05f 100644 --- a/src/utl/test.h +++ b/src/utl/test.h @@ -56,7 +56,7 @@ #include #ifdef CMC_TEST_COLOR -static const char *cmc_test_color[] = {"\x1b[32m", "\x1b[31m", "\x1b[35m"}; +static const char *cmc_test_color[] = { "\x1b[32m", "\x1b[31m", "\x1b[35m" }; #endif struct cmc_test_info @@ -69,15 +69,14 @@ struct cmc_test_info }; /* Logging function */ -static void cmc_test_log(const char *unit_name, const char *current_test, bool aborted, bool passed) +static void cmc_test_log(const char *unit_name, const char *current_test, + bool aborted, bool passed) { if (aborted) { #ifdef CMC_TEST_COLOR - printf("UNIT_TEST %s %sABORTED\x1b[0m AT %s\n", - unit_name, - cmc_test_color[2], - current_test); + printf("UNIT_TEST %s %sABORTED\x1b[0m AT %s\n", unit_name, + cmc_test_color[2], current_test); #else printf("UNIT_TEST %s ABORTED at %s\n", unit_name, current_test); #endif @@ -85,52 +84,55 @@ static void cmc_test_log(const char *unit_name, const char *current_test, bool a else { #ifdef CMC_TEST_COLOR - printf("Test from %s %s%7s\x1b[0m %s\n", - unit_name, + printf("Test from %s %s%7s\x1b[0m %s\n", unit_name, passed ? cmc_test_color[0] : cmc_test_color[1], - passed ? "PASSED" : "FAILED", - current_test); + passed ? "PASSED" : "FAILED", current_test); #else - printf("Test from %s %7s %s\n", unit_name, passed ? "PASSED" : "FAILED", current_test); + printf("Test from %s %7s %s\n", unit_name, passed ? "PASSED" : "FAILED", + current_test); #endif } } -#define CMC_CREATE_UNIT(UNAME, VERBOSE, BODY) \ - uintmax_t UNAME(void) \ - { \ - const char *unit_name = #UNAME; \ - const char *current_test = NULL; \ - \ - struct cmc_test_info tinfo = {0}; \ - struct cmc_timer timer = {0}; \ - \ - tinfo.verbose = VERBOSE; \ - \ - /* Tests */ \ - cmc_timer_start(timer); \ - \ - BODY; \ - \ - cmc_timer_stop(timer); \ - cmc_timer_calc(timer); \ - \ - unittest_abort: \ - if (tinfo.aborted) \ - { \ - cmc_test_log(unit_name, current_test, true, false); \ - } \ - \ - printf("+--------------------------------------------------+\n"); \ - printf("| Unit Test Report : %-30s|\n", unit_name); \ - printf("| TOTAL : %10" PRIuMAX " |\n", tinfo.total); \ - printf("| PASSED : %10" PRIuMAX " |\n", tinfo.passed); \ - printf("| FAILED : %10" PRIuMAX " |\n", tinfo.failed); \ - printf("| |\n"); \ - printf("| Total Unit Test Runtime : %9.0f milliseconds |\n", timer.result); \ - printf("+--------------------------------------------------+\n"); \ - \ - return tinfo.failed; \ +#define CMC_CREATE_UNIT(UNAME, VERBOSE, BODY) \ + uintmax_t UNAME(void) \ + { \ + const char *unit_name = #UNAME; \ + const char *current_test = NULL; \ + \ + struct cmc_test_info tinfo = { 0 }; \ + struct cmc_timer timer = { 0 }; \ + \ + tinfo.verbose = VERBOSE; \ + \ + /* Tests */ \ + cmc_timer_start(timer); \ + \ + BODY; \ + \ + cmc_timer_stop(timer); \ + cmc_timer_calc(timer); \ + \ + unittest_abort: \ + if (tinfo.aborted) \ + { \ + cmc_test_log(unit_name, current_test, true, false); \ + } \ + \ + printf("+--------------------------------------------------+\n"); \ + printf("| Unit Test Report : %-30s|\n", unit_name); \ + printf("| TOTAL : %10" PRIuMAX " |\n", \ + tinfo.total); \ + printf("| PASSED : %10" PRIuMAX " |\n", \ + tinfo.passed); \ + printf("| FAILED : %10" PRIuMAX " |\n", \ + tinfo.failed); \ + printf("| |\n"); \ + printf("| Total Unit Test Runtime : %9.0f milliseconds |\n", \ + timer.result); \ + printf("+--------------------------------------------------+\n"); \ + \ + return tinfo.failed; \ } #define CMC_CREATE_TEST(TNAME, BODY) \