diff --git a/src/cmc/bidimap.h b/src/cmc/bidimap.h index d7371d6..23114f2 100644 --- a/src/cmc/bidimap.h +++ b/src/cmc/bidimap.h @@ -85,912 +85,915 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, CMC_GENERATE_BIDIMAP_SOURCE(PFX, SNAME, K, V) /* HEADER ********************************************************************/ -#define CMC_GENERATE_BIDIMAP_HEADER(PFX, SNAME, K, V) \ - \ - /* BidiMap Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Array of Entries mapping K -> V */ \ - struct SNAME##_entry_s **key_buffer; \ - \ - /* Array of entries mapping V -> K */ \ - struct SNAME##_entry_s **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_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the bidimap */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* BidiMap Entry */ \ - typedef struct SNAME##_entry_s \ - { \ - /* Entry Key */ \ - K key; \ - \ - /* Entry Value */ \ - V value; \ - \ - /* The distance of this node to its original position, used by */ \ - /* robin-hood hashing 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; \ - \ - } SNAME##_entry, *SNAME##_entry_ptr; \ - \ - /* BidiMap Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target bidimap */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* The index of the first element */ \ - size_t first; \ - \ - /* The index of the last element */ \ - size_t last; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - SNAME *PFX##_new(size_t capacity, double load, \ - int (*key_cmp)(K, K), size_t (*key_hash)(K), \ - int (*val_cmp)(V, V), size_t (*val_hash)(V)); \ - void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)); \ - void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)); \ - /* Collection Input and Output */ \ - bool PFX##_insert(SNAME *_map_, K key, V value); \ - bool PFX##_update_key(SNAME *_map_, K key, K *old_key); \ - bool PFX##_update_val(SNAME *_map_, V val, V *old_val); \ - bool PFX##_remove_by_key(SNAME *_map_, K key, V *out_value); \ - bool PFX##_remove_by_val(SNAME *_map_, V value, K *out_key); \ - /* Element Access */ \ - K PFX##_get_key(SNAME *_map_, V val); \ - V PFX##_get_val(SNAME *_map_, K key); \ - /* Collection State */ \ - bool PFX##_contains_key(SNAME *_map_, K key); \ - bool PFX##_contains_val(SNAME *_map_, V val); \ - bool PFX##_empty(SNAME *_map_); \ - bool PFX##_full(SNAME *_map_); \ - size_t PFX##_count(SNAME *_map_); \ - size_t PFX##_capacity(SNAME *_map_); \ - double PFX##_load(SNAME *_map_); \ - /* Collection Utility */ \ - bool PFX##_resize(SNAME *_map_, size_t capacity); \ - SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)); \ - bool PFX##_equals(SNAME *_map1_, SNAME *_map2_); \ - cmc_string PFX##_to_string(SNAME *_map_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - SNAME##_iter *PFX##_iter_new(SNAME *target); \ - void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(SNAME##_iter *iter); \ - bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(SNAME##_iter *iter); \ - void PFX##_iter_to_end(SNAME##_iter *iter); \ - bool PFX##_iter_next(SNAME##_iter *iter); \ - bool PFX##_iter_prev(SNAME##_iter *iter); \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - K PFX##_iter_key(SNAME##_iter *iter); \ - V PFX##_iter_value(SNAME##_iter *iter); \ - size_t PFX##_iter_index(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 *); \ + }; \ + \ + /* 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)); \ + void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)); \ + void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)); \ + /* Collection Input and Output */ \ + bool PFX##_insert(struct SNAME *_map_, K key, V value); \ + bool PFX##_update_key(struct SNAME *_map_, K key, K *old_key); \ + bool PFX##_update_val(struct SNAME *_map_, V val, V *old_val); \ + bool PFX##_remove_by_key(struct SNAME *_map_, K key, V *out_value); \ + bool PFX##_remove_by_val(struct SNAME *_map_, V value, K *out_key); \ + /* 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 SNAME##_entry *PFX##_impl_new_entry(K key, V value); \ - static SNAME##_entry **PFX##_impl_get_entry_by_key(SNAME *_map_, K key); \ - static SNAME##_entry **PFX##_impl_get_entry_by_val(SNAME *_map_, V val); \ - static SNAME##_entry **PFX##_impl_add_entry_to_key(SNAME *_map_, SNAME##_entry *entry); \ - static SNAME##_entry **PFX##_impl_add_entry_to_val(SNAME *_map_, SNAME##_entry *entry); \ - static size_t PFX##_impl_calculate_size(size_t required); \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_map_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_map_); \ - \ - SNAME *PFX##_new(size_t capacity, double load, \ - int (*key_cmp)(K, K), size_t (*key_hash)(K), \ - int (*val_cmp)(V, V), size_t (*val_hash)(V)) \ - { \ - if (capacity == 0 || load <= 0 || load >= 1) \ - return NULL; \ - \ - /* Prevent integer overflow */ \ - if (capacity >= UINTMAX_MAX * load) \ - return NULL; \ - \ - size_t real_capacity = PFX##_impl_calculate_size(capacity / load); \ - \ - SNAME *_map_ = malloc(sizeof(SNAME)); \ - \ - if (!_map_) \ - return NULL; \ - \ - _map_->key_buffer = calloc(real_capacity, sizeof(SNAME##_entry *)); \ - _map_->val_buffer = calloc(real_capacity, sizeof(SNAME##_entry *)); \ - \ - if (!_map_->key_buffer || !_map_->val_buffer) \ - { \ - free(_map_->key_buffer); \ - free(_map_->val_buffer); \ - 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; \ - \ - return _map_; \ - } \ - \ - void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - for (size_t i = 0; i < _map_->capacity; i++) \ - { \ - SNAME##_entry *entry = _map_->key_buffer[i]; \ - \ - if (entry != NULL && entry != CMC_ENTRY_DELETED) \ - { \ - if (deallocator) \ - deallocator(entry->key, entry->value); \ - \ - free(entry); \ - } \ - \ - _map_->key_buffer[i] = NULL; \ - _map_->val_buffer[i] = NULL; \ - } \ - \ - _map_->count = 0; \ - } \ - \ - void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - PFX##_clear(_map_, deallocator); \ - \ - free(_map_->key_buffer); \ - free(_map_->val_buffer); \ - free(_map_); \ - } \ - \ - bool PFX##_insert(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; \ - \ - SNAME##_entry *entry = PFX##_impl_new_entry(key, value); \ - \ - SNAME##_entry **key_entry = PFX##_impl_add_entry_to_key(_map_, entry); \ - 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; \ - \ - free(entry); \ - \ - return false; \ - } \ - \ - _map_->count++; \ - \ - return true; \ - } \ - \ - bool PFX##_update_key(SNAME *_map_, K key, K *old_key) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - return true; \ - } \ - \ - bool PFX##_update_val(SNAME *_map_, V val, V *old_val) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - return true; \ - } \ - \ - bool PFX##_remove_by_key(SNAME *_map_, K key, V *out_value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - return true; \ - } \ - \ - bool PFX##_remove_by_val(SNAME *_map_, V value, K *out_key) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - return true; \ - } \ - \ - K PFX##_get_key(SNAME *_map_, V val) \ - { \ - SNAME##_entry **entry = PFX##_impl_get_entry_by_val(_map_, val); \ - \ - if (!entry) \ - return (V){0}; \ - \ - return (*entry)->key; \ - } \ - \ - V PFX##_get_val(SNAME *_map_, K key) \ - { \ - SNAME##_entry **entry = PFX##_impl_get_entry_by_key(_map_, key); \ - \ - if (!entry) \ - return (V){0}; \ - \ - return (*entry)->value; \ - } \ - \ - bool PFX##_contains_key(SNAME *_map_, K key) \ - { \ - return PFX##_impl_get_entry_by_key(_map_, key) != NULL; \ - } \ - \ - bool PFX##_contains_val(SNAME *_map_, V val) \ - { \ - return PFX##_impl_get_entry_by_val(_map_, val) != NULL; \ - } \ - \ - bool PFX##_empty(SNAME *_map_) \ - { \ - return _map_->count == 0; \ - } \ - \ - bool PFX##_full(SNAME *_map_) \ - { \ - return (double)PFX##_capacity(_map_) * PFX##_load(_map_) <= (double)PFX##_count(_map_); \ - } \ - \ - size_t PFX##_count(SNAME *_map_) \ - { \ - return _map_->count; \ - } \ - \ - size_t PFX##_capacity(SNAME *_map_) \ - { \ - return _map_->capacity; \ - } \ - \ - double PFX##_load(SNAME *_map_) \ - { \ - return _map_->load; \ - } \ - \ - bool PFX##_resize(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; \ - \ - SNAME *_new_map_ = PFX##_new(capacity, PFX##_load(_map_), \ - _map_->key_cmp, _map_->key_hash, \ - _map_->val_cmp, _map_->val_hash); \ - \ - if (!_new_map_) \ - return false; \ - \ - for (size_t i = 0; i < _map_->capacity; i++) \ - { \ - SNAME##_entry *scan = _map_->key_buffer[i]; \ - \ - if (scan && scan != CMC_ENTRY_DELETED) \ - { \ - SNAME##_entry **e1 = PFX##_impl_add_entry_to_key(_new_map_, scan); \ - SNAME##_entry **e2 = PFX##_impl_add_entry_to_val(_new_map_, scan); \ - \ - if (!e1 || !e2) \ - { \ - free(_new_map_->key_buffer); \ - free(_new_map_->val_buffer); \ - free(_new_map_); \ - \ - return false; \ - } \ - \ - _new_map_->count++; \ - } \ - } \ - \ - if (PFX##_count(_map_) != PFX##_count(_new_map_)) \ - { \ - free(_new_map_->key_buffer); \ - free(_new_map_->val_buffer); \ - free(_new_map_); \ - \ - return false; \ - } \ - \ - SNAME##_entry **tmp_key_buf = _map_->key_buffer; \ - 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; \ - \ - free(tmp_key_buf); \ - free(tmp_val_buf); \ - free(_new_map_); \ - \ - return true; \ - } \ - \ - SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)) \ - { \ - SNAME *result = PFX##_new(PFX##_capacity(_map_), PFX##_load(_map_), \ - _map_->key_cmp, _map_->key_hash, \ - _map_->val_cmp, _map_->val_hash); \ - \ - for (size_t i = 0; i < _map_->capacity; i++) \ - { \ - 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(SNAME *_map1_, SNAME *_map2_) \ - { \ - if (PFX##_count(_map1_) != PFX##_count(_map2_)) \ - return false; \ - \ - SNAME *_mapA_; \ - 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++) \ - { \ - SNAME##_entry *scan = _mapA_->key_buffer[i]; \ - \ - if (scan && scan != CMC_ENTRY_DELETED) \ - { \ - 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; \ - } \ - \ - cmc_string PFX##_to_string(SNAME *_map_) \ - { \ - cmc_string str; \ - SNAME *m_ = _map_; \ - const char *name = #SNAME; \ - \ - snprintf(str.s, cmc_string_len, cmc_string_fmt_bidimap, \ - name, m_, m_->key_buffer, m_->val_buffer, m_->capacity, m_->count, \ - m_->load, m_->key_cmp, m_->val_cmp, m_->key_hash, m_->val_hash); \ - \ - return str; \ - } \ - \ - SNAME##_iter *PFX##_iter_new(SNAME *target) \ - { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ - { \ - memset(iter, 0, sizeof(SNAME##_iter)); \ - \ - iter->target = target; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - \ - if (!PFX##_empty(target)) \ - { \ - for (size_t i = 0; i < target->capacity; i++) \ - { \ - 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--) \ - { \ - SNAME##_entry *tmp = target->key_buffer[i - 1]; \ - \ - if (tmp != NULL && tmp != CMC_ENTRY_DELETED) \ - { \ - iter->last = i - 1; \ - break; \ - } \ - } \ - } \ - } \ - \ - bool PFX##_iter_start(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->first; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = false; \ - } \ - } \ - \ - void PFX##_iter_to_end(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->last; \ - iter->index = PFX##_count(iter->target) - 1; \ - iter->start = false; \ - iter->end = true; \ - } \ - } \ - \ - bool PFX##_iter_next(SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->index + 1 == PFX##_count(iter->target)) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - SNAME##_entry *scan = iter->target->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(SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->index == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - SNAME##_entry *scan = iter->target->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(SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->index + 1 == PFX##_count(iter->target)) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ - return false; \ - \ - for (size_t i = 0; i < steps; i++) \ - PFX##_iter_next(iter); \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->index == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index < steps) \ - return false; \ - \ - for (size_t i = 0; i < steps; i++) \ - PFX##_iter_prev(iter); \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator was able to be positioned at the given index */ \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ - { \ - if (index >= PFX##_count(iter->target)) \ - return false; \ - \ - if (iter->index > index) \ - return PFX##_iter_rewind(iter, iter->index - index); \ - else if (iter->index < index) \ - return PFX##_iter_advance(iter, index - iter->index); \ - \ - return true; \ - } \ - \ - K PFX##_iter_key(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (K){0}; \ - \ - return iter->target->key_buffer[iter->cursor]->key; \ - } \ - \ - V PFX##_iter_value(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){0}; \ - \ - return iter->target->key_buffer[iter->cursor]->value; \ - } \ - \ - size_t PFX##_iter_index(SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - static SNAME##_entry *PFX##_impl_new_entry(K key, V value) \ - { \ - SNAME##_entry *entry = malloc(sizeof(SNAME##_entry)); \ - \ - if (!entry) \ - return NULL; \ - \ - entry->key = key; \ - entry->value = value; \ - entry->key_dist = 0; \ - entry->val_dist = 0; \ - \ - return entry; \ - } \ - \ - static SNAME##_entry **PFX##_impl_get_entry_by_key(SNAME *_map_, K key) \ - { \ - size_t hash = _map_->key_hash(key); \ - size_t pos = hash % _map_->capacity; \ - \ - 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 SNAME##_entry **PFX##_impl_get_entry_by_val(SNAME *_map_, V val) \ - { \ - size_t hash = _map_->val_hash(val); \ - size_t pos = hash % _map_->capacity; \ - \ - 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 SNAME##_entry **PFX##_impl_add_entry_to_key(SNAME *_map_, SNAME##_entry *entry) \ - { \ - 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; \ - \ - 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; \ - \ - SNAME##_entry *_tmp_ = *scan; \ - *scan = entry; \ - entry = _tmp_; \ - } \ - } \ - } \ - \ - return NULL; \ - } \ - \ - static SNAME##_entry **PFX##_impl_add_entry_to_val(SNAME *_map_, SNAME##_entry *entry) \ - { \ - 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; \ - \ - 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; \ - \ - 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 SNAME##_iter PFX##_impl_it_start(SNAME *_map_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _map_); \ - \ - return iter; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_map_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _map_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ +#define CMC_GENERATE_BIDIMAP_SOURCE(PFX, SNAME, K, V) \ + \ + /* Implementation Detail Functions */ \ + static struct SNAME##_entry *PFX##_impl_new_entry(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)) \ + { \ + 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_ = malloc(sizeof(struct SNAME)); \ + \ + if (!_map_) \ + return NULL; \ + \ + _map_->key_buffer = calloc(real_capacity, sizeof(struct SNAME##_entry *)); \ + _map_->val_buffer = calloc(real_capacity, sizeof(struct SNAME##_entry *)); \ + \ + if (!_map_->key_buffer || !_map_->val_buffer) \ + { \ + free(_map_->key_buffer); \ + free(_map_->val_buffer); \ + 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; \ + \ + 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 != NULL && entry != CMC_ENTRY_DELETED) \ + { \ + if (deallocator) \ + deallocator(entry->key, entry->value); \ + \ + 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); \ + \ + free(_map_->key_buffer); \ + free(_map_->val_buffer); \ + free(_map_); \ + } \ + \ + 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(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; \ + \ + free(entry); \ + \ + return false; \ + } \ + \ + _map_->count++; \ + \ + return true; \ + } \ + \ + bool PFX##_update_key(struct SNAME *_map_, K key, K *old_key) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + return true; \ + } \ + \ + bool PFX##_update_val(struct SNAME *_map_, V val, V *old_val) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + return true; \ + } \ + \ + bool PFX##_remove_by_key(struct SNAME *_map_, K key, V *out_value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + return true; \ + } \ + \ + bool PFX##_remove_by_val(struct SNAME *_map_, V value, K *out_key) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + 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(capacity, PFX##_load(_map_), \ + _map_->key_cmp, _map_->key_hash, \ + _map_->val_cmp, _map_->val_hash); \ + \ + 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) \ + { \ + free(_new_map_->key_buffer); \ + free(_new_map_->val_buffer); \ + free(_new_map_); \ + \ + return false; \ + } \ + \ + _new_map_->count++; \ + } \ + } \ + \ + if (PFX##_count(_map_) != PFX##_count(_new_map_)) \ + { \ + free(_new_map_->key_buffer); \ + free(_new_map_->val_buffer); \ + 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; \ + \ + free(tmp_key_buf); \ + free(tmp_val_buf); \ + free(_new_map_); \ + \ + 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(PFX##_capacity(_map_), PFX##_load(_map_), \ + _map_->key_cmp, _map_->key_hash, \ + _map_->val_cmp, _map_->val_hash); \ + \ + 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_; \ + const char *name = #SNAME; \ + \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_bidimap, \ + name, m_, m_->key_buffer, m_->val_buffer, m_->capacity, m_->count, \ + m_->load, m_->key_cmp, m_->val_cmp, m_->key_hash, m_->val_hash); \ + \ + return str; \ + } \ + \ + 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++) \ + { \ + 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(K key, V value) \ + { \ + struct SNAME##_entry *entry = 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 a767054..7358b18 100644 --- a/src/cmc/deque.h +++ b/src/cmc/deque.h @@ -52,114 +52,112 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI CMC_GENERATE_DEQUE_SOURCE(PFX, SNAME, V) /* HEADER ********************************************************************/ -#define CMC_GENERATE_DEQUE_HEADER(PFX, SNAME, V) \ - \ - /* Deque Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Dynamic circular array of elements */ \ - V *buffer; \ - \ - /* Current circular array capacity */ \ - size_t capacity; \ - \ - /* Current amount of elements */ \ - size_t count; \ - \ - /* Index representing the front of the deque */ \ - size_t front; \ - \ - /* Index representing the back of the deque */ \ - size_t back; \ - \ - /* Function that returns an iterator to the start of the deque */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the deque */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Deque Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target deque */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - SNAME *PFX##_new(size_t capacity); \ - void PFX##_clear(SNAME *_deque_, void (*deallocator)(V)); \ - void PFX##_free(SNAME *_deque_, void (*deallocator)(V)); \ - /* Collection Input and Output */ \ - bool PFX##_push_front(SNAME *_deque_, V element); \ - bool PFX##_push_back(SNAME *_deque_, V element); \ - bool PFX##_pop_front(SNAME *_deque_); \ - bool PFX##_pop_back(SNAME *_deque_); \ - /* Element Access */ \ - V PFX##_front(SNAME *_deque_); \ - V PFX##_back(SNAME *_deque_); \ - /* Collection State */ \ - bool PFX##_contains(SNAME *_deque_, V element, int (*comparator)(V, V)); \ - bool PFX##_empty(SNAME *_deque_); \ - bool PFX##_full(SNAME *_deque_); \ - size_t PFX##_count(SNAME *_deque_); \ - size_t PFX##_capacity(SNAME *_deque_); \ - /* Collection Utility */ \ - bool PFX##_resize(SNAME *_deque_, size_t capacity); \ - SNAME *PFX##_copy_of(SNAME *_deque_, V (*copy_func)(V)); \ - bool PFX##_equals(SNAME *_deque1_, SNAME *_deque2_, int (*comparator)(V, V)); \ - cmc_string PFX##_to_string(SNAME *_deque_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - SNAME##_iter *PFX##_iter_new(SNAME *target); \ - void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(SNAME##_iter *iter); \ - bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(SNAME##_iter *iter); \ - void PFX##_iter_to_end(SNAME##_iter *iter); \ - bool PFX##_iter_next(SNAME##_iter *iter); \ - bool PFX##_iter_prev(SNAME##_iter *iter); \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - V PFX##_iter_value(SNAME##_iter *iter); \ - V *PFX##_iter_rvalue(SNAME##_iter *iter); \ - size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ +#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 *); \ + }; \ + \ + /* 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); \ + void PFX##_clear(struct SNAME *_deque_, void (*deallocator)(V)); \ + void PFX##_free(struct SNAME *_deque_, void (*deallocator)(V)); \ + /* 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 SNAME##_iter PFX##_impl_it_start(SNAME *_deque_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_deque_); \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_deque_); \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_deque_); \ \ - SNAME *PFX##_new(size_t capacity) \ + struct SNAME *PFX##_new(size_t capacity) \ { \ if (capacity < 1) \ return NULL; \ \ - SNAME *_deque_ = malloc(sizeof(SNAME)); \ + struct SNAME *_deque_ = malloc(sizeof(struct SNAME)); \ \ if (!_deque_) \ return NULL; \ @@ -183,7 +181,7 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI return _deque_; \ } \ \ - void PFX##_clear(SNAME *_deque_, void (*deallocator)(V)) \ + void PFX##_clear(struct SNAME *_deque_, void (*deallocator)(V)) \ { \ if (deallocator) \ { \ @@ -202,7 +200,7 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI _deque_->back = 0; \ } \ \ - void PFX##_free(SNAME *_deque_, void (*deallocator)(V)) \ + void PFX##_free(struct SNAME *_deque_, void (*deallocator)(V)) \ { \ if (deallocator) \ { \ @@ -218,7 +216,7 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI free(_deque_); \ } \ \ - bool PFX##_push_front(SNAME *_deque_, V element) \ + bool PFX##_push_front(struct SNAME *_deque_, V element) \ { \ if (PFX##_full(_deque_)) \ { \ @@ -235,7 +233,7 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI return true; \ } \ \ - bool PFX##_push_back(SNAME *_deque_, V element) \ + bool PFX##_push_back(struct SNAME *_deque_, V element) \ { \ if (PFX##_full(_deque_)) \ { \ @@ -252,7 +250,7 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI return true; \ } \ \ - bool PFX##_pop_front(SNAME *_deque_) \ + bool PFX##_pop_front(struct SNAME *_deque_) \ { \ if (PFX##_empty(_deque_)) \ return false; \ @@ -266,7 +264,7 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI return true; \ } \ \ - bool PFX##_pop_back(SNAME *_deque_) \ + bool PFX##_pop_back(struct SNAME *_deque_) \ { \ if (PFX##_empty(_deque_)) \ return false; \ @@ -280,7 +278,7 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI return true; \ } \ \ - V PFX##_front(SNAME *_deque_) \ + V PFX##_front(struct SNAME *_deque_) \ { \ if (PFX##_empty(_deque_)) \ return (V){0}; \ @@ -288,7 +286,7 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI return _deque_->buffer[_deque_->front]; \ } \ \ - V PFX##_back(SNAME *_deque_) \ + V PFX##_back(struct SNAME *_deque_) \ { \ if (PFX##_empty(_deque_)) \ return (V){0}; \ @@ -296,7 +294,7 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI return _deque_->buffer[(_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1]; \ } \ \ - bool PFX##_contains(SNAME *_deque_, V element, int (*comparator)(V, V)) \ + bool PFX##_contains(struct SNAME *_deque_, V element, int (*comparator)(V, V)) \ { \ for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) \ { \ @@ -309,27 +307,27 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI return false; \ } \ \ - bool PFX##_empty(SNAME *_deque_) \ + bool PFX##_empty(struct SNAME *_deque_) \ { \ return _deque_->count == 0; \ } \ \ - bool PFX##_full(SNAME *_deque_) \ + bool PFX##_full(struct SNAME *_deque_) \ { \ return _deque_->count >= _deque_->capacity; \ } \ \ - size_t PFX##_count(SNAME *_deque_) \ + size_t PFX##_count(struct SNAME *_deque_) \ { \ return _deque_->count; \ } \ \ - size_t PFX##_capacity(SNAME *_deque_) \ + size_t PFX##_capacity(struct SNAME *_deque_) \ { \ return _deque_->capacity; \ } \ \ - bool PFX##_resize(SNAME *_deque_, size_t capacity) \ + bool PFX##_resize(struct SNAME *_deque_, size_t capacity) \ { \ if (PFX##_capacity(_deque_) == capacity) \ return true; \ @@ -359,9 +357,9 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI return true; \ } \ \ - SNAME *PFX##_copy_of(SNAME *_deque_, V (*copy_func)(V)) \ + struct SNAME *PFX##_copy_of(struct SNAME *_deque_, V (*copy_func)(V)) \ { \ - SNAME *result = PFX##_new(_deque_->capacity); \ + struct SNAME *result = PFX##_new(_deque_->capacity); \ \ if (!result) \ return NULL; \ @@ -390,7 +388,7 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI return result; \ } \ \ - bool PFX##_equals(SNAME *_deque1_, SNAME *_deque2_, int (*comparator)(V, V)) \ + bool PFX##_equals(struct SNAME *_deque1_, struct SNAME *_deque2_, int (*comparator)(V, V)) \ { \ if (PFX##_count(_deque1_) != PFX##_count(_deque2_)) \ return false; \ @@ -408,10 +406,10 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI return true; \ } \ \ - cmc_string PFX##_to_string(SNAME *_deque_) \ + struct cmc_string PFX##_to_string(struct SNAME *_deque_) \ { \ - cmc_string str; \ - SNAME *d_ = _deque_; \ + struct cmc_string str; \ + struct SNAME *d_ = _deque_; \ const char *name = #SNAME; \ \ snprintf(str.s, cmc_string_len, cmc_string_fmt_deque, \ @@ -420,9 +418,9 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI return str; \ } \ \ - SNAME##_iter *PFX##_iter_new(SNAME *target) \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ + struct SNAME##_iter *iter = malloc(sizeof(struct SNAME##_iter)); \ \ if (!iter) \ return NULL; \ @@ -432,12 +430,12 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI return iter; \ } \ \ - void PFX##_iter_free(SNAME##_iter *iter) \ + void PFX##_iter_free(struct SNAME##_iter *iter) \ { \ free(iter); \ } \ \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ { \ iter->target = target; \ iter->cursor = target->front; \ @@ -446,17 +444,17 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI iter->end = PFX##_empty(target); \ } \ \ - bool PFX##_iter_start(SNAME##_iter *iter) \ + bool PFX##_iter_start(struct SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->start; \ } \ \ - bool PFX##_iter_end(SNAME##_iter *iter) \ + bool PFX##_iter_end(struct SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->end; \ } \ \ - void PFX##_iter_to_start(SNAME##_iter *iter) \ + void PFX##_iter_to_start(struct SNAME##_iter *iter) \ { \ iter->cursor = iter->target->front; \ iter->index = 0; \ @@ -464,7 +462,7 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI iter->end = PFX##_empty(iter->target); \ } \ \ - void PFX##_iter_to_end(SNAME##_iter *iter) \ + void PFX##_iter_to_end(struct SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ { \ @@ -485,7 +483,7 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI iter->end = true; \ } \ \ - bool PFX##_iter_next(SNAME##_iter *iter) \ + bool PFX##_iter_next(struct SNAME##_iter *iter) \ { \ if (iter->end) \ return false; \ @@ -504,7 +502,7 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI return true; \ } \ \ - bool PFX##_iter_prev(SNAME##_iter *iter) \ + bool PFX##_iter_prev(struct SNAME##_iter *iter) \ { \ if (iter->start) \ return false; \ @@ -524,7 +522,7 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI } \ \ /* Returns true only if the iterator moved */ \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps) \ { \ if (iter->end) \ return false; \ @@ -547,7 +545,7 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI } \ \ /* Returns true only if the iterator moved */ \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps) \ { \ if (iter->start) \ return false; \ @@ -575,7 +573,7 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI } \ \ /* Returns true only if the iterator was able to be positioned at the given index */ \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index) \ { \ if (index >= PFX##_count(iter->target)) \ return false; \ @@ -588,7 +586,7 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI return true; \ } \ \ - V PFX##_iter_value(SNAME##_iter *iter) \ + V PFX##_iter_value(struct SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ return (V){0}; \ @@ -596,7 +594,7 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI return iter->target->buffer[iter->cursor]; \ } \ \ - V *PFX##_iter_rvalue(SNAME##_iter *iter) \ + V *PFX##_iter_rvalue(struct SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ return NULL; \ @@ -604,23 +602,23 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI return &(iter->target->buffer[iter->cursor]); \ } \ \ - size_t PFX##_iter_index(SNAME##_iter *iter) \ + size_t PFX##_iter_index(struct SNAME##_iter *iter) \ { \ return iter->index; \ } \ \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_deque_) \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_deque_) \ { \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ \ PFX##_iter_init(&iter, _deque_); \ \ return iter; \ } \ \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_deque_) \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_deque_) \ { \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ \ PFX##_iter_init(&iter, _deque_); \ PFX##_iter_to_end(&iter); \ diff --git a/src/cmc/hashmap.h b/src/cmc/hashmap.h index 7360021..c8f4775 100644 --- a/src/cmc/hashmap.h +++ b/src/cmc/hashmap.h @@ -32,7 +32,7 @@ static const char *cmc_string_fmt_hashmap = "%s at %p { buffer:%p, capacity:%" P #ifndef CMC_IMPL_HASHTABLE_STATE #define CMC_IMPL_HASHTABLE_STATE -enum cmc_entry_state_e +enum cmc_entry_state { CMC_ES_DELETED = -1, CMC_ES_EMPTY = 0, @@ -89,837 +89,839 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, CMC_GENERATE_HASHMAP_SOURCE(PFX, SNAME, K, V) /* HEADER ********************************************************************/ -#define CMC_GENERATE_HASHMAP_HEADER(PFX, SNAME, K, V) \ - \ - /* Hashmap Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Array of Entries */ \ - struct SNAME##_entry_s *buffer; \ - \ - /* Current array capacity */ \ - size_t capacity; \ - \ - /* Current amount of keys */ \ - size_t count; \ - \ - /* Load factor in range (0.0, 1.0) */ \ - double load; \ - \ - /* Key comparison function */ \ - int (*cmp)(K, K); \ - \ - /* Key hash function */ \ - size_t (*hash)(K); \ - \ - /* Function that returns an iterator to the start of the hashmap */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the hashmap */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Hashmap Entry */ \ - typedef struct SNAME##_entry_s \ - { \ - /* Entry Key */ \ - K key; \ - \ - /* Entry Value */ \ - V value; \ - \ - /* The distance of this node to its original position, used by */ \ - /* robin-hood hashing */ \ - size_t dist; \ - \ - /* The sate of this node (DELETED, EMPTY, FILLED) */ \ - enum cmc_entry_state_e state; \ - \ - } SNAME##_entry, *SNAME##_entry_ptr; \ - \ - /* Hashmap Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target hashmap */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* The index of the first element */ \ - size_t first; \ - \ - /* The index of the last element */ \ - size_t last; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - SNAME *PFX##_new(size_t capacity, double load, int (*compare)(K, K), size_t (*hash)(K)); \ - void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)); \ - void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)); \ - /* Collection Input and Output */ \ - bool PFX##_insert(SNAME *_map_, K key, V value); \ - bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value); \ - bool PFX##_remove(SNAME *_map_, K key, V *out_value); \ - /* Element Access */ \ - bool PFX##_max(SNAME *_map_, K *key, V *value); \ - bool PFX##_min(SNAME *_map_, K *key, V *value); \ - V PFX##_get(SNAME *_map_, K key); \ - V *PFX##_get_ref(SNAME *_map_, K key); \ - /* Collection State */ \ - bool PFX##_contains(SNAME *_map_, K key); \ - bool PFX##_empty(SNAME *_map_); \ - bool PFX##_full(SNAME *_map_); \ - size_t PFX##_count(SNAME *_map_); \ - size_t PFX##_capacity(SNAME *_map_); \ - double PFX##_load(SNAME *_map_); \ - /* Collection Utility */ \ - bool PFX##_resize(SNAME *_map_, size_t capacity); \ - SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)); \ - bool PFX##_equals(SNAME *_map1_, SNAME *_map2_, int (*value_comparator)(V, V)); \ - cmc_string PFX##_to_string(SNAME *_map_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - SNAME##_iter *PFX##_iter_new(SNAME *target); \ - void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(SNAME##_iter *iter); \ - bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(SNAME##_iter *iter); \ - void PFX##_iter_to_end(SNAME##_iter *iter); \ - bool PFX##_iter_next(SNAME##_iter *iter); \ - bool PFX##_iter_prev(SNAME##_iter *iter); \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - K PFX##_iter_key(SNAME##_iter *iter); \ - V PFX##_iter_value(SNAME##_iter *iter); \ - V *PFX##_iter_rvalue(SNAME##_iter *iter); \ - size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ +#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 *); \ + }; \ + \ + /* 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)); \ + void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)); \ + void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)); \ + /* 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 SNAME##_entry *PFX##_impl_get_entry(SNAME *_map_, K key); \ - static size_t PFX##_impl_calculate_size(size_t required); \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_map_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_map_); \ - \ - SNAME *PFX##_new(size_t capacity, double load, int (*compare)(K, K), size_t (*hash)(K)) \ - { \ - if (capacity == 0 || load <= 0 || load >= 1) \ - return NULL; \ - \ - /* Prevent integer overflow */ \ - if (capacity >= UINTMAX_MAX * load) \ - return NULL; \ - \ - size_t real_capacity = PFX##_impl_calculate_size(capacity / load); \ - \ - SNAME *_map_ = malloc(sizeof(SNAME)); \ - \ - if (!_map_) \ - return NULL; \ - \ - _map_->buffer = calloc(real_capacity, sizeof(SNAME##_entry)); \ - \ - if (!_map_->buffer) \ - { \ - 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; \ - \ - return _map_; \ - } \ - \ - void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _map_->capacity; i++) \ - { \ - SNAME##_entry *entry = &(_map_->buffer[i]); \ - \ - if (entry->state == CMC_ES_FILLED) \ - { \ - deallocator(entry->key, entry->value); \ - } \ - } \ - } \ - \ - memset(_map_->buffer, 0, sizeof(SNAME##_entry) * _map_->capacity); \ - \ - _map_->count = 0; \ - } \ - \ - void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _map_->capacity; i++) \ - { \ - SNAME##_entry *entry = &(_map_->buffer[i]); \ - \ - if (entry->state == CMC_ES_FILLED) \ - { \ - deallocator(entry->key, entry->value); \ - } \ - } \ - } \ - \ - free(_map_->buffer); \ - free(_map_); \ - } \ - \ - bool PFX##_insert(SNAME *_map_, K key, V value) \ - { \ - if (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; \ - \ - 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(SNAME *_map_, K key, V new_value, V *old_value) \ - { \ - SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ - \ - if (!entry) \ - return false; \ - \ - if (old_value) \ - *old_value = entry->value; \ - \ - entry->value = new_value; \ - \ - return true; \ - } \ - \ - bool PFX##_remove(SNAME *_map_, K key, V *out_value) \ - { \ - SNAME##_entry *result = PFX##_impl_get_entry(_map_, key); \ - \ - if (result == NULL) \ - return false; \ - \ - if (out_value) \ - *out_value = result->value; \ - \ - result->key = (K){0}; \ - result->value = (V){0}; \ - result->dist = 0; \ - result->state = CMC_ES_DELETED; \ - \ - _map_->count--; \ - \ - return true; \ - } \ - \ - bool PFX##_max(SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - 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(SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - 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(SNAME *_map_, K key) \ - { \ - SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ - \ - if (!entry) \ - return (V){0}; \ - \ - return entry->value; \ - } \ - \ - V *PFX##_get_ref(SNAME *_map_, K key) \ - { \ - SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ - \ - if (!entry) \ - return NULL; \ - \ - return &(entry->value); \ - } \ - \ - bool PFX##_contains(SNAME *_map_, K key) \ - { \ - return PFX##_impl_get_entry(_map_, key) != NULL; \ - } \ - \ - bool PFX##_empty(SNAME *_map_) \ - { \ - return _map_->count == 0; \ - } \ - \ - bool PFX##_full(SNAME *_map_) \ - { \ - return (double)PFX##_capacity(_map_) * PFX##_load(_map_) <= (double)PFX##_count(_map_); \ - } \ - \ - size_t PFX##_count(SNAME *_map_) \ - { \ - return _map_->count; \ - } \ - \ - size_t PFX##_capacity(SNAME *_map_) \ - { \ - return _map_->capacity; \ - } \ - \ - double PFX##_load(SNAME *_map_) \ - { \ - return _map_->load; \ - } \ - \ - bool PFX##_resize(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; \ - \ - SNAME *_new_map_ = PFX##_new(capacity, PFX##_load(_map_), _map_->cmp, _map_->hash); \ - \ - if (!_new_map_) \ - return false; \ - \ - SNAME##_iter iter; \ - \ - for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - K key = PFX##_iter_key(&iter); \ - V value = PFX##_iter_value(&iter); \ - \ - PFX##_insert(_new_map_, key, value); \ - } \ - \ - if (PFX##_count(_map_) != PFX##_count(_new_map_)) \ - { \ - PFX##_free(_new_map_, NULL); \ - return false; \ - } \ - \ - SNAME##_entry *tmp_b = _map_->buffer; \ - _map_->buffer = _new_map_->buffer; \ - _new_map_->buffer = tmp_b; \ - \ - size_t tmp_c = _map_->capacity; \ - _map_->capacity = _new_map_->capacity; \ - _new_map_->capacity = tmp_c; \ - \ - PFX##_free(_new_map_, NULL); \ - \ - return true; \ - } \ - \ - SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)) \ - { \ - SNAME *result = PFX##_new(_map_->capacity, _map_->load, _map_->cmp, _map_->hash); \ - \ - if (!result) \ - return NULL; \ - \ - if (key_copy_func || value_copy_func) \ - { \ - for (size_t i = 0; i < _map_->capacity; i++) \ - { \ - SNAME##_entry *scan = &(_map_->buffer[i]); \ - \ - if (scan->state != CMC_ES_EMPTY) \ - { \ - SNAME##_entry *target = &(result->buffer[i]); \ - \ - if (scan->state == CMC_ES_DELETED) \ - target->state = CMC_ES_DELETED; \ - else \ - { \ - target->state = scan->state; \ - target->dist = scan->dist; \ - \ - if (key_copy_func) \ - target->key = key_copy_func(scan->key); \ - else \ - target->key = scan->key; \ - \ - if (value_copy_func) \ - target->value = value_copy_func(scan->value); \ - else \ - target->value = scan->value; \ - } \ - } \ - } \ - } \ - else \ - memcpy(result->buffer, _map_->buffer, sizeof(SNAME##_entry) * _map_->capacity); \ - \ - result->count = _map_->count; \ - \ - return result; \ - } \ - \ - bool PFX##_equals(SNAME *_map1_, SNAME *_map2_, int (*value_comparator)(V, V)) \ - { \ - if (PFX##_count(_map1_) != PFX##_count(_map2_)) \ - return false; \ - \ - SNAME##_iter iter; \ - PFX##_iter_init(&iter, _map1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - SNAME##_entry *entry = PFX##_impl_get_entry(_map2_, PFX##_iter_key(&iter)); \ - \ - if (entry == NULL) \ - return false; \ - \ - if (value_comparator) \ - { \ - if (value_comparator(entry->value, PFX##_iter_value(&iter)) != 0) \ - return false; \ - } \ - } \ - \ - return true; \ - } \ - \ - cmc_string PFX##_to_string(SNAME *_map_) \ - { \ - cmc_string str; \ - SNAME *m_ = _map_; \ - const char *name = #SNAME; \ - \ - snprintf(str.s, cmc_string_len, cmc_string_fmt_hashmap, \ - name, m_, m_->buffer, m_->capacity, m_->count, m_->load, m_->cmp, m_->hash); \ - \ - return str; \ - } \ - \ - SNAME##_iter *PFX##_iter_new(SNAME *target) \ - { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ - { \ - memset(iter, 0, sizeof(SNAME##_iter)); \ - \ - iter->target = target; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - \ - if (!PFX##_empty(target)) \ - { \ - for (size_t i = 0; i < target->capacity; i++) \ - { \ - if (target->buffer[i].state == CMC_ES_FILLED) \ - { \ - iter->first = i; \ - break; \ - } \ - } \ - \ - iter->cursor = iter->first; \ - \ - for (size_t i = target->capacity; i > 0; i--) \ - { \ - if (target->buffer[i - 1].state == CMC_ES_FILLED) \ - { \ - iter->last = i - 1; \ - break; \ - } \ - } \ - } \ - } \ - \ - bool PFX##_iter_start(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->first; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - } \ - } \ - \ - void PFX##_iter_to_end(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->last; \ - iter->index = PFX##_count(iter->target) - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - } \ - } \ - \ - bool PFX##_iter_next(SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->index + 1 == PFX##_count(iter->target)) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ - \ - iter->index++; \ - \ - while (1) \ - { \ - iter->cursor++; \ - scan = &(iter->target->buffer[iter->cursor]); \ - \ - if (scan->state == CMC_ES_FILLED) \ - break; \ - } \ - \ - return true; \ - } \ - \ - bool PFX##_iter_prev(SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->index == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ - \ - iter->index--; \ - \ - while (1) \ - { \ - iter->cursor--; \ - scan = &(iter->target->buffer[iter->cursor]); \ - \ - if (scan->state == CMC_ES_FILLED) \ - break; \ - } \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->index + 1 == PFX##_count(iter->target)) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ - return false; \ - \ - for (size_t i = 0; i < steps; i++) \ - PFX##_iter_next(iter); \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->index == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index < steps) \ - return false; \ - \ - for (size_t i = 0; i < steps; i++) \ - PFX##_iter_prev(iter); \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator was able to be positioned at the given index */ \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ - { \ - if (index >= PFX##_count(iter->target)) \ - return false; \ - \ - if (iter->index > index) \ - return PFX##_iter_rewind(iter, iter->index - index); \ - else if (iter->index < index) \ - return PFX##_iter_advance(iter, index - iter->index); \ - \ - return true; \ - } \ - \ - K PFX##_iter_key(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (K){0}; \ - \ - return iter->target->buffer[iter->cursor].key; \ - } \ - \ - V PFX##_iter_value(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){0}; \ - \ - return iter->target->buffer[iter->cursor].value; \ - } \ - \ - V *PFX##_iter_rvalue(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->target->buffer[iter->cursor].value); \ - } \ - \ - size_t PFX##_iter_index(SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - static SNAME##_entry *PFX##_impl_get_entry(SNAME *_map_, K key) \ - { \ - size_t hash = _map_->hash(key); \ - size_t pos = hash % _map_->capacity; \ - \ - SNAME##_entry *target = &(_map_->buffer[pos]); \ - \ - while (target->state == CMC_ES_FILLED || target->state == CMC_ES_DELETED) \ - { \ - if (_map_->cmp(target->key, key) == 0) \ - return target; \ - \ - pos++; \ - target = &(_map_->buffer[pos % _map_->capacity]); \ - } \ - \ - return NULL; \ - } \ - \ - static size_t PFX##_impl_calculate_size(size_t required) \ - { \ - const size_t count = sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]); \ - \ - if (cmc_hashtable_primes[count - 1] < required) \ - return required; \ - \ - size_t i = 0; \ - while (cmc_hashtable_primes[i] < required) \ - i++; \ - \ - return cmc_hashtable_primes[i]; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_map_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _map_); \ - \ - return iter; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_map_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _map_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ +#define CMC_GENERATE_HASHMAP_SOURCE(PFX, SNAME, K, V) \ + \ + /* Implementation Detail Functions */ \ + static 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)) \ + { \ + 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_ = malloc(sizeof(struct SNAME)); \ + \ + if (!_map_) \ + return NULL; \ + \ + _map_->buffer = calloc(real_capacity, sizeof(struct SNAME##_entry)); \ + \ + if (!_map_->buffer) \ + { \ + 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; \ + \ + 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); \ + } \ + } \ + } \ + \ + free(_map_->buffer); \ + free(_map_); \ + } \ + \ + 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 / 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 = _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; \ + \ + 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_; \ + const char *name = #SNAME; \ + \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_hashmap, \ + name, m_, m_->buffer, m_->capacity, m_->count, m_->load, m_->cmp, m_->hash); \ + \ + return str; \ + } \ + \ + 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 = 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 d4470a8..bd7f619 100644 --- a/src/cmc/hashset.h +++ b/src/cmc/hashset.h @@ -31,7 +31,7 @@ static const char *cmc_string_fmt_hashset = "%s at %p { buffer:%p, capacity:%" P #ifndef CMC_IMPL_HASHTABLE_STATE #define CMC_IMPL_HASHTABLE_STATE -enum cmc_entry_state_e +enum cmc_entry_state { CMC_ES_DELETED = -1, CMC_ES_EMPTY = 0, @@ -91,10 +91,10 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, #define CMC_GENERATE_HASHSET_HEADER(PFX, SNAME, V) \ \ /* Hashset Structure */ \ - typedef struct SNAME##_s \ + struct SNAME \ { \ /* Array of Entries */ \ - struct SNAME##_entry_s *buffer; \ + struct SNAME##_entry *buffer; \ \ /* Current Array Capcity */ \ size_t capacity; \ @@ -112,14 +112,13 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, size_t (*hash)(V); \ \ /* Function that returns an iterator to the start of the hashset */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + struct SNAME##_iter (*it_start)(struct SNAME *); \ \ /* Function that returns an iterator to the end of the hashset */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + struct SNAME##_iter (*it_end)(struct SNAME *); \ + }; \ \ - } SNAME, *SNAME##_ptr; \ - \ - typedef struct SNAME##_entry_s \ + struct SNAME##_entry \ { \ /* Entry element */ \ V value; \ @@ -128,15 +127,14 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, size_t dist; \ \ /* The sate of this node (DELETED, EMPTY, FILLED) */ \ - enum cmc_entry_state_e state; \ - \ - } SNAME##_entry, *SNAME##_entry_ptr; \ + enum cmc_entry_state state; \ + }; \ \ /* Hashset Iterator */ \ - typedef struct SNAME##_iter_s \ + struct SNAME##_iter \ { \ /* Target Hashset */ \ - struct SNAME##_s *target; \ + struct SNAME *target; \ \ /* Cursor's position (index) */ \ size_t cursor; \ @@ -155,877 +153,881 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ /* If the iterator has reached the end of the iteration */ \ bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ + }; \ \ /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ - SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), size_t (*hash)(V)); \ - void PFX##_clear(SNAME *_set_, void (*deallocator)(V)); \ - void PFX##_free(SNAME *_set_, void (*deallocator)(V)); \ + struct SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), \ + size_t (*hash)(V)); \ + void PFX##_clear(struct SNAME *_set_, void (*deallocator)(V)); \ + void PFX##_free(struct SNAME *_set_, void (*deallocator)(V)); \ /* Collection Input and Output */ \ - bool PFX##_insert(SNAME *_set_, V element); \ - bool PFX##_remove(SNAME *_set_, V element); \ + bool PFX##_insert(struct SNAME *_set_, V element); \ + bool PFX##_remove(struct SNAME *_set_, V element); \ /* Element Access */ \ - bool PFX##_max(SNAME *_set_, V *value); \ - bool PFX##_min(SNAME *_set_, V *value); \ + bool PFX##_max(struct SNAME *_set_, V *value); \ + bool PFX##_min(struct SNAME *_set_, V *value); \ /* Collection State */ \ - bool PFX##_contains(SNAME *_set_, V element); \ - bool PFX##_empty(SNAME *_set_); \ - bool PFX##_full(SNAME *_set_); \ - size_t PFX##_count(SNAME *_set_); \ - size_t PFX##_capacity(SNAME *_set_); \ - double PFX##_load(SNAME *_set_); \ + 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(SNAME *_set_, size_t capacity); \ - SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)); \ - bool PFX##_equals(SNAME *_set1_, SNAME *_set2_); \ - cmc_string PFX##_to_string(SNAME *_set_); \ + 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 */ \ - SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_); \ - SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_); \ - SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_); \ - SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_); \ - bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_); \ - bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_); \ - bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_); \ - bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_); \ - bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_); \ + 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 */ \ - SNAME##_iter *PFX##_iter_new(SNAME *target); \ - void PFX##_iter_free(SNAME##_iter *iter); \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ + void PFX##_iter_free(struct SNAME##_iter *iter); \ /* Iterator Initialization */ \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ /* Iterator State */ \ - bool PFX##_iter_start(SNAME##_iter *iter); \ - bool PFX##_iter_end(SNAME##_iter *iter); \ + bool PFX##_iter_start(struct SNAME##_iter *iter); \ + bool PFX##_iter_end(struct SNAME##_iter *iter); \ /* Iterator Movement */ \ - void PFX##_iter_to_start(SNAME##_iter *iter); \ - void PFX##_iter_to_end(SNAME##_iter *iter); \ - bool PFX##_iter_next(SNAME##_iter *iter); \ - bool PFX##_iter_prev(SNAME##_iter *iter); \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ + 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(SNAME##_iter *iter); \ - size_t PFX##_iter_index(SNAME##_iter *iter); \ + 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 SNAME##_entry *PFX##_impl_get_entry(SNAME *_set_, V element); \ - static size_t PFX##_impl_calculate_size(size_t required); \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_set_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_set_); \ - \ - SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), size_t (*hash)(V)) \ - { \ - if (capacity == 0 || load <= 0 || load >= 1) \ - return NULL; \ - \ - /* Prevent integer overflow */ \ - if (capacity >= UINTMAX_MAX * load) \ - return NULL; \ - \ - size_t real_capacity = PFX##_impl_calculate_size(capacity / load); \ - \ - SNAME *_set_ = malloc(sizeof(SNAME)); \ - \ - if (!_set_) \ - return NULL; \ - \ - _set_->buffer = calloc(real_capacity, sizeof(SNAME##_entry)); \ - \ - if (!_set_->buffer) \ - { \ - 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; \ - \ - return _set_; \ - } \ - \ - void PFX##_clear(SNAME *_set_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _set_->capacity; i++) \ - { \ - SNAME##_entry *entry = &(_set_->buffer[i]); \ - \ - if (entry->state == CMC_ES_FILLED) \ - { \ - deallocator(entry->value); \ - } \ - } \ - } \ - \ - memset(_set_->buffer, 0, sizeof(SNAME##_entry) * _set_->capacity); \ - \ - _set_->count = 0; \ - } \ - \ - void PFX##_free(SNAME *_set_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _set_->capacity; i++) \ - { \ - SNAME##_entry *entry = &(_set_->buffer[i]); \ - \ - if (entry->state == CMC_ES_FILLED) \ - { \ - deallocator(entry->value); \ - } \ - } \ - } \ - \ - free(_set_->buffer); \ - free(_set_); \ - } \ - \ - bool PFX##_insert(SNAME *_set_, V element) \ - { \ - if (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; \ - \ - SNAME##_entry *target = &(_set_->buffer[pos]); \ - \ - if (PFX##_impl_get_entry(_set_, element) != NULL) \ - return false; \ - \ - if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) \ - { \ - target->value = element; \ - target->dist = 0; \ - target->state = CMC_ES_FILLED; \ - } \ - else \ - { \ - while (true) \ - { \ - pos++; \ - target = &(_set_->buffer[pos % _set_->capacity]); \ - \ - if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) \ - { \ - target->value = element; \ - target->dist = pos - original_pos; \ - target->state = CMC_ES_FILLED; \ - \ - break; \ - } \ - else if (target->dist < pos - original_pos) \ - { \ - V tmp = target->value; \ - size_t tmp_dist = target->dist; \ - \ - target->value = element; \ - target->dist = pos - original_pos; \ - \ - element = tmp; \ - original_pos = pos - tmp_dist; \ - } \ - } \ - } \ - \ - _set_->count++; \ - \ - return true; \ - } \ - \ - bool PFX##_remove(SNAME *_set_, V element) \ - { \ - SNAME##_entry *result = PFX##_impl_get_entry(_set_, element); \ - \ - if (result == NULL) \ - return false; \ - \ - result->value = (V){0}; \ - result->dist = 0; \ - result->state = CMC_ES_DELETED; \ - \ - _set_->count--; \ - \ - return true; \ - } \ - \ - bool PFX##_max(SNAME *_set_, V *value) \ - { \ - if (PFX##_empty(_set_)) \ - return false; \ - \ - SNAME##_iter iter; \ - \ - for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - V result = PFX##_iter_value(&iter); \ - size_t index = PFX##_iter_index(&iter); \ - \ - if (index == 0) \ - *value = result; \ - else if (_set_->cmp(result, *value) > 0) \ - *value = result; \ - } \ - \ - return true; \ - } \ - \ - bool PFX##_min(SNAME *_set_, V *value) \ - { \ - if (PFX##_empty(_set_)) \ - return false; \ - \ - SNAME##_iter iter; \ - \ - for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - V result = PFX##_iter_value(&iter); \ - size_t index = PFX##_iter_index(&iter); \ - \ - if (index == 0) \ - *value = result; \ - else if (_set_->cmp(result, *value) < 0) \ - *value = result; \ - } \ - \ - return true; \ - } \ - \ - bool PFX##_contains(SNAME *_set_, V element) \ - { \ - return PFX##_impl_get_entry(_set_, element) != NULL; \ - } \ - \ - bool PFX##_empty(SNAME *_set_) \ - { \ - return _set_->count == 0; \ - } \ - \ - bool PFX##_full(SNAME *_set_) \ - { \ - return (double)PFX##_capacity(_set_) * PFX##_load(_set_) <= (double)PFX##_count(_set_); \ - } \ - \ - size_t PFX##_count(SNAME *_set_) \ - { \ - return _set_->count; \ - } \ - \ - size_t PFX##_capacity(SNAME *_set_) \ - { \ - return _set_->capacity; \ - } \ - \ - double PFX##_load(SNAME *_set_) \ - { \ - return _set_->load; \ - } \ - \ - bool PFX##_resize(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; \ - \ - SNAME *_new_set_ = PFX##_new(capacity, PFX##_load(_set_), _set_->cmp, _set_->hash); \ - \ - if (!_new_set_) \ - return false; \ - \ - SNAME##_iter iter; \ - \ - for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - 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; \ - } \ - \ - 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; \ - } \ - \ - SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)) \ - { \ - SNAME *result = PFX##_new(_set_->capacity, _set_->load, _set_->cmp, _set_->hash); \ - \ - if (!result) \ - return NULL; \ - \ - if (copy_func) \ - { \ - for (size_t i = 0; i < _set_->capacity; i++) \ - { \ - SNAME##_entry *scan = &(_set_->buffer[i]); \ - \ - if (scan->state != CMC_ES_EMPTY) \ - { \ - SNAME##_entry *target = &(result->buffer[i]); \ - \ - if (scan->state == CMC_ES_DELETED) \ - target->state = CMC_ES_DELETED; \ - else \ - { \ - target->state = scan->state; \ - target->dist = scan->dist; \ - \ - target->value = copy_func(scan->value); \ - } \ - } \ - } \ - } \ - else \ - memcpy(result->buffer, _set_->buffer, sizeof(SNAME##_entry) * _set_->capacity); \ - \ - result->count = _set_->count; \ - \ - return result; \ - } \ - \ - bool PFX##_equals(SNAME *_set1_, SNAME *_set2_) \ - { \ - if (PFX##_count(_set1_) != PFX##_count(_set2_)) \ - return false; \ - \ - if (PFX##_count(_set1_) == 0) \ - return true; \ - \ - SNAME##_iter iter; \ - PFX##_iter_init(&iter, _set1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - if (PFX##_impl_get_entry(_set2_, PFX##_iter_value(&iter)) == NULL) \ - return false; \ - } \ - \ - return true; \ - } \ - \ - cmc_string PFX##_to_string(SNAME *_set_) \ - { \ - cmc_string str; \ - SNAME *s_ = _set_; \ - const char *name = #SNAME; \ - \ - snprintf(str.s, cmc_string_len, cmc_string_fmt_hashset, \ - name, s_, s_->buffer, s_->capacity, s_->count, s_->load, s_->cmp, s_->hash); \ - \ - return str; \ - } \ - \ - SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_) \ - { \ - SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ - \ - if (!_set_r_) \ - return NULL; \ - \ - SNAME##_iter iter1, iter2; \ - PFX##_iter_init(&iter1, _set1_); \ - PFX##_iter_init(&iter2, _set2_); \ - \ - for (PFX##_iter_to_start(&iter1); !PFX##_iter_end(&iter1); PFX##_iter_next(&iter1)) \ - { \ - PFX##_insert(_set_r_, PFX##_iter_value(&iter1)); \ - } \ - \ - for (PFX##_iter_to_start(&iter2); !PFX##_iter_end(&iter2); PFX##_iter_next(&iter2)) \ - { \ - PFX##_insert(_set_r_, PFX##_iter_value(&iter2)); \ - } \ - \ - return _set_r_; \ - } \ - \ - SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_) \ - { \ - SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ - \ - if (!_set_r_) \ - return NULL; \ - \ - SNAME *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; \ - SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \ - \ - SNAME##_iter iter; \ - PFX##_iter_init(&iter, _set_A_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - V value = PFX##_iter_value(&iter); \ - \ - if (PFX##_impl_get_entry(_set_B_, value) != NULL) \ - PFX##_insert(_set_r_, value); \ - } \ - \ - return _set_r_; \ - } \ - \ - SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_) \ - { \ - SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ - \ - if (!_set_r_) \ - return NULL; \ - \ - SNAME##_iter iter; \ - PFX##_iter_init(&iter, _set1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - V value = PFX##_iter_value(&iter); \ - \ - if (PFX##_impl_get_entry(_set2_, value) == NULL) \ - PFX##_insert(_set_r_, value); \ - } \ - \ - return _set_r_; \ - } \ - \ - SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_) \ - { \ - SNAME##_iter iter1, iter2; \ - \ - SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ - \ - if (!_set_r_) \ - return NULL; \ - \ - PFX##_iter_init(&iter1, _set1_); \ - PFX##_iter_init(&iter2, _set2_); \ - \ - for (PFX##_iter_to_start(&iter1); !PFX##_iter_end(&iter1); PFX##_iter_next(&iter1)) \ - { \ - V value = PFX##_iter_value(&iter1); \ - \ - if (PFX##_impl_get_entry(_set2_, value) == NULL) \ - PFX##_insert(_set_r_, value); \ - } \ - \ - for (PFX##_iter_to_start(&iter2); !PFX##_iter_end(&iter2); PFX##_iter_next(&iter2)) \ - { \ - V value = PFX##_iter_value(&iter2); \ - \ - if (PFX##_impl_get_entry(_set1_, value) == NULL) \ - PFX##_insert(_set_r_, value); \ - } \ - \ - return _set_r_; \ - } \ - \ - /* Is _set1_ a subset of _set2_ ? */ \ - /* A set X is a subset of a set Y when: X <= Y */ \ - /* If X is a subset of Y, then Y is a superset of X */ \ - bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_) \ - { \ - /* If the cardinality of _set1_ is greater than that of _set2_, then it is safe to */ \ - /* say that _set1_ can't be a subset of _set2_ */ \ - if (PFX##_count(_set1_) > PFX##_count(_set2_)) \ - return false; \ - \ - /* The empty set is a subset of all sets */ \ - if (PFX##_empty(_set1_)) \ - return true; \ - \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _set1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - V value = PFX##_iter_value(&iter); \ - \ - if (!PFX##_contains(_set2_, value)) \ - return false; \ - } \ - \ - return true; \ - } \ - \ - /* Is _set1_ a superset of _set2_ ? */ \ - /* A set X is a superset of a set Y when: X >= Y */ \ - /* If X is a superset of Y, then Y is a subset of X */ \ - bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_) \ - { \ - return PFX##_is_subset(_set2_, _set1_); \ - } \ - \ - /* Is _set1_ a proper subset of _set2_ ? */ \ - /* A set X is a proper subset of a set Y when: X < Y */ \ - /* If X is a proper subset of Y, then Y is a proper superset of X */ \ - bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_) \ - { \ - /* If the cardinality of _set1_ is greater than or equal to that of _set2_, then it */ \ - /* is safe to say that _set1_ can't be a proper subset of _set2_ */ \ - if (PFX##_count(_set1_) >= PFX##_count(_set2_)) \ - return false; \ - \ - if (PFX##_empty(_set1_)) \ - { \ - /* The empty set is a proper subset of all non-empty sets */ \ - if (!PFX##_empty(_set2_)) \ - return true; \ - /* The empty set is not a proper subset of itself (this is true for any set) */ \ - else \ - return false; \ - } \ - \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _set1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - V value = PFX##_iter_value(&iter); \ - \ - if (!PFX##_contains(_set2_, value)) \ - return false; \ - } \ - \ - return true; \ - } \ - \ - /* Is _set1_ a proper superset of _set2_ ? */ \ - /* A set X is a proper superset of a set Y when: X > Y */ \ - /* If X is a proper superset of Y, then Y is a proper subset of X */ \ - bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_) \ - { \ - return PFX##_is_proper_subset(_set2_, _set1_); \ - } \ - \ - /* Is _set1_ a disjointset of _set2_ ? */ \ - /* A set X is a disjointset of a set Y if their intersection is empty, that is, if */ \ - /* there are no elements in common between the two */ \ - bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_) \ - { \ - /* The intersection of an empty set with any other set will result in an empty set */ \ - if (PFX##_empty(_set1_)) \ - return true; \ - \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _set1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - V value = PFX##_iter_value(&iter); \ - \ - if (PFX##_contains(_set2_, value)) \ - return false; \ - } \ - \ - return true; \ - } \ - \ - SNAME##_iter *PFX##_iter_new(SNAME *target) \ - { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ - { \ - memset(iter, 0, sizeof(SNAME##_iter)); \ - \ - iter->target = target; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - \ - if (!PFX##_empty(target)) \ - { \ - for (size_t i = 0; i < target->capacity; i++) \ - { \ - if (target->buffer[i].state == CMC_ES_FILLED) \ - { \ - iter->first = i; \ - break; \ - } \ - } \ - \ - iter->cursor = iter->first; \ - \ - for (size_t i = target->capacity; i > 0; i--) \ - { \ - if (target->buffer[i - 1].state == CMC_ES_FILLED) \ - { \ - iter->last = i - 1; \ - break; \ - } \ - } \ - } \ - } \ - \ - bool PFX##_iter_start(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->first; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - } \ - } \ - \ - void PFX##_iter_to_end(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->last; \ - iter->index = PFX##_count(iter->target) - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - } \ - } \ - \ - bool PFX##_iter_next(SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->index + 1 == PFX##_count(iter->target)) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ - \ - iter->index++; \ - \ - while (1) \ - { \ - iter->cursor++; \ - scan = &(iter->target->buffer[iter->cursor]); \ - \ - if (scan->state == CMC_ES_FILLED) \ - break; \ - } \ - \ - return true; \ - } \ - \ - bool PFX##_iter_prev(SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->index == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ - \ - iter->index--; \ - \ - while (1) \ - { \ - iter->cursor--; \ - scan = &(iter->target->buffer[iter->cursor]); \ - \ - if (scan->state == CMC_ES_FILLED) \ - break; \ - } \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->index + 1 == PFX##_count(iter->target)) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ - return false; \ - \ - for (size_t i = 0; i < steps; i++) \ - PFX##_iter_next(iter); \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->index == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index < steps) \ - return false; \ - \ - for (size_t i = 0; i < steps; i++) \ - PFX##_iter_prev(iter); \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator was able to be positioned at the given index */ \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ - { \ - if (index >= PFX##_count(iter->target)) \ - return false; \ - \ - if (iter->index > index) \ - return PFX##_iter_rewind(iter, iter->index - index); \ - else if (iter->index < index) \ - return PFX##_iter_advance(iter, index - iter->index); \ - \ - return true; \ - } \ - \ - V PFX##_iter_value(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){0}; \ - \ - return iter->target->buffer[iter->cursor].value; \ - } \ - \ - size_t PFX##_iter_index(SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - static SNAME##_entry *PFX##_impl_get_entry(SNAME *_set_, V element) \ - { \ - size_t hash = _set_->hash(element); \ - size_t pos = hash % _set_->capacity; \ - \ - SNAME##_entry *target = &(_set_->buffer[pos]); \ - \ - while (target->state == CMC_ES_FILLED || target->state == CMC_ES_DELETED) \ - { \ - if (_set_->cmp(target->value, element) == 0) \ - return target; \ - \ - pos++; \ - target = &(_set_->buffer[pos % _set_->capacity]); \ - } \ - \ - return NULL; \ - } \ - \ - static size_t PFX##_impl_calculate_size(size_t required) \ - { \ - const size_t count = sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]); \ - \ - if (cmc_hashtable_primes[count - 1] < required) \ - return required; \ - \ - size_t i = 0; \ - while (cmc_hashtable_primes[i] < required) \ - i++; \ - \ - return cmc_hashtable_primes[i]; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_set_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _set_); \ - \ - return iter; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_set_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _set_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ +#define CMC_GENERATE_HASHSET_SOURCE(PFX, SNAME, V) \ + \ + /* Implementation Detail Functions */ \ + static 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)) \ + { \ + 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_ = malloc(sizeof(struct SNAME)); \ + \ + if (!_set_) \ + return NULL; \ + \ + _set_->buffer = calloc(real_capacity, sizeof(struct SNAME##_entry)); \ + \ + if (!_set_->buffer) \ + { \ + 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; \ + \ + 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_); \ + } \ + \ + 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(_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->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_; \ + const char *name = #SNAME; \ + \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_hashset, \ + name, s_, s_->buffer, s_->capacity, s_->count, s_->load, s_->cmp, s_->hash); \ + \ + return str; \ + } \ + \ + 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 = 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 = 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 42e7975..9368c81 100644 --- a/src/cmc/heap.h +++ b/src/cmc/heap.h @@ -40,11 +40,11 @@ /* to_string format */ static const char *cmc_string_fmt_heap = "%s at %p { buffer:%p, capacity:%" PRIuMAX ", count:%" PRIuMAX ", type:%s, cmp:%p }"; -typedef enum cmc_heap_order_e +enum cmc_heap_order { cmc_max_heap = 1, cmc_min_heap = -1 -} cmc_heap_order; +}; #define CMC_GENERATE_HEAP(PFX, SNAME, V) \ CMC_GENERATE_HEAP_HEADER(PFX, SNAME, V) \ @@ -57,104 +57,102 @@ typedef enum cmc_heap_order_e CMC_GENERATE_HEAP_SOURCE(PFX, SNAME, V) /* HEADER ********************************************************************/ -#define CMC_GENERATE_HEAP_HEADER(PFX, SNAME, V) \ - \ - /* Heap Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Dynamic array of elements */ \ - V *buffer; \ - \ - /* Current array capacity */ \ - size_t capacity; \ - \ - /* Current amount of elements in the heap */ \ - size_t count; \ - \ - /* Heap order (MaxHeap or MinHeap) */ \ - enum cmc_heap_order_e HO; \ - \ - /* Element comparison function */ \ - int (*cmp)(V, V); \ - \ - /* Function that returns an iterator to the start of the heap */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the heap */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Heap Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target heap */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - SNAME *PFX##_new(size_t capacity, cmc_heap_order HO, int (*compare)(V, V)); \ - void PFX##_clear(SNAME *_heap_, void (*deallocator)(V)); \ - void PFX##_free(SNAME *_heap_, void (*deallocator)(V)); \ - /* Collection Input and Output */ \ - bool PFX##_insert(SNAME *_heap_, V element); \ - bool PFX##_remove(SNAME *_heap_, V *result); \ - /* Element Access */ \ - V PFX##_peek(SNAME *_heap_); \ - /* Collection State */ \ - bool PFX##_contains(SNAME *_heap_, V element); \ - bool PFX##_empty(SNAME *_heap_); \ - bool PFX##_full(SNAME *_heap_); \ - size_t PFX##_count(SNAME *_heap_); \ - size_t PFX##_capacity(SNAME *_heap_); \ - /* Collection Utility */ \ - bool PFX##_resize(SNAME *_heap_, size_t capacity); \ - SNAME *PFX##_copy_of(SNAME *_heap_, V (*copy_func)(V)); \ - bool PFX##_equals(SNAME *_heap1_, SNAME *_heap2_); \ - cmc_string PFX##_to_string(SNAME *_heap_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - SNAME##_iter *PFX##_iter_new(SNAME *target); \ - void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(SNAME##_iter *iter); \ - bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(SNAME##_iter *iter); \ - void PFX##_iter_to_end(SNAME##_iter *iter); \ - bool PFX##_iter_next(SNAME##_iter *iter); \ - bool PFX##_iter_prev(SNAME##_iter *iter); \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - V PFX##_iter_value(SNAME##_iter *iter); \ - size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ +#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 *); \ + }; \ + \ + /* 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)); \ + void PFX##_clear(struct SNAME *_heap_, void (*deallocator)(V)); \ + void PFX##_free(struct SNAME *_heap_, void (*deallocator)(V)); \ + /* 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(SNAME *_heap_, size_t index); \ - static bool PFX##_impl_float_down(SNAME *_heap_, size_t index); \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_heap_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_heap_); \ + 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_); \ \ - SNAME *PFX##_new(size_t capacity, cmc_heap_order HO, int (*compare)(V, V)) \ + struct SNAME *PFX##_new(size_t capacity, enum cmc_heap_order HO, int (*compare)(V, V)) \ { \ if (capacity < 1) \ return NULL; \ @@ -162,7 +160,7 @@ typedef enum cmc_heap_order_e if (HO != cmc_min_heap && HO != cmc_max_heap) \ return NULL; \ \ - SNAME *_heap_ = malloc(sizeof(SNAME)); \ + struct SNAME *_heap_ = malloc(sizeof(struct SNAME)); \ \ if (!_heap_) \ return NULL; \ @@ -186,7 +184,7 @@ typedef enum cmc_heap_order_e return _heap_; \ } \ \ - void PFX##_clear(SNAME *_heap_, void (*deallocator)(V)) \ + void PFX##_clear(struct SNAME *_heap_, void (*deallocator)(V)) \ { \ if (deallocator) \ { \ @@ -201,7 +199,7 @@ typedef enum cmc_heap_order_e _heap_->count = 0; \ } \ \ - void PFX##_free(SNAME *_heap_, void (*deallocator)(V)) \ + void PFX##_free(struct SNAME *_heap_, void (*deallocator)(V)) \ { \ if (deallocator) \ { \ @@ -215,7 +213,7 @@ typedef enum cmc_heap_order_e free(_heap_); \ } \ \ - bool PFX##_insert(SNAME *_heap_, V element) \ + bool PFX##_insert(struct SNAME *_heap_, V element) \ { \ if (PFX##_full(_heap_)) \ { \ @@ -237,7 +235,7 @@ typedef enum cmc_heap_order_e return true; \ } \ \ - bool PFX##_remove(SNAME *_heap_, V *result) \ + bool PFX##_remove(struct SNAME *_heap_, V *result) \ { \ if (PFX##_empty(_heap_)) \ return false; \ @@ -254,7 +252,7 @@ typedef enum cmc_heap_order_e return true; \ } \ \ - V PFX##_peek(SNAME *_heap_) \ + V PFX##_peek(struct SNAME *_heap_) \ { \ if (PFX##_empty(_heap_)) \ return (V){0}; \ @@ -262,7 +260,7 @@ typedef enum cmc_heap_order_e return _heap_->buffer[0]; \ } \ \ - bool PFX##_contains(SNAME *_heap_, V element) \ + bool PFX##_contains(struct SNAME *_heap_, V element) \ { \ for (size_t i = 0; i < _heap_->count; i++) \ { \ @@ -273,27 +271,27 @@ typedef enum cmc_heap_order_e return false; \ } \ \ - bool PFX##_empty(SNAME *_heap_) \ + bool PFX##_empty(struct SNAME *_heap_) \ { \ return _heap_->count == 0; \ } \ \ - bool PFX##_full(SNAME *_heap_) \ + bool PFX##_full(struct SNAME *_heap_) \ { \ return _heap_->count >= _heap_->capacity; \ } \ \ - size_t PFX##_count(SNAME *_heap_) \ + size_t PFX##_count(struct SNAME *_heap_) \ { \ return _heap_->count; \ } \ \ - size_t PFX##_capacity(SNAME *_heap_) \ + size_t PFX##_capacity(struct SNAME *_heap_) \ { \ return _heap_->capacity; \ } \ \ - bool PFX##_resize(SNAME *_heap_, size_t capacity) \ + bool PFX##_resize(struct SNAME *_heap_, size_t capacity) \ { \ if (PFX##_capacity(_heap_) == capacity) \ return true; \ @@ -312,9 +310,9 @@ typedef enum cmc_heap_order_e return true; \ } \ \ - SNAME *PFX##_copy_of(SNAME *_heap_, V (*copy_func)(V)) \ + struct SNAME *PFX##_copy_of(struct SNAME *_heap_, V (*copy_func)(V)) \ { \ - SNAME *result = PFX##_new(_heap_->capacity, _heap_->HO, _heap_->cmp); \ + struct SNAME *result = PFX##_new(_heap_->capacity, _heap_->HO, _heap_->cmp); \ \ if (!result) \ return NULL; \ @@ -332,7 +330,7 @@ typedef enum cmc_heap_order_e return result; \ } \ \ - bool PFX##_equals(SNAME *_heap1_, SNAME *_heap2_) \ + bool PFX##_equals(struct SNAME *_heap1_, struct SNAME *_heap2_) \ { \ if (PFX##_count(_heap1_) != PFX##_count(_heap2_)) \ return false; \ @@ -346,10 +344,10 @@ typedef enum cmc_heap_order_e return true; \ } \ \ - cmc_string PFX##_to_string(SNAME *_heap_) \ + struct cmc_string PFX##_to_string(struct SNAME *_heap_) \ { \ - cmc_string str; \ - SNAME *h_ = _heap_; \ + struct cmc_string str; \ + struct SNAME *h_ = _heap_; \ const char *name = #SNAME; \ const char *t = h_->HO == 1 ? "MaxHeap" : "MinHeap"; \ \ @@ -359,9 +357,9 @@ typedef enum cmc_heap_order_e return str; \ } \ \ - SNAME##_iter *PFX##_iter_new(SNAME *target) \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ + struct SNAME##_iter *iter = malloc(sizeof(struct SNAME##_iter)); \ \ if (!iter) \ return NULL; \ @@ -371,12 +369,12 @@ typedef enum cmc_heap_order_e return iter; \ } \ \ - void PFX##_iter_free(SNAME##_iter *iter) \ + void PFX##_iter_free(struct SNAME##_iter *iter) \ { \ free(iter); \ } \ \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ { \ iter->target = target; \ iter->cursor = 0; \ @@ -384,17 +382,17 @@ typedef enum cmc_heap_order_e iter->end = PFX##_empty(target); \ } \ \ - bool PFX##_iter_start(SNAME##_iter *iter) \ + bool PFX##_iter_start(struct SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->start; \ } \ \ - bool PFX##_iter_end(SNAME##_iter *iter) \ + bool PFX##_iter_end(struct SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->end; \ } \ \ - void PFX##_iter_to_start(SNAME##_iter *iter) \ + void PFX##_iter_to_start(struct SNAME##_iter *iter) \ { \ if (!PFX##_empty(iter->target)) \ { \ @@ -404,7 +402,7 @@ typedef enum cmc_heap_order_e } \ } \ \ - void PFX##_iter_to_end(SNAME##_iter *iter) \ + void PFX##_iter_to_end(struct SNAME##_iter *iter) \ { \ if (!PFX##_empty(iter->target)) \ { \ @@ -414,7 +412,7 @@ typedef enum cmc_heap_order_e } \ } \ \ - bool PFX##_iter_next(SNAME##_iter *iter) \ + bool PFX##_iter_next(struct SNAME##_iter *iter) \ { \ if (iter->end) \ return false; \ @@ -432,7 +430,7 @@ typedef enum cmc_heap_order_e return true; \ } \ \ - bool PFX##_iter_prev(SNAME##_iter *iter) \ + bool PFX##_iter_prev(struct SNAME##_iter *iter) \ { \ if (iter->start) \ return false; \ @@ -451,7 +449,7 @@ typedef enum cmc_heap_order_e } \ \ /* Returns true only if the iterator moved */ \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps) \ { \ if (iter->start) \ return false; \ @@ -476,7 +474,7 @@ typedef enum cmc_heap_order_e } \ \ /* Returns true only if the iterator moved */ \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps) \ { \ if (iter->start) \ return false; \ @@ -498,7 +496,7 @@ typedef enum cmc_heap_order_e } \ \ /* Returns true only if the iterator was able to be positioned at the given index */ \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index) \ { \ if (index >= PFX##_count(iter->target)) \ return false; \ @@ -511,7 +509,7 @@ typedef enum cmc_heap_order_e return true; \ } \ \ - V PFX##_iter_value(SNAME##_iter *iter) \ + V PFX##_iter_value(struct SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ return (V){0}; \ @@ -519,12 +517,12 @@ typedef enum cmc_heap_order_e return iter->target->buffer[iter->cursor]; \ } \ \ - size_t PFX##_iter_index(SNAME##_iter *iter) \ + size_t PFX##_iter_index(struct SNAME##_iter *iter) \ { \ return iter->cursor; \ } \ \ - static bool PFX##_impl_float_up(SNAME *_heap_, size_t index) \ + static bool PFX##_impl_float_up(struct SNAME *_heap_, size_t index) \ { \ /* Current index */ \ size_t C = index; \ @@ -550,7 +548,7 @@ typedef enum cmc_heap_order_e return true; \ } \ \ - static bool PFX##_impl_float_down(SNAME *_heap_, size_t index) \ + static bool PFX##_impl_float_down(struct SNAME *_heap_, size_t index) \ { \ int mod = _heap_->HO; \ \ @@ -587,9 +585,9 @@ typedef enum cmc_heap_order_e return true; \ } \ \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_heap_) \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_heap_) \ { \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ \ PFX##_iter_init(&iter, _heap_); \ PFX##_iter_to_start(&iter); \ @@ -597,9 +595,9 @@ typedef enum cmc_heap_order_e return iter; \ } \ \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_heap_) \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_heap_) \ { \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ \ PFX##_iter_init(&iter, _heap_); \ PFX##_iter_to_end(&iter); \ diff --git a/src/cmc/intervalheap.h b/src/cmc/intervalheap.h index 69c7908..36ebfa4 100644 --- a/src/cmc/intervalheap.h +++ b/src/cmc/intervalheap.h @@ -42,909 +42,906 @@ static const char *cmc_string_fmt_intervalheap = "%s at %p { buffer:%p, capacity CMC_GENERATE_INTERVALHEAP_SOURCE(PFX, SNAME, V) /* HEADER ********************************************************************/ -#define CMC_GENERATE_INTERVALHEAP_HEADER(PFX, SNAME, V) \ - \ - /* Heap Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Dynamic array of nodes */ \ - struct SNAME##_node_s *buffer; \ - \ - /* Current array capacity (how many nodes can be stored) */ \ - size_t capacity; \ - \ - /* Current amount of nodes in the dynamic array */ \ - size_t size; \ - \ - /* Current amount of elements in the heap */ \ - size_t count; \ - \ - /* Element comparison function */ \ - int (*cmp)(V, V); \ - \ - /* Function that returns an iterator to the start of the heap */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the heap */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Heap Node */ \ - typedef struct SNAME##_node_s \ - { \ - /* 0 - Value belonging to the MinHeap */ \ - /* 1 - Value belonging to the MaxHeap */ \ - V data[2]; \ - \ - } SNAME##_node, *SNAME##_node_ptr; \ - \ - /* Heap Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target heap */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)); \ - void PFX##_clear(SNAME *_heap_, void (*deallocator)(V)); \ - void PFX##_free(SNAME *_heap_, void (*deallocator)(V)); \ - /* Collection Input and Output */ \ - bool PFX##_insert(SNAME *_heap_, V element); \ - bool PFX##_remove_max(SNAME *_heap_, V *result); \ - bool PFX##_remove_min(SNAME *_heap_, V *result); \ - /* Collection Update */ \ - bool PFX##_update_max(SNAME *_heap_, V element); \ - bool PFX##_update_min(SNAME *_heap_, V element); \ - /* Element Access */ \ - bool PFX##_max(SNAME *_heap_, V *value); \ - bool PFX##_min(SNAME *_heap_, V *value); \ - /* Collection State */ \ - bool PFX##_contains(SNAME *_heap_, V element); \ - bool PFX##_empty(SNAME *_heap_); \ - bool PFX##_full(SNAME *_heap_); \ - size_t PFX##_count(SNAME *_heap_); \ - size_t PFX##_capacity(SNAME *_heap_); \ - /* Collection Utility */ \ - bool PFX##_resize(SNAME *_heap_, size_t capacity); \ - SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)); \ - bool PFX##_equals(SNAME *_heap1_, SNAME *_heap2_); \ - cmc_string PFX##_to_string(SNAME *_heap_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - SNAME##_iter *PFX##_iter_new(SNAME *target); \ - void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(SNAME##_iter *iter); \ - bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(SNAME##_iter *iter); \ - void PFX##_iter_to_end(SNAME##_iter *iter); \ - bool PFX##_iter_next(SNAME##_iter *iter); \ - bool PFX##_iter_prev(SNAME##_iter *iter); \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - V PFX##_iter_value(SNAME##_iter *iter); \ - size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ +#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 *); \ + }; \ + \ + /* 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)); \ + void PFX##_clear(struct SNAME *_heap_, void (*deallocator)(V)); \ + void PFX##_free(struct SNAME *_heap_, void (*deallocator)(V)); \ + /* 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(SNAME *_heap_); \ - static void PFX##_impl_float_up_min(SNAME *_heap_); \ - static void PFX##_impl_float_down_max(SNAME *_heap_); \ - static void PFX##_impl_float_down_min(SNAME *_heap_); \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_heap_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_heap_); \ - \ - SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)) \ - { \ - if (capacity == 0 || capacity == UINT64_MAX) \ - return NULL; \ - \ - SNAME *_heap_ = malloc(sizeof(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 = calloc(capacity, sizeof(SNAME##_node)); \ - \ - if (!_heap_->buffer) \ - { \ - 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; \ - \ - return _heap_; \ - } \ - \ - void PFX##_clear(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(SNAME *_heap_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _heap_->count; i++) \ - { \ - deallocator(_heap_->buffer[i / 2].data[i % 2]); \ - } \ - } \ - \ - free(_heap_->buffer); \ - \ - free(_heap_); \ - } \ - \ - bool PFX##_insert(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 \ - { \ - 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 */ \ - 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(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 */ \ - 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(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 */ \ - 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(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(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(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(SNAME *_heap_, V *value) \ - { \ - if (PFX##_empty(_heap_)) \ - return false; \ - \ - *value = _heap_->buffer[0].data[0]; \ - \ - return true; \ - } \ - \ - bool PFX##_contains(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(SNAME *_heap_) \ - { \ - return _heap_->count == 0; \ - } \ - \ - bool PFX##_full(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(SNAME *_heap_) \ - { \ - return _heap_->count; \ - } \ - \ - size_t PFX##_capacity(SNAME *_heap_) \ - { \ - return _heap_->capacity; \ - } \ - \ - bool PFX##_resize(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; \ - \ - SNAME##_node *new_buffer = realloc(_heap_->buffer, sizeof(SNAME##_node) * capacity); \ - \ - if (!new_buffer) \ - return false; \ - \ - memset(new_buffer + _heap_->capacity, 0, sizeof(SNAME##_node) * _heap_->capacity); \ - \ - _heap_->buffer = new_buffer; \ - _heap_->capacity = capacity; \ - \ - return true; \ - } \ - \ - SNAME *PFX##_copy_of(SNAME *_heap_, V (*copy_func)(V)) \ - { \ - SNAME *result = malloc(sizeof(SNAME)); \ - \ - if (!result) \ - return NULL; \ - \ - memcpy(result, _heap_, sizeof(SNAME)); \ - \ - result->buffer = malloc(sizeof(SNAME##_node) * _heap_->capacity); \ - \ - if (!result->buffer) \ - { \ - 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(SNAME##_node) * _heap_->capacity); \ - \ - return result; \ - } \ - \ - bool PFX##_equals(SNAME *_heap1_, 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; \ - } \ - \ - cmc_string PFX##_to_string(SNAME *_heap_) \ - { \ - cmc_string str; \ - SNAME *h_ = _heap_; \ - const char *name = #SNAME; \ - \ - snprintf(str.s, cmc_string_len, cmc_string_fmt_intervalheap, \ - name, h_, h_->buffer, h_->capacity, h_->size, h_->count, h_->cmp); \ - \ - return str; \ - } \ - \ - SNAME##_iter *PFX##_iter_new(SNAME *target) \ - { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ - { \ - iter->target = target; \ - iter->cursor = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - } \ - \ - bool PFX##_iter_start(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - } \ - } \ - \ - void PFX##_iter_to_end(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - } \ - } \ - \ - bool PFX##_iter_next(SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->cursor + 1 == PFX##_count(iter->target)) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - iter->cursor++; \ - \ - return true; \ - } \ - \ - bool PFX##_iter_prev(SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->cursor == 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(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(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(SNAME##_iter *iter, size_t index) \ - { \ - if (index >= PFX##_count(iter->target)) \ - return false; \ - \ - if (iter->cursor > index) \ - return PFX##_iter_rewind(iter, iter->cursor - index); \ - else if (iter->cursor < index) \ - return PFX##_iter_advance(iter, index - iter->cursor); \ - \ - return true; \ - } \ - \ - V PFX##_iter_value(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){0}; \ - \ - return iter->target->buffer[iter->cursor / 2].data[iter->cursor % 2]; \ - } \ - \ - size_t PFX##_iter_index(SNAME##_iter *iter) \ - { \ - return iter->cursor; \ - } \ - \ - static void PFX##_impl_float_up_max(SNAME *_heap_) \ - { \ - size_t index = _heap_->size - 1; \ - \ - SNAME##_node *curr_node = &(_heap_->buffer[index]); \ - \ - /* FLoat Up on the MaxHeap */ \ - while (index > 0) \ - { \ - /* Parent index */ \ - size_t P_index = (index - 1) / 2; \ - \ - 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(SNAME *_heap_) \ - { \ - size_t index = _heap_->size - 1; \ - \ - SNAME##_node *curr_node = &(_heap_->buffer[index]); \ - \ - /* FLoat Up on the MinHeap */ \ - while (index > 0) \ - { \ - /* Parent index */ \ - size_t P_index = (index - 1) / 2; \ - \ - 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(SNAME *_heap_) \ - { \ - /* Floats Down from the MinHeap */ \ - size_t index = 0; \ - \ - 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) \ - { \ - SNAME##_node *L = &(_heap_->buffer[L_index]); \ - 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; \ - \ - 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(SNAME *_heap_) \ - { \ - /* Floats Down from the MinHeap */ \ - size_t index = 0; \ - \ - 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) \ - { \ - SNAME##_node *L = &(_heap_->buffer[L_index]); \ - 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; \ - \ - 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 SNAME##_iter PFX##_impl_it_start(SNAME *_heap_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _heap_); \ - PFX##_iter_to_start(&iter); \ - \ - return iter; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_heap_) \ - { \ - 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)) \ + { \ + if (capacity == 0 || capacity == UINT64_MAX) \ + return NULL; \ + \ + struct SNAME *_heap_ = 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 = calloc(capacity, sizeof(struct SNAME##_node)); \ + \ + if (!_heap_->buffer) \ + { \ + 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; \ + \ + 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]); \ + } \ + } \ + \ + free(_heap_->buffer); \ + \ + free(_heap_); \ + } \ + \ + 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 = 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 = malloc(sizeof(struct SNAME)); \ + \ + if (!result) \ + return NULL; \ + \ + memcpy(result, _heap_, sizeof(struct SNAME)); \ + \ + result->buffer = malloc(sizeof(struct SNAME##_node) * _heap_->capacity); \ + \ + if (!result->buffer) \ + { \ + 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); \ + \ + 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_; \ + const char *name = #SNAME; \ + \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_intervalheap, \ + name, h_, h_->buffer, h_->capacity, h_->size, h_->count, h_->cmp); \ + \ + 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) \ + { \ + 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 af89c76..c9c417f 100644 --- a/src/cmc/linkedlist.h +++ b/src/cmc/linkedlist.h @@ -49,857 +49,854 @@ static const char *cmc_string_fmt_linkedlist = "%s at %p { count:%" PRIuMAX ", h CMC_GENERATE_LINKEDLIST_SOURCE(PFX, SNAME, V) /* HEADER ********************************************************************/ -#define CMC_GENERATE_LINKEDLIST_HEADER(PFX, SNAME, V) \ - \ - /* Linked List Structure */ \ - typedef struct SNAME##_s \ - { \ - /* First node in the list */ \ - struct SNAME##_node_s *head; \ - \ - /* Last node in the list */ \ - struct SNAME##_node_s *tail; \ - \ - /* Current amount of elements in the list */ \ - size_t count; \ - \ - /* Function that returns an iterator to the start of the list */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the list */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Doubly-linked list node */ \ - typedef struct SNAME##_node_s \ - { \ - /* Node's data */ \ - V data; \ - \ - /* Pointer to the next node on the linked list */ \ - struct SNAME##_node_s *next; \ - \ - /* Pointer to the previous node on the linked list */ \ - struct SNAME##_node_s *prev; \ - \ - } SNAME##_node, *SNAME##_node_ptr; \ - \ - /* Linked List Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target Linked List */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's current node */ \ - struct SNAME##_node_s *cursor; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - SNAME *PFX##_new(void); \ - void PFX##_clear(SNAME *_list_, void (*deallocator)(V)); \ - void PFX##_free(SNAME *_list_, void (*deallocator)(V)); \ - /* Collection Input and Output */ \ - bool PFX##_push_front(SNAME *_list_, V element); \ - bool PFX##_push_at(SNAME *_list_, V element, size_t index); \ - bool PFX##_push_back(SNAME *_list_, V element); \ - bool PFX##_pop_front(SNAME *_list_); \ - bool PFX##_pop_at(SNAME *_list_, size_t index); \ - bool PFX##_pop_back(SNAME *_list_); \ - /* Element Access */ \ - V PFX##_front(SNAME *_list_); \ - V PFX##_get(SNAME *_list_, size_t index); \ - V *PFX##_get_ref(SNAME *_list_, size_t index); \ - V PFX##_back(SNAME *_list_); \ - /* Collection State */ \ - bool PFX##_contains(SNAME *_list_, V element, int (*comparator)(V, V)); \ - bool PFX##_empty(SNAME *_list_); \ - size_t PFX##_count(SNAME *_list_); \ - /* Collection Utility */ \ - SNAME *PFX##_copy_of(SNAME *_list_, V (*copy_func)(V)); \ - bool PFX##_equals(SNAME *_list1_, SNAME *_list2_, int (*comparator)(V, V)); \ - cmc_string PFX##_to_string(SNAME *_list_); \ - \ - /* Node Related Functions */ \ - /* Node Allocation and Deallocation */ \ - SNAME##_node *PFX##_new_node(V element); \ - void PFX##_free_node(SNAME##_node *_node_); \ - /* Node Access Relative to a Linked List */ \ - SNAME##_node *PFX##_head(SNAME *_list_); \ - SNAME##_node *PFX##_get_node(SNAME *_list_, size_t index); \ - SNAME##_node *PFX##_tail(SNAME *_list_); \ - /* Input and Output Relative to a Node */ \ - bool PFX##_insert_after(SNAME *_owner_, SNAME##_node *_node_, V element); \ - bool PFX##_insert_before(SNAME *_owner_, SNAME##_node *_node_, V element); \ - bool PFX##_remove_after(SNAME *_owner_, SNAME##_node *_node_); \ - bool PFX##_remove_current(SNAME *_owner_, SNAME##_node *_node_); \ - bool PFX##_remove_before(SNAME *_owner_, SNAME##_node *_node_); \ - /* Node Access Relative to a Linked List Node */ \ - SNAME##_node *PFX##_next_node(SNAME##_node *_node_); \ - SNAME##_node *PFX##_prev_node(SNAME##_node *_node_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - SNAME##_iter *PFX##_iter_new(SNAME *target); \ - void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(SNAME##_iter *iter); \ - bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(SNAME##_iter *iter); \ - void PFX##_iter_to_end(SNAME##_iter *iter); \ - bool PFX##_iter_next(SNAME##_iter *iter); \ - bool PFX##_iter_prev(SNAME##_iter *iter); \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - V PFX##_iter_value(SNAME##_iter *iter); \ - V *PFX##_iter_rvalue(SNAME##_iter *iter); \ - size_t PFX##_iter_index(SNAME##_iter *iter); \ - SNAME##_node *PFX##_iter_node(SNAME##_iter *iter); \ - \ +#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 *); \ + }; \ + \ + /* 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); \ + void PFX##_clear(struct SNAME *_list_, void (*deallocator)(V)); \ + void PFX##_free(struct SNAME *_list_, void (*deallocator)(V)); \ + /* 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(V element); \ + void PFX##_free_node(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 SNAME##_iter PFX##_impl_it_start(SNAME *_list_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_list_); \ - \ - SNAME *PFX##_new(void) \ - { \ - SNAME *_list_ = malloc(sizeof(SNAME)); \ - \ - if (!_list_) \ - return NULL; \ - \ - _list_->count = 0; \ - _list_->head = NULL; \ - _list_->tail = NULL; \ - \ - _list_->it_start = PFX##_impl_it_start; \ - _list_->it_end = PFX##_impl_it_end; \ - \ - return _list_; \ - } \ - \ - void PFX##_clear(SNAME *_list_, void (*deallocator)(V)) \ - { \ - SNAME##_node *scan = _list_->head; \ - \ - while (_list_->head != NULL) \ - { \ - _list_->head = _list_->head->next; \ - \ - if (deallocator) \ - { \ - deallocator(scan->data); \ - } \ - \ - free(scan); \ - \ - scan = _list_->head; \ - } \ - \ - _list_->count = 0; \ - _list_->head = NULL; \ - _list_->tail = NULL; \ - } \ - \ - void PFX##_free(SNAME *_list_, void (*deallocator)(V)) \ - { \ - PFX##_clear(_list_, deallocator); \ - \ - free(_list_); \ - } \ - \ - bool PFX##_push_front(SNAME *_list_, V element) \ - { \ - SNAME##_node *_node_ = PFX##_new_node(element); \ - \ - if (!_node_) \ - return false; \ - \ - if (PFX##_empty(_list_)) \ - { \ - _list_->head = _node_; \ - _list_->tail = _node_; \ - } \ - else \ - { \ - _node_->next = _list_->head; \ - _list_->head->prev = _node_; \ - _list_->head = _node_; \ - } \ - \ - _list_->count++; \ - \ - return true; \ - } \ - \ - bool PFX##_push_at(SNAME *_list_, V element, size_t index) \ - { \ - if (index > _list_->count) \ - return false; \ - \ - if (index == 0) \ - { \ - return PFX##_push_front(_list_, element); \ - } \ - else if (index == _list_->count) \ - { \ - return PFX##_push_back(_list_, element); \ - } \ - \ - SNAME##_node *_node_ = PFX##_new_node(element); \ - \ - if (!_node_) \ - return false; \ - \ - SNAME##_node *scan = PFX##_get_node(_list_, index - 1); \ - \ - _node_->next = scan->next; \ - _node_->prev = scan; \ - _node_->next->prev = _node_; \ - _node_->prev->next = _node_; \ - \ - _list_->count++; \ - \ - return true; \ - } \ - \ - bool PFX##_push_back(SNAME *_list_, V element) \ - { \ - SNAME##_node *_node_ = PFX##_new_node(element); \ - \ - if (!_node_) \ - return false; \ - \ - if (PFX##_empty(_list_)) \ - { \ - _list_->head = _node_; \ - _list_->tail = _node_; \ - } \ - else \ - { \ - _node_->prev = _list_->tail; \ - _list_->tail->next = _node_; \ - _list_->tail = _node_; \ - } \ - \ - _list_->count++; \ - \ - return true; \ - } \ - \ - bool PFX##_pop_front(SNAME *_list_) \ - { \ - if (PFX##_empty(_list_)) \ - return false; \ - \ - SNAME##_node *_node_ = _list_->head; \ - _list_->head = _list_->head->next; \ - \ - free(_node_); \ - \ - if (_list_->head == NULL) \ - _list_->tail = NULL; \ - else \ - _list_->head->prev = NULL; \ - \ - _list_->count--; \ - \ - return true; \ - } \ - \ - bool PFX##_pop_at(SNAME *_list_, size_t index) \ - { \ - if (PFX##_empty(_list_)) \ - return false; \ - \ - if (index >= _list_->count) \ - return false; \ - \ - if (index == 0) \ - { \ - return PFX##_pop_front(_list_); \ - } \ - else if (index == _list_->count - 1) \ - { \ - return PFX##_pop_back(_list_); \ - } \ - \ - SNAME##_node *_node_ = PFX##_get_node(_list_, index); \ - \ - if (!_node_) \ - return false; \ - \ - _node_->next->prev = _node_->prev; \ - _node_->prev->next = _node_->next; \ - \ - free(_node_); \ - \ - _list_->count--; \ - \ - return true; \ - } \ - \ - bool PFX##_pop_back(SNAME *_list_) \ - { \ - if (PFX##_empty(_list_)) \ - return false; \ - \ - SNAME##_node *_node_ = _list_->tail; \ - _list_->tail = _list_->tail->prev; \ - \ - free(_node_); \ - \ - if (_list_->tail == NULL) \ - _list_->head = NULL; \ - else \ - _list_->tail->next = NULL; \ - \ - _list_->count--; \ - \ - return true; \ - } \ - \ - V PFX##_front(SNAME *_list_) \ - { \ - if (PFX##_empty(_list_)) \ - return (V){0}; \ - \ - return _list_->head->data; \ - } \ - \ - V PFX##_get(SNAME *_list_, size_t index) \ - { \ - if (index >= _list_->count || PFX##_empty(_list_)) \ - return (V){0}; \ - \ - SNAME##_node *scan = PFX##_get_node(_list_, index); \ - \ - if (scan == NULL) \ - return (V){0}; \ - \ - return scan->data; \ - } \ - \ - V *PFX##_get_ref(SNAME *_list_, size_t index) \ - { \ - if (index >= _list_->count) \ - return NULL; \ - \ - if (PFX##_empty(_list_)) \ - return NULL; \ - \ - SNAME##_node *scan = PFX##_get_node(_list_, index); \ - \ - if (scan == NULL) \ - return NULL; \ - \ - return &(scan->data); \ - } \ - \ - V PFX##_back(SNAME *_list_) \ - { \ - if (PFX##_empty(_list_)) \ - return (V){0}; \ - \ - return _list_->tail->data; \ - } \ - \ - bool PFX##_contains(SNAME *_list_, V element, int (*comparator)(V, V)) \ - { \ - SNAME##_node *scan = _list_->head; \ - \ - while (scan != NULL) \ - { \ - if (comparator(scan->data, element) == 0) \ - return true; \ - \ - scan = scan->next; \ - } \ - \ - return false; \ - } \ - \ - bool PFX##_empty(SNAME *_list_) \ - { \ - return _list_->count == 0; \ - } \ - \ - size_t PFX##_count(SNAME *_list_) \ - { \ - return _list_->count; \ - } \ - \ - SNAME *PFX##_copy_of(SNAME *_list_, V (*copy_func)(V)) \ - { \ - SNAME *result = PFX##_new(); \ - \ - if (!result) \ - return NULL; \ - \ - SNAME##_node *scan = _list_->head; \ - \ - while (scan != NULL) \ - { \ - /* This allocation should never fail since it might not be */ \ - /* possible to recover from it. That is why it isn't checked */ \ - SNAME##_node *new_node; \ - \ - if (copy_func) \ - new_node = PFX##_new_node(copy_func(scan->data)); \ - else \ - new_node = PFX##_new_node(scan->data); \ - \ - if (!result->head) \ - { \ - result->head = new_node; \ - result->tail = new_node; \ - } \ - else \ - { \ - new_node->prev = result->tail; \ - result->tail->next = new_node; \ - result->tail = new_node; \ - } \ - \ - scan = scan->next; \ - } \ - \ - result->count = _list_->count; \ - \ - return result; \ - } \ - \ - bool PFX##_equals(SNAME *_list1_, SNAME *_list2_, int (*comparator)(V, V)) \ - { \ - if (PFX##_count(_list1_) != PFX##_count(_list2_)) \ - return false; \ - \ - SNAME##_node *scan1 = _list1_->head; \ - SNAME##_node *scan2 = _list2_->head; \ - \ - while (scan1 != NULL && scan2 != NULL) \ - { \ - if (comparator(scan1->data, scan2->data) != 0) \ - return false; \ - \ - scan1 = scan1->next; \ - scan2 = scan2->next; \ - } \ - \ - return true; \ - } \ - \ - cmc_string PFX##_to_string(SNAME *_list_) \ - { \ - cmc_string str; \ - SNAME *l_ = _list_; \ - const char *name = #SNAME; \ - \ - snprintf(str.s, cmc_string_len, cmc_string_fmt_linkedlist, \ - name, l_, l_->count, l_->head, l_->tail); \ - \ - return str; \ - } \ - \ - SNAME##_node *PFX##_new_node(V element) \ - { \ - SNAME##_node *_node_ = malloc(sizeof(SNAME##_node)); \ - \ - if (!_node_) \ - return NULL; \ - \ - _node_->data = element; \ - _node_->next = NULL; \ - _node_->prev = NULL; \ - \ - return _node_; \ - } \ - \ - void PFX##_free_node(SNAME##_node *_node_) \ - { \ - free(_node_); \ - } \ - \ - SNAME##_node *PFX##_head(SNAME *_list_) \ - { \ - return _list_->head; \ - } \ - \ - SNAME##_node *PFX##_get_node(SNAME *_list_, size_t index) \ - { \ - if (index >= _list_->count) \ - return NULL; \ - \ - if (PFX##_empty(_list_)) \ - return NULL; \ - \ - SNAME##_node *_node_ = NULL; \ - \ - if (index <= _list_->count / 2) \ - { \ - _node_ = _list_->head; \ - for (size_t i = 0; i < index; i++) \ - { \ - _node_ = _node_->next; \ - } \ - } \ - else \ - { \ - _node_ = _list_->tail; \ - for (size_t i = _list_->count - 1; i > index; i--) \ - { \ - _node_ = _node_->prev; \ - } \ - } \ - \ - return _node_; \ - } \ - \ - SNAME##_node *PFX##_tail(SNAME *_list_) \ - { \ - return _list_->tail; \ - } \ - \ - bool PFX##_insert_after(SNAME *_owner_, SNAME##_node *_node_, V element) \ - { \ - SNAME##_node *new_node = PFX##_new_node(element); \ - \ - if (!new_node) \ - return false; \ - \ - new_node->next = _node_->next; \ - \ - if (_node_->next != NULL) \ - _node_->next->prev = new_node; \ - else \ - _owner_->tail = new_node; \ - \ - new_node->prev = _node_; \ - _node_->next = new_node; \ - \ - _owner_->count++; \ - \ - return true; \ - } \ - \ - bool PFX##_insert_before(SNAME *_owner_, SNAME##_node *_node_, V element) \ - { \ - SNAME##_node *new_node = PFX##_new_node(element); \ - \ - if (!new_node) \ - return false; \ - \ - new_node->prev = _node_->prev; \ - \ - if (_node_->prev != NULL) \ - _node_->prev->next = new_node; \ - else \ - _owner_->head = new_node; \ - \ - new_node->next = _node_; \ - _node_->prev = new_node; \ - \ - _owner_->count++; \ - \ - return true; \ - } \ - \ - bool PFX##_remove_after(SNAME *_owner_, SNAME##_node *_node_) \ - { \ - if (_node_->next == NULL) \ - return false; \ - \ - SNAME##_node *tmp = _node_->next; \ - \ - if (tmp->next != NULL) \ - { \ - _node_->next = _node_->next->next; \ - _node_->next->prev = _node_; \ - } \ - else \ - _owner_->tail = _node_; \ - \ - free(tmp); \ - \ - _owner_->count--; \ - \ - return true; \ - } \ - \ - bool PFX##_remove_current(SNAME *_owner_, SNAME##_node *_node_) \ - { \ - if (_node_->prev != NULL) \ - _node_->prev->next = _node_->next; \ - else \ - _owner_->head = _node_->next; \ - \ - if (_node_->next != NULL) \ - _node_->next->prev = _node_->prev; \ - else \ - _owner_->tail = _node_->prev; \ - \ - free(_node_); \ - \ - _owner_->count--; \ - \ - return true; \ - } \ - \ - bool PFX##_remove_before(SNAME *_owner_, SNAME##_node *_node_) \ - { \ - if (_node_->prev == NULL) \ - return false; \ - \ - SNAME##_node *tmp = _node_->prev; \ - \ - if (tmp->prev != NULL) \ - { \ - _node_->prev = _node_->prev->prev; \ - _node_->prev->next = _node_; \ - } \ - else \ - _owner_->head = _node_; \ - \ - free(tmp); \ - \ - _owner_->count--; \ - \ - return true; \ - } \ - \ - SNAME##_node *PFX##_next_node(SNAME##_node *_node_) \ - { \ - return _node_->next; \ - } \ - \ - SNAME##_node *PFX##_prev_node(SNAME##_node *_node_) \ - { \ - return _node_->prev; \ - } \ - \ - SNAME##_iter *PFX##_iter_new(SNAME *target) \ - { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ - { \ - iter->target = target; \ - iter->cursor = target->head; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - } \ - \ - bool PFX##_iter_start(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->target->head; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - } \ - } \ - \ - void PFX##_iter_to_end(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->target->tail; \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - } \ - } \ - \ - bool PFX##_iter_next(SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->cursor->next == NULL) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - iter->cursor = iter->cursor->next; \ - iter->index++; \ - \ - return true; \ - } \ - \ - bool PFX##_iter_prev(SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->cursor->prev == NULL) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - iter->cursor = iter->cursor->prev; \ - iter->index--; \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->cursor->next == NULL) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ - return false; \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - iter->index += steps; \ - \ - for (size_t i = 0; i < steps; i++) \ - iter->cursor = iter->cursor->next; \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->cursor->prev == NULL) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index < steps) \ - return false; \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - iter->index -= steps; \ - \ - for (size_t i = 0; i < steps; i++) \ - iter->cursor = iter->cursor->prev; \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator was able to be positioned at the given */ \ - /* index */ \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ - { \ - if (index >= PFX##_count(iter->target)) \ - return false; \ - \ - if (iter->index > index) \ - return PFX##_iter_rewind(iter, iter->index - index); \ - else if (iter->index < index) \ - return PFX##_iter_advance(iter, index - iter->index); \ - \ - return true; \ - } \ - \ - V PFX##_iter_value(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){0}; \ - \ - return iter->cursor->data; \ - } \ - \ - V *PFX##_iter_rvalue(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->cursor->data); \ - } \ - \ - size_t PFX##_iter_index(SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - SNAME##_node *PFX##_iter_node(SNAME##_iter *iter) \ - { \ - return iter->cursor; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_list_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _list_); \ - PFX##_iter_to_start(&iter); \ - \ - return iter; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_list_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _list_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ +#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 SNAME *_list_ = 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; \ + \ + 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); \ + } \ + \ + 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); \ + \ + free(_list_); \ + } \ + \ + bool PFX##_push_front(struct SNAME *_list_, V element) \ + { \ + struct SNAME##_node *_node_ = PFX##_new_node(element); \ + \ + if (!_node_) \ + return false; \ + \ + if (PFX##_empty(_list_)) \ + { \ + _list_->head = _node_; \ + _list_->tail = _node_; \ + } \ + else \ + { \ + _node_->next = _list_->head; \ + _list_->head->prev = _node_; \ + _list_->head = _node_; \ + } \ + \ + _list_->count++; \ + \ + return true; \ + } \ + \ + bool PFX##_push_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(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(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; \ + \ + 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; \ + \ + 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; \ + \ + 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(); \ + \ + 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(copy_func(scan->data)); \ + else \ + new_node = PFX##_new_node(scan->data); \ + \ + if (!result->head) \ + { \ + result->head = new_node; \ + result->tail = new_node; \ + } \ + else \ + { \ + new_node->prev = result->tail; \ + result->tail->next = new_node; \ + result->tail = new_node; \ + } \ + \ + scan = scan->next; \ + } \ + \ + result->count = _list_->count; \ + \ + return result; \ + } \ + \ + bool PFX##_equals(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_; \ + const char *name = #SNAME; \ + \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_linkedlist, \ + name, l_, l_->count, l_->head, l_->tail); \ + \ + return str; \ + } \ + \ + struct SNAME##_node *PFX##_new_node(V element) \ + { \ + struct SNAME##_node *_node_ = 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##_node *_node_) \ + { \ + 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(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(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_; \ + \ + 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; \ + \ + 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_; \ + \ + 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 = 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) \ + { \ + 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 50e5fd7..5e52ebd 100644 --- a/src/cmc/list.h +++ b/src/cmc/list.h @@ -67,7 +67,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu #define CMC_GENERATE_LIST_HEADER(PFX, SNAME, V) \ \ /* List Structure */ \ - typedef struct SNAME##_s \ + struct SNAME \ { \ /* Dynamic array of elements */ \ V *buffer; \ @@ -79,18 +79,17 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu size_t count; \ \ /* Function that returns an iterator to the start of the list */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + struct SNAME##_iter (*it_start)(struct SNAME *); \ \ /* Function that returns an iterator to the end of the list */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ + struct SNAME##_iter (*it_end)(struct SNAME *); \ + }; \ \ /* List Iterator */ \ - typedef struct SNAME##_iter_s \ + struct SNAME##_iter \ { \ /* Target list */ \ - struct SNAME##_s *target; \ + struct SNAME *target; \ \ /* Cursor's position (index) */ \ size_t cursor; \ @@ -100,82 +99,82 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu \ /* If the iterator has reached the end of the iteration */ \ bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ + }; \ \ /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ - SNAME *PFX##_new(size_t capacity); \ - SNAME *PFX##_new_from(V *elements, size_t size); \ - void PFX##_clear(SNAME *_list_, void (*deallocator)(V)); \ - void PFX##_free(SNAME *_list_, void (*deallocator)(V)); \ + struct SNAME *PFX##_new(size_t capacity); \ + 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)); \ /* Collection Input and Output */ \ - bool PFX##_push_front(SNAME *_list_, V element); \ - bool PFX##_push_at(SNAME *_list_, V element, size_t index); \ - bool PFX##_push_back(SNAME *_list_, V element); \ - bool PFX##_pop_front(SNAME *_list_); \ - bool PFX##_pop_at(SNAME *_list_, size_t index); \ - bool PFX##_pop_back(SNAME *_list_); \ + 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(SNAME *_list_, V *elements, size_t size); \ - bool PFX##_seq_push_at(SNAME *_list_, V *elements, size_t size, size_t index); \ - bool PFX##_seq_push_back(SNAME *_list_, V *elements, size_t size); \ - bool PFX##_seq_pop_at(SNAME *_list_, size_t from, size_t to); \ - SNAME *PFX##_seq_sublist(SNAME *_list_, size_t from, size_t to); \ + 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(SNAME *_list_); \ - V PFX##_get(SNAME *_list_, size_t index); \ - V *PFX##_get_ref(SNAME *_list_, size_t index); \ - V PFX##_back(SNAME *_list_); \ - size_t PFX##_indexof(SNAME *_list_, V element, int (*comparator)(V, V), bool from_start); \ + 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(SNAME *_list_, V element, int (*comparator)(V, V)); \ - bool PFX##_empty(SNAME *_list_); \ - bool PFX##_full(SNAME *_list_); \ - size_t PFX##_count(SNAME *_list_); \ - bool PFX##_fits(SNAME *_list_, size_t size); \ - size_t PFX##_capacity(SNAME *_list_); \ + 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(SNAME *_list_, size_t capacity); \ - SNAME *PFX##_copy_of(SNAME *_list_, V (*copy_func)(V)); \ - bool PFX##_equals(SNAME *_list1_, SNAME *_list2_, int (*comparator)(V, V)); \ - cmc_string PFX##_to_string(SNAME *_list_); \ + 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 */ \ - SNAME##_iter *PFX##_iter_new(SNAME *target); \ - void PFX##_iter_free(SNAME##_iter *iter); \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ + void PFX##_iter_free(struct SNAME##_iter *iter); \ /* Iterator Initialization */ \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ /* Iterator State */ \ - bool PFX##_iter_start(SNAME##_iter *iter); \ - bool PFX##_iter_end(SNAME##_iter *iter); \ + bool PFX##_iter_start(struct SNAME##_iter *iter); \ + bool PFX##_iter_end(struct SNAME##_iter *iter); \ /* Iterator Movement */ \ - void PFX##_iter_to_start(SNAME##_iter *iter); \ - void PFX##_iter_to_end(SNAME##_iter *iter); \ - bool PFX##_iter_next(SNAME##_iter *iter); \ - bool PFX##_iter_prev(SNAME##_iter *iter); \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ + 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(SNAME##_iter *iter); \ - V *PFX##_iter_rvalue(SNAME##_iter *iter); \ - size_t PFX##_iter_index(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_LIST_SOURCE(PFX, SNAME, V) \ \ /* Implementation Detail Functions */ \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_list_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_list_); \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_list_); \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_list_); \ \ - SNAME *PFX##_new(size_t capacity) \ + struct SNAME *PFX##_new(size_t capacity) \ { \ if (capacity < 1) \ return NULL; \ \ - SNAME *_list_ = malloc(sizeof(SNAME)); \ + struct SNAME *_list_ = malloc(sizeof(struct SNAME)); \ \ if (!_list_) \ return NULL; \ @@ -197,12 +196,12 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return _list_; \ } \ \ - SNAME *PFX##_new_from(V *elements, size_t size) \ + struct SNAME *PFX##_new_from(V *elements, size_t size) \ { \ if (size == 0) \ return NULL; \ \ - SNAME *_list_ = PFX##_new(size + size / 2); \ + struct SNAME *_list_ = PFX##_new(size + size / 2); \ \ if (!_list_) \ return NULL; \ @@ -214,7 +213,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return _list_; \ } \ \ - void PFX##_clear(SNAME *_list_, void (*deallocator)(V)) \ + void PFX##_clear(struct SNAME *_list_, void (*deallocator)(V)) \ { \ if (deallocator) \ { \ @@ -227,7 +226,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu _list_->count = 0; \ } \ \ - void PFX##_free(SNAME *_list_, void (*deallocator)(V)) \ + void PFX##_free(struct SNAME *_list_, void (*deallocator)(V)) \ { \ if (deallocator) \ { \ @@ -239,7 +238,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu free(_list_); \ } \ \ - bool PFX##_push_front(SNAME *_list_, V element) \ + bool PFX##_push_front(struct SNAME *_list_, V element) \ { \ if (PFX##_full(_list_)) \ { \ @@ -259,7 +258,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return true; \ } \ \ - bool PFX##_push_at(SNAME *_list_, V element, size_t index) \ + bool PFX##_push_at(struct SNAME *_list_, V element, size_t index) \ { \ if (index > _list_->count) \ return false; \ @@ -279,7 +278,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return true; \ } \ \ - bool PFX##_push_back(SNAME *_list_, V element) \ + bool PFX##_push_back(struct SNAME *_list_, V element) \ { \ if (PFX##_full(_list_)) \ { \ @@ -292,7 +291,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return true; \ } \ \ - bool PFX##_pop_front(SNAME *_list_) \ + bool PFX##_pop_front(struct SNAME *_list_) \ { \ if (PFX##_empty(_list_)) \ return false; \ @@ -304,7 +303,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return true; \ } \ \ - bool PFX##_pop_at(SNAME *_list_, size_t index) \ + bool PFX##_pop_at(struct SNAME *_list_, size_t index) \ { \ if (index >= _list_->count) \ return false; \ @@ -317,7 +316,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return true; \ } \ \ - bool PFX##_pop_back(SNAME *_list_) \ + bool PFX##_pop_back(struct SNAME *_list_) \ { \ if (PFX##_empty(_list_)) \ return false; \ @@ -327,7 +326,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return true; \ } \ \ - bool PFX##_seq_push_front(SNAME *_list_, V *elements, size_t size) \ + bool PFX##_seq_push_front(struct SNAME *_list_, V *elements, size_t size) \ { \ if (size == 0) \ return false; \ @@ -347,7 +346,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return true; \ } \ \ - bool PFX##_seq_push_at(SNAME *_list_, V *elements, size_t size, size_t index) \ + bool PFX##_seq_push_at(struct SNAME *_list_, V *elements, size_t size, size_t index) \ { \ if (size == 0 || index > _list_->count) \ return false; \ @@ -375,7 +374,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return true; \ } \ \ - bool PFX##_seq_push_back(SNAME *_list_, V *elements, size_t size) \ + bool PFX##_seq_push_back(struct SNAME *_list_, V *elements, size_t size) \ { \ if (size == 0) \ return false; \ @@ -393,7 +392,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return true; \ } \ \ - bool PFX##_seq_pop_at(SNAME *_list_, size_t from, size_t to) \ + bool PFX##_seq_pop_at(struct SNAME *_list_, size_t from, size_t to) \ { \ if (from > to || to >= _list_->count) \ return false; \ @@ -410,14 +409,14 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return true; \ } \ \ - SNAME *PFX##_seq_sublist(SNAME *_list_, size_t from, size_t to) \ + 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; \ \ - SNAME *result = PFX##_new(length); \ + struct SNAME *result = PFX##_new(length); \ \ if (!result) \ return NULL; \ @@ -435,7 +434,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return result; \ } \ \ - V PFX##_front(SNAME *_list_) \ + V PFX##_front(struct SNAME *_list_) \ { \ if (PFX##_empty(_list_)) \ return (V){0}; \ @@ -443,7 +442,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return _list_->buffer[0]; \ } \ \ - V PFX##_get(SNAME *_list_, size_t index) \ + V PFX##_get(struct SNAME *_list_, size_t index) \ { \ if (index >= _list_->count || PFX##_empty(_list_)) \ return (V){0}; \ @@ -451,7 +450,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return _list_->buffer[index]; \ } \ \ - V *PFX##_get_ref(SNAME *_list_, size_t index) \ + V *PFX##_get_ref(struct SNAME *_list_, size_t index) \ { \ if (index >= _list_->count) \ return NULL; \ @@ -462,7 +461,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return &(_list_->buffer[index]); \ } \ \ - V PFX##_back(SNAME *_list_) \ + V PFX##_back(struct SNAME *_list_) \ { \ if (PFX##_empty(_list_)) \ return (V){0}; \ @@ -470,7 +469,8 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return _list_->buffer[_list_->count - 1]; \ } \ \ - size_t PFX##_indexof(SNAME *_list_, V element, int (*comparator)(V, V), bool from_start) \ + size_t PFX##_indexof(struct SNAME *_list_, V element, int (*comparator)(V, V), \ + bool from_start) \ { \ if (from_start) \ { \ @@ -492,7 +492,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return _list_->count; \ } \ \ - bool PFX##_contains(SNAME *_list_, V element, int (*comparator)(V, V)) \ + bool PFX##_contains(struct SNAME *_list_, V element, int (*comparator)(V, V)) \ { \ for (size_t i = 0; i < _list_->count; i++) \ { \ @@ -503,32 +503,32 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return false; \ } \ \ - bool PFX##_empty(SNAME *_list_) \ + bool PFX##_empty(struct SNAME *_list_) \ { \ return _list_->count == 0; \ } \ \ - bool PFX##_full(SNAME *_list_) \ + bool PFX##_full(struct SNAME *_list_) \ { \ return _list_->count >= _list_->capacity; \ } \ \ - size_t PFX##_count(SNAME *_list_) \ + size_t PFX##_count(struct SNAME *_list_) \ { \ return _list_->count; \ } \ \ - bool PFX##_fits(SNAME *_list_, size_t size) \ + bool PFX##_fits(struct SNAME *_list_, size_t size) \ { \ return _list_->count + size <= _list_->capacity; \ } \ \ - size_t PFX##_capacity(SNAME *_list_) \ + size_t PFX##_capacity(struct SNAME *_list_) \ { \ return _list_->capacity; \ } \ \ - bool PFX##_resize(SNAME *_list_, size_t capacity) \ + bool PFX##_resize(struct SNAME *_list_, size_t capacity) \ { \ if (PFX##_capacity(_list_) == capacity) \ return true; \ @@ -547,9 +547,9 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return true; \ } \ \ - SNAME *PFX##_copy_of(SNAME *_list_, V (*copy_func)(V)) \ + struct SNAME *PFX##_copy_of(struct SNAME *_list_, V (*copy_func)(V)) \ { \ - SNAME *result = PFX##_new(_list_->capacity); \ + struct SNAME *result = PFX##_new(_list_->capacity); \ \ if (!result) \ return NULL; \ @@ -567,7 +567,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return result; \ } \ \ - bool PFX##_equals(SNAME *_list1_, SNAME *_list2_, int (*comparator)(V, V)) \ + bool PFX##_equals(struct SNAME *_list1_, struct SNAME *_list2_, int (*comparator)(V, V)) \ { \ if (PFX##_count(_list1_) != PFX##_count(_list2_)) \ return false; \ @@ -581,10 +581,10 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return false; \ } \ \ - cmc_string PFX##_to_string(SNAME *_list_) \ + struct cmc_string PFX##_to_string(struct SNAME *_list_) \ { \ - cmc_string str; \ - SNAME *l_ = _list_; \ + struct cmc_string str; \ + struct SNAME *l_ = _list_; \ const char *name = #SNAME; \ \ snprintf(str.s, cmc_string_len, cmc_string_fmt_list, \ @@ -593,9 +593,9 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return str; \ } \ \ - SNAME##_iter *PFX##_iter_new(SNAME *target) \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ + struct SNAME##_iter *iter = malloc(sizeof(struct SNAME##_iter)); \ \ if (!iter) \ return NULL; \ @@ -605,12 +605,12 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return iter; \ } \ \ - void PFX##_iter_free(SNAME##_iter *iter) \ + void PFX##_iter_free(struct SNAME##_iter *iter) \ { \ free(iter); \ } \ \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ { \ iter->target = target; \ iter->cursor = 0; \ @@ -618,17 +618,17 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu iter->end = PFX##_empty(target); \ } \ \ - bool PFX##_iter_start(SNAME##_iter *iter) \ + bool PFX##_iter_start(struct SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->start; \ } \ \ - bool PFX##_iter_end(SNAME##_iter *iter) \ + bool PFX##_iter_end(struct SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->end; \ } \ \ - void PFX##_iter_to_start(SNAME##_iter *iter) \ + void PFX##_iter_to_start(struct SNAME##_iter *iter) \ { \ if (!PFX##_empty(iter->target)) \ { \ @@ -638,7 +638,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu } \ } \ \ - void PFX##_iter_to_end(SNAME##_iter *iter) \ + void PFX##_iter_to_end(struct SNAME##_iter *iter) \ { \ if (!PFX##_empty(iter->target)) \ { \ @@ -648,7 +648,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu } \ } \ \ - bool PFX##_iter_next(SNAME##_iter *iter) \ + bool PFX##_iter_next(struct SNAME##_iter *iter) \ { \ if (iter->end) \ return false; \ @@ -666,7 +666,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return true; \ } \ \ - bool PFX##_iter_prev(SNAME##_iter *iter) \ + bool PFX##_iter_prev(struct SNAME##_iter *iter) \ { \ if (iter->start) \ return false; \ @@ -685,7 +685,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu } \ \ /* Returns true only if the iterator moved */ \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps) \ { \ if (iter->end) \ return false; \ @@ -707,7 +707,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu } \ \ /* Returns true only if the iterator moved */ \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps) \ { \ if (iter->start) \ return false; \ @@ -729,7 +729,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu } \ \ /* Returns true only if the iterator was able to be positioned at the given index */ \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index) \ { \ if (index >= PFX##_count(iter->target)) \ return false; \ @@ -742,7 +742,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return true; \ } \ \ - V PFX##_iter_value(SNAME##_iter *iter) \ + V PFX##_iter_value(struct SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ return (V){0}; \ @@ -750,7 +750,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return iter->target->buffer[iter->cursor]; \ } \ \ - V *PFX##_iter_rvalue(SNAME##_iter *iter) \ + V *PFX##_iter_rvalue(struct SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ return NULL; \ @@ -758,14 +758,14 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return &(iter->target->buffer[iter->cursor]); \ } \ \ - size_t PFX##_iter_index(SNAME##_iter *iter) \ + size_t PFX##_iter_index(struct SNAME##_iter *iter) \ { \ return iter->cursor; \ } \ \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_list_) \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_list_) \ { \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ \ PFX##_iter_init(&iter, _list_); \ PFX##_iter_to_start(&iter); \ @@ -773,9 +773,9 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return iter; \ } \ \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_list_) \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_list_) \ { \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ \ PFX##_iter_init(&iter, _list_); \ PFX##_iter_to_end(&iter); \ diff --git a/src/cmc/multimap.h b/src/cmc/multimap.h index 5d09ada..e31d23b 100644 --- a/src/cmc/multimap.h +++ b/src/cmc/multimap.h @@ -101,1023 +101,1020 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, CMC_GENERATE_MULTIMAP_SOURCE(PFX, SNAME, K, V) /* HEADER ********************************************************************/ -#define CMC_GENERATE_MULTIMAP_HEADER(PFX, SNAME, K, V) \ - \ - /* Multimap Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Array of linked list to entries */ \ - struct SNAME##_entry_s *(*buffer)[2]; \ - \ - /* Current array capacity */ \ - size_t capacity; \ - \ - /* Current amount of keys */ \ - size_t count; \ - \ - /* Load factor in range (0.0, infinity) */ \ - double load; \ - \ - /* Key comparison functions */ \ - int (*cmp)(K, K); \ - \ - /* Key hash function */ \ - size_t (*hash)(K); \ - \ - /* Function that returns an iterator to the start of the multimap */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the multimap */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Multimap Entry */ \ - typedef struct SNAME##_entry_s \ - { \ - /* Entry Key */ \ - K key; \ - \ - /* Entry Value */ \ - V value; \ - \ - /* Next entry on the linked list */ \ - struct SNAME##_entry_s *next; \ - \ - /* Previous entry on the linked list */ \ - struct SNAME##_entry_s *prev; \ - \ - } SNAME##_entry, *SNAME##_entry_ptr; \ - \ - typedef struct SNAME##_iter_s \ - { \ - /* Target multimap */ \ - struct SNAME##_s *target; \ - \ - /* Current entry */ \ - struct SNAME##_entry_s *curr_entry; \ - \ - /* Cursor`s position (index) */ \ - size_t cursor; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* The index of the first element */ \ - size_t first; \ - \ - /* The index of the last element */ \ - size_t last; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - SNAME *PFX##_new(size_t capacity, double load, int (*compare)(K, K), size_t (*hash)(K)); \ - void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)); \ - void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)); \ - /* Collection Input and Output */ \ - bool PFX##_insert(SNAME *_map_, K key, V value); \ - bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value); \ - size_t PFX##_update_all(SNAME *_map_, K key, V new_value, V **old_values); \ - bool PFX##_remove(SNAME *_map_, K key, V *out_value); \ - size_t PFX##_remove_all(SNAME *_map_, K key, V **out_values); \ - /* Element Access */ \ - bool PFX##_max(SNAME *_map_, K *key, V *value); \ - bool PFX##_min(SNAME *_map_, K *key, V *value); \ - V PFX##_get(SNAME *_map_, K key); \ - V *PFX##_get_ref(SNAME *_map_, K key); \ - /* Collection State */ \ - bool PFX##_contains(SNAME *_map_, K key); \ - bool PFX##_empty(SNAME *_map_); \ - bool PFX##_full(SNAME *_map_); \ - size_t PFX##_count(SNAME *_map_); \ - size_t PFX##_key_count(SNAME *_map_, K key); \ - size_t PFX##_capacity(SNAME *_map_); \ - double PFX##_load(SNAME *_map_); \ - /* Collection Utility */ \ - bool PFX##_resize(SNAME *_map_, size_t capacity); \ - SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)); \ - bool PFX##_equals(SNAME *_map1_, SNAME *_map2_, bool ignore_key_count); \ - cmc_string PFX##_to_string(SNAME *_map_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - SNAME##_iter *PFX##_iter_new(SNAME *target); \ - void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(SNAME##_iter *iter); \ - bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(SNAME##_iter *iter); \ - void PFX##_iter_to_end(SNAME##_iter *iter); \ - bool PFX##_iter_next(SNAME##_iter *iter); \ - bool PFX##_iter_prev(SNAME##_iter *iter); \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - K PFX##_iter_key(SNAME##_iter *iter); \ - V PFX##_iter_value(SNAME##_iter *iter); \ - V *PFX##_iter_rvalue(SNAME##_iter *iter); \ - size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ +#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 *); \ + }; \ + \ + /* 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)); \ + void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)); \ + void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)); \ + /* 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 */ \ - SNAME##_entry *PFX##_impl_new_entry(K key, V value); \ - SNAME##_entry *PFX##_impl_get_entry(SNAME *_map_, K key); \ - size_t PFX##_impl_calculate_size(size_t required); \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_map_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_map_); \ - \ - SNAME *PFX##_new(size_t capacity, double load, int (*compare)(K, K), size_t (*hash)(K)) \ - { \ - if (capacity == 0 || load <= 0) \ - return NULL; \ - \ - /* Prevent integer overflow */ \ - if (capacity >= UINTMAX_MAX * load) \ - return NULL; \ - \ - size_t real_capacity = PFX##_impl_calculate_size(capacity / load); \ - \ - SNAME *_map_ = malloc(sizeof(SNAME)); \ - \ - if (!_map_) \ - return NULL; \ - \ - _map_->buffer = calloc(real_capacity, sizeof(SNAME##_entry_ptr[2])); \ - \ - if (!_map_->buffer) \ - { \ - 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; \ - \ - return _map_; \ - } \ - \ - void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - size_t index = 0; \ - SNAME##_entry *scan; \ - \ - while (index < _map_->capacity) \ - { \ - scan = _map_->buffer[index][0]; \ - \ - if (scan != NULL) \ - { \ - if (scan->next == NULL && scan->prev == NULL) \ - { \ - if (deallocator) \ - deallocator(scan->key, scan->value); \ - \ - free(scan); \ - } \ - else \ - { \ - while (scan != NULL) \ - { \ - SNAME##_entry *tmp = scan; \ - \ - scan = scan->next; \ - \ - if (deallocator) \ - deallocator(tmp->key, tmp->value); \ - \ - free(tmp); \ - } \ - } \ - } \ - \ - index++; \ - } \ - \ - memset(_map_->buffer, 0, sizeof(SNAME##_entry_ptr[2]) * _map_->capacity); \ - \ - _map_->count = 0; \ - } \ - \ - void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - size_t index = 0; \ - SNAME##_entry *scan; \ - \ - while (index < _map_->capacity) \ - { \ - scan = _map_->buffer[index][0]; \ - \ - if (scan != NULL) \ - { \ - if (scan->next == NULL && scan->prev == NULL) \ - free(scan); \ - else \ - { \ - while (scan != NULL) \ - { \ - SNAME##_entry *tmp = scan; \ - \ - scan = scan->next; \ - \ - if (deallocator) \ - deallocator(tmp->key, tmp->value); \ - \ - free(tmp); \ - } \ - } \ - } \ - \ - index++; \ - } \ - \ - free(_map_->buffer); \ - free(_map_); \ - } \ - \ - bool PFX##_insert(SNAME *_map_, K key, V value) \ - { \ - if (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; \ - \ - SNAME##_entry *entry = PFX##_impl_new_entry(key, value); \ - \ - if (_map_->buffer[pos][0] == NULL) \ - { \ - _map_->buffer[pos][0] = entry; \ - _map_->buffer[pos][1] = entry; \ - } \ - else \ - { \ - entry->prev = _map_->buffer[pos][1]; \ - \ - _map_->buffer[pos][1]->next = entry; \ - _map_->buffer[pos][1] = entry; \ - } \ - \ - _map_->count++; \ - \ - return true; \ - } \ - \ - bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value) \ - { \ - SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ - \ - if (!entry) \ - return false; \ - \ - if (old_value) \ - *old_value = entry->value; \ - \ - entry->value = new_value; \ - \ - return false; \ - } \ - \ - size_t PFX##_update_all(SNAME *_map_, K key, V new_value, V **old_values) \ - { \ - size_t total = PFX##_key_count(_map_, key); \ - size_t index = 0; \ - \ - if (total == 0) \ - return total; \ - \ - if (old_values) \ - { \ - *old_values = malloc(sizeof(V) * total); \ - \ - if (!(*old_values)) \ - return false; \ - } \ - \ - size_t hash = _map_->hash(key); \ - \ - SNAME##_entry *entry = _map_->buffer[hash % _map_->capacity][0]; \ - \ - while (entry != NULL) \ - { \ - if (_map_->cmp(entry->key, key) == 0) \ - { \ - if (old_values) \ - (*old_values)[index++] = entry->value; \ - \ - entry->value = new_value; \ - } \ - \ - entry = entry->next; \ - } \ - \ - return index; \ - } \ - \ - bool PFX##_remove(SNAME *_map_, K key, V *out_value) \ - { \ - size_t hash = _map_->hash(key); \ - \ - SNAME##_entry **head = &(_map_->buffer[hash % _map_->capacity][0]); \ - SNAME##_entry **tail = &(_map_->buffer[hash % _map_->capacity][1]); \ - \ - if (*head == NULL) \ - return false; \ - \ - SNAME##_entry *entry = *head; \ - \ - if (entry->next == NULL && entry->prev == NULL) \ - { \ - if (_map_->cmp(entry->key, key) == 0) \ - { \ - *head = NULL; \ - *tail = NULL; \ - \ - if (out_value) \ - *out_value = entry->value; \ - } \ - else \ - return false; \ - } \ - else \ - { \ - bool found = false; \ - \ - while (entry != NULL) \ - { \ - if (_map_->cmp(entry->key, key) == 0) \ - { \ - if (*head == entry) \ - *head = entry->next; \ - if (*tail == entry) \ - *tail = entry->prev; \ - \ - if (entry->prev != NULL) \ - entry->prev->next = entry->next; \ - if (entry->next != NULL) \ - entry->next->prev = entry->prev; \ - \ - if (out_value) \ - *out_value = entry->value; \ - \ - found = true; \ - \ - break; \ - } \ - else \ - entry = entry->next; \ - } \ - \ - if (!found) \ - return false; \ - } \ - \ - free(entry); \ - \ - _map_->count--; \ - \ - return true; \ - } \ - \ - size_t PFX##_remove_all(SNAME *_map_, K key, V **out_values) \ - { \ - size_t hash = _map_->hash(key); \ - \ - SNAME##_entry **head = &(_map_->buffer[hash % _map_->capacity][0]); \ - SNAME##_entry **tail = &(_map_->buffer[hash % _map_->capacity][1]); \ - \ - if (*head == NULL) \ - return 0; \ - \ - size_t total = PFX##_key_count(_map_, key); \ - size_t index = 0; \ - \ - if (out_values) \ - *out_values = malloc(sizeof(SNAME##_entry) * total); \ - \ - SNAME##_entry *entry = *head; \ - \ - if (entry->next == NULL) \ - { \ - *head = NULL; \ - *tail = NULL; \ - \ - if (out_values) \ - (*out_values)[index++] = entry->value; \ - \ - free(entry); \ - } \ - else \ - { \ - while (entry != NULL) \ - { \ - if (_map_->cmp(entry->key, key) == 0) \ - { \ - if (*head == entry) \ - *head = entry->next; \ - if (*tail == entry) \ - *tail = entry->prev; \ - \ - SNAME##_entry *temp = entry->next; \ - \ - if (entry->prev != NULL) \ - entry->prev->next = entry->next; \ - if (entry->next != NULL) \ - entry->next->prev = entry->prev; \ - \ - if (out_values) \ - (*out_values)[index++] = entry->value; \ - \ - free(entry); \ - \ - entry = temp; \ - } \ - else \ - entry = entry->next; \ - } \ - } \ - \ - _map_->count -= index; \ - \ - return index; \ - } \ - \ - bool PFX##_max(SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - SNAME##_iter iter; \ - \ - for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - K result_key = PFX##_iter_key(&iter); \ - V result_value = PFX##_iter_value(&iter); \ - size_t index = PFX##_iter_index(&iter); \ - \ - if (index == 0) \ - { \ - *key = result_key; \ - *value = result_value; \ - } \ - else if (_map_->cmp(result_key, *key) > 0) \ - { \ - *key = result_key; \ - *value = result_value; \ - } \ - } \ - \ - return true; \ - } \ - \ - bool PFX##_min(SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - SNAME##_iter iter; \ - \ - for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - K result_key = PFX##_iter_key(&iter); \ - V result_value = PFX##_iter_value(&iter); \ - size_t index = PFX##_iter_index(&iter); \ - \ - if (index == 0) \ - { \ - *key = result_key; \ - *value = result_value; \ - } \ - else if (_map_->cmp(result_key, *key) < 0) \ - { \ - *key = result_key; \ - *value = result_value; \ - } \ - } \ - \ - return true; \ - } \ - \ - V PFX##_get(SNAME *_map_, K key) \ - { \ - SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ - \ - if (!entry) \ - return (V){0}; \ - \ - return entry->value; \ - } \ - \ - V *PFX##_get_ref(SNAME *_map_, K key) \ - { \ - SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \ - \ - if (!entry) \ - return NULL; \ - \ - return &(entry->value); \ - } \ - \ - bool PFX##_contains(SNAME *_map_, K key) \ - { \ - return PFX##_impl_get_entry(_map_, key) != NULL; \ - } \ - \ - bool PFX##_empty(SNAME *_map_) \ - { \ - return _map_->count == 0; \ - } \ - \ - bool PFX##_full(SNAME *_map_) \ - { \ - return (double)PFX##_capacity(_map_) * PFX##_load(_map_) <= (double)PFX##_count(_map_); \ - } \ - \ - size_t PFX##_count(SNAME *_map_) \ - { \ - return _map_->count; \ - } \ - \ - size_t PFX##_key_count(SNAME *_map_, K key) \ - { \ - size_t hash = _map_->hash(key); \ - \ - SNAME##_entry *entry = _map_->buffer[hash % _map_->capacity][0]; \ - \ - size_t total_count = 0; \ - \ - if (!entry) \ - return total_count; \ - \ - while (entry != NULL) \ - { \ - if (_map_->cmp(entry->key, key) == 0) \ - total_count++; \ - \ - entry = entry->next; \ - } \ - \ - return total_count; \ - } \ - \ - size_t PFX##_capacity(SNAME *_map_) \ - { \ - return _map_->capacity; \ - } \ - \ - double PFX##_load(SNAME *_map_) \ - { \ - return _map_->load; \ - } \ - \ - bool PFX##_resize(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; \ - \ - SNAME *_new_map_ = PFX##_new(capacity, PFX##_load(_map_), _map_->cmp, _map_->hash); \ - \ - if (!_new_map_) \ - return false; \ - \ - SNAME##_iter iter; \ - \ - for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - K key = PFX##_iter_key(&iter); \ - V value = PFX##_iter_value(&iter); \ - \ - PFX##_insert(_new_map_, key, value); \ - } \ - \ - if (PFX##_count(_map_) != PFX##_count(_new_map_)) \ - { \ - PFX##_free(_new_map_, NULL); \ - return false; \ - } \ - \ - SNAME##_entry *(*tmp_b)[2] = _map_->buffer; \ - _map_->buffer = _new_map_->buffer; \ - _new_map_->buffer = tmp_b; \ - \ - size_t tmp_c = _map_->capacity; \ - _map_->capacity = _new_map_->capacity; \ - _new_map_->capacity = tmp_c; \ - \ - PFX##_free(_new_map_, NULL); \ - \ - return true; \ - } \ - \ - SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)) \ - { \ - SNAME *result = PFX##_new(_map_->capacity, _map_->load, _map_->cmp, _map_->hash); \ - \ - if (!result) \ - return NULL; \ - \ - SNAME##_iter iter; \ - PFX##_iter_init(&iter, _map_); \ - \ - if (!PFX##_empty(_map_)) \ - { \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - K key = PFX##_iter_key(&iter); \ - V value = PFX##_iter_value(&iter); \ - \ - if (key_copy_func) \ - key = key_copy_func(key); \ - if (value_copy_func) \ - value = value_copy_func(value); \ - \ - PFX##_insert(result, key, value); \ - } \ - } \ - \ - return result; \ - } \ - \ - bool PFX##_equals(SNAME *_map1_, SNAME *_map2_, bool ignore_key_count) \ - { \ - if (ignore_key_count) \ - { \ - SNAME##_iter iter; \ - PFX##_iter_init(&iter, _map1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - if (PFX##_impl_get_entry(_map2_, PFX##_iter_key(&iter)) == NULL) \ - return false; \ - } \ - } \ - else \ - { \ - /* Since the key count matters this can be checked and an early exit */ \ - if (PFX##_count(_map1_) != PFX##_count(_map2_)) \ - return false; \ - \ - SNAME##_iter iter; \ - PFX##_iter_init(&iter, _map1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - K key = PFX##_iter_key(&iter); \ - \ - if (PFX##_key_count(_map1_, key) != PFX##_key_count(_map2_, key)) \ - return false; \ - } \ - } \ - \ - return true; \ - } \ - \ - cmc_string PFX##_to_string(SNAME *_map_) \ - { \ - cmc_string str; \ - SNAME *m_ = _map_; \ - const char *name = #SNAME; \ - \ - snprintf(str.s, cmc_string_len, cmc_string_fmt_multimap, \ - name, m_, m_->buffer, m_->capacity, m_->count, m_->load, m_->cmp, m_->hash); \ - \ - return str; \ - } \ - \ - SNAME##_iter *PFX##_iter_new(SNAME *target) \ - { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ - { \ - memset(iter, 0, sizeof(SNAME##_iter)); \ - \ - iter->target = target; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - \ - if (!PFX##_empty(target)) \ - { \ - for (size_t i = 0; i < target->capacity; i++) \ - { \ - if (target->buffer[i][0] != NULL) \ - { \ - iter->curr_entry = target->buffer[i][0]; \ - iter->first = i; \ - break; \ - } \ - } \ - \ - iter->cursor = iter->first; \ - \ - for (size_t i = target->capacity; i > 0; i--) \ - { \ - if (target->buffer[i - 1][0] != NULL) \ - { \ - iter->last = i - 1; \ - break; \ - } \ - } \ - } \ - } \ - \ - bool PFX##_iter_start(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->first; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - iter->curr_entry = iter->target->buffer[iter->first][0]; \ - } \ - } \ - \ - void PFX##_iter_to_end(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->last; \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - iter->curr_entry = iter->target->buffer[iter->last][1]; \ - } \ - } \ - \ - bool PFX##_iter_next(SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->curr_entry->next != NULL) \ - { \ - iter->curr_entry = iter->curr_entry->next; \ - iter->index++; \ - } \ - else \ - { \ - if (iter->cursor == iter->last) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - iter->cursor++; \ - \ - while (iter->target->buffer[iter->cursor][0] == NULL) \ - iter->cursor++; \ - \ - iter->curr_entry = iter->target->buffer[iter->cursor][0]; \ - \ - iter->index++; \ - } \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - return true; \ - } \ - \ - bool PFX##_iter_prev(SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->curr_entry->prev != NULL) \ - { \ - iter->curr_entry = iter->curr_entry->prev; \ - iter->index--; \ - } \ - else \ - { \ - if (iter->cursor == iter->first) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - iter->cursor--; \ - \ - while (iter->target->buffer[iter->cursor][1] == NULL) \ - iter->cursor--; \ - \ - iter->curr_entry = iter->target->buffer[iter->cursor][1]; \ - \ - iter->index--; \ - } \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->index + 1 == PFX##_count(iter->target)) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ - return false; \ - \ - for (size_t i = 0; i < steps; i++) \ - PFX##_iter_next(iter); \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->index == 0) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->index < steps) \ - return false; \ - \ - for (size_t i = 0; i < steps; i++) \ - PFX##_iter_prev(iter); \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator was able to be positioned at the given index */ \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ - { \ - if (index >= PFX##_count(iter->target)) \ - return false; \ - \ - if (iter->index > index) \ - return PFX##_iter_rewind(iter, iter->index - index); \ - else if (iter->index < index) \ - return PFX##_iter_advance(iter, index - iter->index); \ - \ - return true; \ - } \ - \ - K PFX##_iter_key(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (K){0}; \ - \ - return iter->curr_entry->key; \ - } \ - \ - V PFX##_iter_value(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){0}; \ - \ - return iter->curr_entry->value; \ - } \ - \ - V *PFX##_iter_rvalue(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->curr_entry->value); \ - } \ - \ - size_t PFX##_iter_index(SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - SNAME##_entry *PFX##_impl_new_entry(K key, V value) \ - { \ - SNAME##_entry *entry = malloc(sizeof(SNAME##_entry)); \ - \ - if (!entry) \ - return NULL; \ - \ - entry->key = key; \ - entry->value = value; \ - entry->next = NULL; \ - entry->prev = NULL; \ - \ - return entry; \ - } \ - \ - SNAME##_entry *PFX##_impl_get_entry(SNAME *_map_, K key) \ - { \ - size_t hash = _map_->hash(key); \ - \ - SNAME##_entry *entry = _map_->buffer[hash % _map_->capacity][0]; \ - \ - while (entry != NULL) \ - { \ - if (_map_->cmp(entry->key, key) == 0) \ - return entry; \ - \ - entry = entry->next; \ - } \ - \ - return NULL; \ - } \ - \ - size_t PFX##_impl_calculate_size(size_t required) \ - { \ - const size_t count = sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]); \ - \ - if (cmc_hashtable_primes[count - 1] < required) \ - return required; \ - \ - size_t i = 0; \ - while (cmc_hashtable_primes[i] < required) \ - i++; \ - \ - return cmc_hashtable_primes[i]; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_map_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _map_); \ - \ - return iter; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_map_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _map_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ +#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)) \ + { \ + 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_ = malloc(sizeof(struct SNAME)); \ + \ + if (!_map_) \ + return NULL; \ + \ + _map_->buffer = calloc(real_capacity, sizeof(struct SNAME##_entry * [2])); \ + \ + if (!_map_->buffer) \ + { \ + 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; \ + \ + 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_); \ + } \ + \ + 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_; \ + const char *name = #SNAME; \ + \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_multimap, \ + name, m_, m_->buffer, m_->capacity, m_->count, m_->load, m_->cmp, m_->hash); \ + \ + return str; \ + } \ + \ + 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 8db56eb..fc452ea 100644 --- a/src/cmc/multiset.h +++ b/src/cmc/multiset.h @@ -34,7 +34,7 @@ static const char *cmc_string_fmt_multiset = "%s at %p { buffer:%p, capacity:%" #ifndef CMC_IMPL_HASHTABLE_STATE #define CMC_IMPL_HASHTABLE_STATE -enum cmc_entry_state_e +enum cmc_entry_state { CMC_ES_DELETED = -1, CMC_ES_EMPTY = 0, @@ -94,10 +94,10 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, #define CMC_GENERATE_MULTISET_HEADER(PFX, SNAME, V) \ \ /* Hashset Structure */ \ - typedef struct SNAME##_s \ + struct SNAME \ { \ /* Array of Entries */ \ - struct SNAME##_entry_s *buffer; \ + struct SNAME##_entry *buffer; \ \ /* Current Array Capcity */ \ size_t capacity; \ @@ -118,14 +118,13 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, size_t (*hash)(V); \ \ /* Function that returns an iterator to the start of the hashset */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + struct SNAME##_iter (*it_start)(struct SNAME *); \ \ /* Function that returns an iterator to the end of the hashset */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + struct SNAME##_iter (*it_end)(struct SNAME *); \ + }; \ \ - } SNAME, *SNAME##_ptr; \ - \ - typedef struct SNAME##_entry_s \ + struct SNAME##_entry \ { \ /* Entry element */ \ V value; \ @@ -137,15 +136,14 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, size_t dist; \ \ /* The sate of this node (DELETED, EMPTY, FILLED) */ \ - enum cmc_entry_state_e state; \ - \ - } SNAME##_entry, *SNAME##_entry_ptr; \ + enum cmc_entry_state state; \ + }; \ \ /* Hashset Iterator */ \ - typedef struct SNAME##_iter_s \ + struct SNAME##_iter \ { \ /* Target Hashset */ \ - struct SNAME##_s *target; \ + struct SNAME *target; \ \ /* Cursor's position (index) */ \ size_t cursor; \ @@ -164,83 +162,84 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ /* If the iterator has reached the end of the iteration */ \ bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ + }; \ \ /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ - SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), size_t (*hash)(V)); \ - void PFX##_clear(SNAME *_set_, void (*deallocator)(V)); \ - void PFX##_free(SNAME *_set_, void (*deallocator)(V)); \ + struct SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), \ + size_t (*hash)(V)); \ + void PFX##_clear(struct SNAME *_set_, void (*deallocator)(V)); \ + void PFX##_free(struct SNAME *_set_, void (*deallocator)(V)); \ /* Collection Input and Output */ \ - bool PFX##_insert(SNAME *_set_, V element); \ - bool PFX##_insert_many(SNAME *_set_, V element, size_t count); \ - bool PFX##_update(SNAME *_set_, V element, size_t multiplicity); \ - bool PFX##_remove(SNAME *_set_, V element); \ - size_t PFX##_remove_all(SNAME *_set_, V element); \ + 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(SNAME *_set_, V *value); \ - bool PFX##_min(SNAME *_set_, V *value); \ - size_t PFX##_multiplicity_of(SNAME *_set_, V element); \ + 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(SNAME *_set_, V element); \ - bool PFX##_empty(SNAME *_set_); \ - bool PFX##_full(SNAME *_set_); \ - size_t PFX##_count(SNAME *_set_); \ - size_t PFX##_cardinality(SNAME *_set_); \ - size_t PFX##_capacity(SNAME *_set_); \ - double PFX##_load(SNAME *_set_); \ + 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(SNAME *_set_, size_t capacity); \ - SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)); \ - bool PFX##_equals(SNAME *_set1_, SNAME *_set2_, bool ignore_multiplicity); \ - cmc_string PFX##_to_string(SNAME *_set_); \ + 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 */ \ - SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_); \ - SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_); \ - SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_); \ - SNAME *PFX##_summation(SNAME *_set1_, SNAME *_set2_); \ - SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_); \ - bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_); \ - bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_); \ - bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_); \ - bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_); \ - bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_); \ + 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 */ \ - SNAME##_iter *PFX##_iter_new(SNAME *target); \ - void PFX##_iter_free(SNAME##_iter *iter); \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ + void PFX##_iter_free(struct SNAME##_iter *iter); \ /* Iterator Initialization */ \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ /* Iterator State */ \ - bool PFX##_iter_start(SNAME##_iter *iter); \ - bool PFX##_iter_end(SNAME##_iter *iter); \ + bool PFX##_iter_start(struct SNAME##_iter *iter); \ + bool PFX##_iter_end(struct SNAME##_iter *iter); \ /* Iterator Movement */ \ - void PFX##_iter_to_start(SNAME##_iter *iter); \ - void PFX##_iter_to_end(SNAME##_iter *iter); \ - bool PFX##_iter_next(SNAME##_iter *iter); \ - bool PFX##_iter_prev(SNAME##_iter *iter); \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ + 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(SNAME##_iter *iter); \ - size_t PFX##_iter_multiplicity(SNAME##_iter *iter); \ - size_t PFX##_iter_index(SNAME##_iter *iter); \ + 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 SNAME##_entry *PFX##_impl_insert_and_return(SNAME *_set_, V element, bool *new_node); \ - static SNAME##_entry *PFX##_impl_get_entry(SNAME *_set_, V element); \ + 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 SNAME##_iter PFX##_impl_it_start(SNAME *_set_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_set_); \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_set_); \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_set_); \ \ - SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), size_t (*hash)(V)) \ + struct SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), size_t (*hash)(V)) \ { \ if (capacity == 0 || load <= 0 || load >= 1) \ return NULL; \ @@ -251,12 +250,12 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ size_t real_capacity = PFX##_impl_calculate_size(capacity / load); \ \ - SNAME *_set_ = malloc(sizeof(SNAME)); \ + struct SNAME *_set_ = malloc(sizeof(struct SNAME)); \ \ if (!_set_) \ return NULL; \ \ - _set_->buffer = calloc(real_capacity, sizeof(SNAME##_entry)); \ + _set_->buffer = calloc(real_capacity, sizeof(struct SNAME##_entry)); \ \ if (!_set_->buffer) \ { \ @@ -277,13 +276,13 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return _set_; \ } \ \ - void PFX##_clear(SNAME *_set_, void (*deallocator)(V)) \ + void PFX##_clear(struct SNAME *_set_, void (*deallocator)(V)) \ { \ if (deallocator) \ { \ for (size_t i = 0; i < _set_->capacity; i++) \ { \ - SNAME##_entry *entry = &(_set_->buffer[i]); \ + struct SNAME##_entry *entry = &(_set_->buffer[i]); \ \ if (entry->state == CMC_ES_FILLED) \ { \ @@ -292,18 +291,18 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, } \ } \ \ - memset(_set_->buffer, 0, sizeof(SNAME##_entry) * _set_->capacity); \ + memset(_set_->buffer, 0, sizeof(struct SNAME##_entry) * _set_->capacity); \ \ _set_->count = 0; \ } \ \ - void PFX##_free(SNAME *_set_, void (*deallocator)(V)) \ + void PFX##_free(struct SNAME *_set_, void (*deallocator)(V)) \ { \ if (deallocator) \ { \ for (size_t i = 0; i < _set_->capacity; i++) \ { \ - SNAME##_entry *entry = &(_set_->buffer[i]); \ + struct SNAME##_entry *entry = &(_set_->buffer[i]); \ \ if (entry->state == CMC_ES_FILLED) \ { \ @@ -316,11 +315,11 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, free(_set_); \ } \ \ - bool PFX##_insert(SNAME *_set_, V element) \ + bool PFX##_insert(struct SNAME *_set_, V element) \ { \ bool new_node; \ \ - SNAME##_entry *entry = PFX##_impl_insert_and_return(_set_, element, &new_node); \ + struct SNAME##_entry *entry = PFX##_impl_insert_and_return(_set_, element, &new_node); \ \ if (!entry) \ return false; \ @@ -333,14 +332,14 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - bool PFX##_insert_many(SNAME *_set_, V element, size_t count) \ + bool PFX##_insert_many(struct SNAME *_set_, V element, size_t count) \ { \ if (count == 0) \ return true; \ \ bool new_node; \ \ - SNAME##_entry *entry = PFX##_impl_insert_and_return(_set_, element, &new_node); \ + struct SNAME##_entry *entry = PFX##_impl_insert_and_return(_set_, element, &new_node); \ \ if (!entry) \ return false; \ @@ -355,14 +354,14 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - bool PFX##_update(SNAME *_set_, V element, size_t multiplicity) \ + bool PFX##_update(struct SNAME *_set_, V element, size_t multiplicity) \ { \ if (multiplicity == 0) \ return PFX##_remove_all(_set_, element); \ \ bool new_node; \ \ - SNAME##_entry *entry = PFX##_impl_insert_and_return(_set_, element, &new_node); \ + struct SNAME##_entry *entry = PFX##_impl_insert_and_return(_set_, element, &new_node); \ \ if (!entry) \ return false; \ @@ -377,9 +376,9 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - bool PFX##_remove(SNAME *_set_, V element) \ + bool PFX##_remove(struct SNAME *_set_, V element) \ { \ - SNAME##_entry *result = PFX##_impl_get_entry(_set_, element); \ + struct SNAME##_entry *result = PFX##_impl_get_entry(_set_, element); \ \ if (result == NULL) \ return false; \ @@ -401,9 +400,9 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - size_t PFX##_remove_all(SNAME *_set_, V element) \ + size_t PFX##_remove_all(struct SNAME *_set_, V element) \ { \ - SNAME##_entry *result = PFX##_impl_get_entry(_set_, element); \ + struct SNAME##_entry *result = PFX##_impl_get_entry(_set_, element); \ \ if (result == NULL) \ return 0; \ @@ -421,12 +420,12 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return removed; \ } \ \ - bool PFX##_max(SNAME *_set_, V *value) \ + bool PFX##_max(struct SNAME *_set_, V *value) \ { \ if (PFX##_empty(_set_)) \ return false; \ \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ \ for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ { \ @@ -442,12 +441,12 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - bool PFX##_min(SNAME *_set_, V *value) \ + bool PFX##_min(struct SNAME *_set_, V *value) \ { \ if (PFX##_empty(_set_)) \ return false; \ \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ \ for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ { \ @@ -463,9 +462,9 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - size_t PFX##_multiplicity_of(SNAME *_set_, V element) \ + size_t PFX##_multiplicity_of(struct SNAME *_set_, V element) \ { \ - SNAME##_entry *entry = PFX##_impl_get_entry(_set_, element); \ + struct SNAME##_entry *entry = PFX##_impl_get_entry(_set_, element); \ \ if (!entry) \ return 0; \ @@ -473,42 +472,42 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return entry->multiplicity; \ } \ \ - bool PFX##_contains(SNAME *_set_, V element) \ + bool PFX##_contains(struct SNAME *_set_, V element) \ { \ return PFX##_impl_get_entry(_set_, element) != NULL; \ } \ \ - bool PFX##_empty(SNAME *_set_) \ + bool PFX##_empty(struct SNAME *_set_) \ { \ return _set_->count == 0; \ } \ \ - bool PFX##_full(SNAME *_set_) \ + bool PFX##_full(struct SNAME *_set_) \ { \ return (double)PFX##_capacity(_set_) * PFX##_load(_set_) <= (double)PFX##_count(_set_); \ } \ \ - size_t PFX##_count(SNAME *_set_) \ + size_t PFX##_count(struct SNAME *_set_) \ { \ return _set_->count; \ } \ \ - size_t PFX##_cardinality(SNAME *_set_) \ + size_t PFX##_cardinality(struct SNAME *_set_) \ { \ return _set_->cardinality; \ } \ \ - size_t PFX##_capacity(SNAME *_set_) \ + size_t PFX##_capacity(struct SNAME *_set_) \ { \ return _set_->capacity; \ } \ \ - double PFX##_load(SNAME *_set_) \ + double PFX##_load(struct SNAME *_set_) \ { \ return _set_->load; \ } \ \ - bool PFX##_resize(SNAME *_set_, size_t capacity) \ + bool PFX##_resize(struct SNAME *_set_, size_t capacity) \ { \ if (PFX##_capacity(_set_) == capacity) \ return true; \ @@ -527,12 +526,12 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, if (theoretical_size < PFX##_count(_set_) / PFX##_load(_set_)) \ return false; \ \ - SNAME *_new_set_ = PFX##_new(capacity, PFX##_load(_set_), _set_->cmp, _set_->hash); \ + struct SNAME *_new_set_ = PFX##_new(capacity, PFX##_load(_set_), _set_->cmp, _set_->hash); \ \ if (!_new_set_) \ return false; \ \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ \ for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ { \ @@ -545,7 +544,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return false; \ } \ \ - SNAME##_entry *tmp_b = _set_->buffer; \ + struct SNAME##_entry *tmp_b = _set_->buffer; \ _set_->buffer = _new_set_->buffer; \ _new_set_->buffer = tmp_b; \ \ @@ -558,9 +557,9 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)) \ + struct SNAME *PFX##_copy_of(struct SNAME *_set_, V (*copy_func)(V)) \ { \ - SNAME *result = PFX##_new(_set_->capacity, _set_->load, _set_->cmp, _set_->hash); \ + struct SNAME *result = PFX##_new(_set_->capacity, _set_->load, _set_->cmp, _set_->hash); \ \ if (!result) \ return NULL; \ @@ -569,11 +568,11 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, { \ for (size_t i = 0; i < _set_->capacity; i++) \ { \ - SNAME##_entry *scan = &(_set_->buffer[i]); \ + struct SNAME##_entry *scan = &(_set_->buffer[i]); \ \ if (scan->state != CMC_ES_EMPTY) \ { \ - SNAME##_entry *target = &(result->buffer[i]); \ + struct SNAME##_entry *target = &(result->buffer[i]); \ \ if (scan->state == CMC_ES_DELETED) \ target->state = CMC_ES_DELETED; \ @@ -589,7 +588,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, } \ } \ else \ - memcpy(result->buffer, _set_->buffer, sizeof(SNAME##_entry) * _set_->capacity); \ + memcpy(result->buffer, _set_->buffer, sizeof(struct SNAME##_entry) * _set_->capacity); \ \ result->count = _set_->count; \ result->cardinality = _set_->cardinality; \ @@ -597,7 +596,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return result; \ } \ \ - bool PFX##_equals(SNAME *_set1_, SNAME *_set2_, bool ignore_multiplicity) \ + bool PFX##_equals(struct SNAME *_set1_, struct SNAME *_set2_, bool ignore_multiplicity) \ { \ if (PFX##_count(_set1_) != PFX##_count(_set2_)) \ return false; \ @@ -608,12 +607,12 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, if (PFX##_count(_set1_) == 0) \ return true; \ \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ PFX##_iter_init(&iter, _set1_); \ \ for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ { \ - SNAME##_entry *entry = PFX##_impl_get_entry(_set2_, PFX##_iter_value(&iter)); \ + struct SNAME##_entry *entry = PFX##_impl_get_entry(_set2_, PFX##_iter_value(&iter)); \ \ if (entry == NULL) \ return false; \ @@ -625,10 +624,10 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - cmc_string PFX##_to_string(SNAME *_set_) \ + struct cmc_string PFX##_to_string(struct SNAME *_set_) \ { \ - cmc_string str; \ - SNAME *s_ = _set_; \ + struct cmc_string str; \ + struct SNAME *s_ = _set_; \ const char *name = #SNAME; \ \ snprintf(str.s, cmc_string_len, cmc_string_fmt_multiset, \ @@ -638,14 +637,15 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return str; \ } \ \ - SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_) \ + struct SNAME *PFX##_union(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ - SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ + struct SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, \ + _set1_->hash); \ \ if (!_set_r_) \ return NULL; \ \ - SNAME##_iter iter1, iter2; \ + struct SNAME##_iter iter1, iter2; \ PFX##_iter_init(&iter1, _set1_); \ PFX##_iter_init(&iter2, _set2_); \ \ @@ -674,17 +674,18 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return _set_r_; \ } \ \ - SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_) \ + struct SNAME *PFX##_intersection(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ - SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ + struct SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, \ + _set1_->hash); \ \ if (!_set_r_) \ return NULL; \ \ - SNAME *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; \ - SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \ + struct SNAME *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; \ + struct SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \ \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ PFX##_iter_init(&iter, _set_A_); \ \ for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ @@ -701,14 +702,15 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return _set_r_; \ } \ \ - SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_) \ + struct SNAME *PFX##_difference(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ - SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ + struct SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, \ + _set1_->hash); \ \ if (!_set_r_) \ return NULL; \ \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ PFX##_iter_init(&iter, _set1_); \ \ for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ @@ -725,14 +727,15 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return _set_r_; \ } \ \ - SNAME *PFX##_summation(SNAME *_set1_, SNAME *_set2_) \ + struct SNAME *PFX##_summation(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ - SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ + struct SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, \ + _set1_->hash); \ \ if (!_set_r_) \ return NULL; \ \ - SNAME##_iter iter1, iter2; \ + struct SNAME##_iter iter1, iter2; \ PFX##_iter_init(&iter1, _set1_); \ PFX##_iter_init(&iter2, _set2_); \ \ @@ -749,11 +752,12 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return _set_r_; \ } \ \ - SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_) \ + struct SNAME *PFX##_symmetric_difference(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ - SNAME##_iter iter1, iter2; \ + struct SNAME##_iter iter1, iter2; \ \ - SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \ + struct SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, \ + _set1_->hash); \ \ if (!_set_r_) \ return NULL; \ @@ -796,7 +800,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return _set_r_; \ } \ \ - bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_) \ + bool PFX##_is_subset(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ if (PFX##_count(_set1_) > PFX##_count(_set2_)) \ return false; \ @@ -804,7 +808,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, if (PFX##_empty(_set1_)) \ return true; \ \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ \ PFX##_iter_init(&iter, _set1_); \ \ @@ -822,12 +826,12 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_) \ + bool PFX##_is_superset(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ return PFX##_is_subset(_set2_, _set1_); \ } \ \ - bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_) \ + bool PFX##_is_proper_subset(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ if (PFX##_count(_set1_) >= PFX##_count(_set2_)) \ return false; \ @@ -840,7 +844,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return false; \ } \ \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ \ PFX##_iter_init(&iter, _set1_); \ \ @@ -858,17 +862,17 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_) \ + bool PFX##_is_proper_superset(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ return PFX##_is_proper_subset(_set2_, _set1_); \ } \ \ - bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_) \ + bool PFX##_is_disjointset(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ if (PFX##_empty(_set1_)) \ return true; \ \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ \ PFX##_iter_init(&iter, _set1_); \ \ @@ -883,9 +887,9 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - SNAME##_iter *PFX##_iter_new(SNAME *target) \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ + struct SNAME##_iter *iter = malloc(sizeof(struct SNAME##_iter)); \ \ if (!iter) \ return NULL; \ @@ -895,14 +899,14 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return iter; \ } \ \ - void PFX##_iter_free(SNAME##_iter *iter) \ + void PFX##_iter_free(struct SNAME##_iter *iter) \ { \ free(iter); \ } \ \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ { \ - memset(iter, 0, sizeof(SNAME##_iter)); \ + memset(iter, 0, sizeof(struct SNAME##_iter)); \ \ iter->target = target; \ iter->start = true; \ @@ -932,17 +936,17 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, } \ } \ \ - bool PFX##_iter_start(SNAME##_iter *iter) \ + bool PFX##_iter_start(struct SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->start; \ } \ \ - bool PFX##_iter_end(SNAME##_iter *iter) \ + bool PFX##_iter_end(struct SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->end; \ } \ \ - void PFX##_iter_to_start(SNAME##_iter *iter) \ + void PFX##_iter_to_start(struct SNAME##_iter *iter) \ { \ if (!PFX##_empty(iter->target)) \ { \ @@ -953,7 +957,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, } \ } \ \ - void PFX##_iter_to_end(SNAME##_iter *iter) \ + void PFX##_iter_to_end(struct SNAME##_iter *iter) \ { \ if (!PFX##_empty(iter->target)) \ { \ @@ -964,7 +968,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, } \ } \ \ - bool PFX##_iter_next(SNAME##_iter *iter) \ + bool PFX##_iter_next(struct SNAME##_iter *iter) \ { \ if (iter->end) \ return false; \ @@ -977,7 +981,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ iter->start = PFX##_empty(iter->target); \ \ - SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ + struct SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ \ iter->index++; \ \ @@ -993,7 +997,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - bool PFX##_iter_prev(SNAME##_iter *iter) \ + bool PFX##_iter_prev(struct SNAME##_iter *iter) \ { \ if (iter->start) \ return false; \ @@ -1006,7 +1010,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ iter->end = PFX##_empty(iter->target); \ \ - SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ + struct SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ \ iter->index--; \ \ @@ -1023,7 +1027,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, } \ \ /* Returns true only if the iterator moved */ \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps) \ { \ if (iter->end) \ return false; \ @@ -1044,7 +1048,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, } \ \ /* Returns true only if the iterator moved */ \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps) \ { \ if (iter->start) \ return false; \ @@ -1065,7 +1069,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, } \ \ /* Returns true only if the iterator was able to be positioned at the given index */ \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index) \ { \ if (index >= PFX##_count(iter->target)) \ return false; \ @@ -1078,7 +1082,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ - V PFX##_iter_value(SNAME##_iter *iter) \ + V PFX##_iter_value(struct SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ return (V){0}; \ @@ -1086,7 +1090,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return iter->target->buffer[iter->cursor].value; \ } \ \ - size_t PFX##_iter_multiplicity(SNAME##_iter *iter) \ + size_t PFX##_iter_multiplicity(struct SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ return 0; \ @@ -1094,19 +1098,20 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return iter->target->buffer[iter->cursor].multiplicity; \ } \ \ - size_t PFX##_iter_index(SNAME##_iter *iter) \ + size_t PFX##_iter_index(struct SNAME##_iter *iter) \ { \ return iter->index; \ } \ \ - static SNAME##_entry *PFX##_impl_insert_and_return(SNAME *_set_, V element, bool *new_node) \ + 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; \ \ - SNAME##_entry *entry = PFX##_impl_get_entry(_set_, element); \ + struct SNAME##_entry *entry = PFX##_impl_get_entry(_set_, element); \ \ if (entry != NULL) \ return entry; \ @@ -1125,7 +1130,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, /* Current multiplicity. Might change due to robin hood hashing */ \ size_t curr_mul = 1; \ \ - SNAME##_entry *target = &(_set_->buffer[pos]); \ + struct SNAME##_entry *target = &(_set_->buffer[pos]); \ \ if (target->state == CMC_ES_EMPTY || target->state == CMC_ES_DELETED) \ { \ @@ -1173,12 +1178,12 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return target; \ } \ \ - static SNAME##_entry *PFX##_impl_get_entry(SNAME *_set_, V element) \ + 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; \ \ - SNAME##_entry *target = &(_set_->buffer[pos]); \ + struct SNAME##_entry *target = &(_set_->buffer[pos]); \ \ while (target->state == CMC_ES_FILLED || target->state == CMC_ES_DELETED) \ { \ @@ -1206,18 +1211,18 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return cmc_hashtable_primes[i]; \ } \ \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_set_) \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_set_) \ { \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ \ PFX##_iter_init(&iter, _set_); \ \ return iter; \ } \ \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_set_) \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_set_) \ { \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ \ PFX##_iter_init(&iter, _set_); \ PFX##_iter_to_end(&iter); \ diff --git a/src/cmc/queue.h b/src/cmc/queue.h index 8215e96..ed0487c 100644 --- a/src/cmc/queue.h +++ b/src/cmc/queue.h @@ -64,533 +64,531 @@ static const char *cmc_string_fmt_queue = "%s at %p { buffer:%p, capacity:%" PRI CMC_GENERATE_QUEUE_SOURCE(PFX, SNAME, V) /* HEADER ********************************************************************/ -#define CMC_GENERATE_QUEUE_HEADER(PFX, SNAME, V) \ - \ - /* Queue Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Dynamic circular array of elements */ \ - V *buffer; \ - \ - /* Current circular array capacity */ \ - size_t capacity; \ - \ - /* Current amount of elements */ \ - size_t count; \ - \ - /* Index representing the front of the queue */ \ - size_t front; \ - \ - /* Index representing the back of the queue */ \ - size_t back; \ - \ - /* Function that returns an iterator to the start of the queue */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the queue */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Queue Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target queue */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - SNAME *PFX##_new(size_t capacity); \ - void PFX##_clear(SNAME *_queue_, void (*deallocator)(V)); \ - void PFX##_free(SNAME *_queue_, void (*deallocator)(V)); \ - /* Collection Input and Output */ \ - bool PFX##_enqueue(SNAME *_queue_, V element); \ - bool PFX##_dequeue(SNAME *_queue_); \ - /* Element Access */ \ - V PFX##_peek(SNAME *_queue_); \ - /* Collection State */ \ - bool PFX##_contains(SNAME *_queue_, V element, int (*comparator)(V, V)); \ - bool PFX##_empty(SNAME *_queue_); \ - bool PFX##_full(SNAME *_queue_); \ - size_t PFX##_count(SNAME *_queue_); \ - size_t PFX##_capacity(SNAME *_queue_); \ - /* Collection Utility */ \ - bool PFX##_resize(SNAME *_queue_, size_t capacity); \ - SNAME *PFX##_copy_of(SNAME *_queue_, V (*copy_func)(V)); \ - bool PFX##_equals(SNAME *_queue1_, SNAME *_queue2_, int (*comparator)(V, V)); \ - cmc_string PFX##_to_string(SNAME *_queue_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - SNAME##_iter *PFX##_iter_new(SNAME *target); \ - void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(SNAME##_iter *iter); \ - bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(SNAME##_iter *iter); \ - void PFX##_iter_to_end(SNAME##_iter *iter); \ - bool PFX##_iter_next(SNAME##_iter *iter); \ - bool PFX##_iter_prev(SNAME##_iter *iter); \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - V PFX##_iter_value(SNAME##_iter *iter); \ - V *PFX##_iter_rvalue(SNAME##_iter *iter); \ - size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ +#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 *); \ + }; \ + \ + /* 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); \ + void PFX##_clear(struct SNAME *_queue_, void (*deallocator)(V)); \ + void PFX##_free(struct SNAME *_queue_, void (*deallocator)(V)); \ + /* 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 SNAME##_iter PFX##_impl_it_start(SNAME *_queue_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_queue_); \ - \ - SNAME *PFX##_new(size_t capacity) \ - { \ - if (capacity < 1) \ - return NULL; \ - \ - SNAME *_queue_ = malloc(sizeof(SNAME)); \ - \ - if (!_queue_) \ - return NULL; \ - \ - _queue_->buffer = calloc(capacity, sizeof(V)); \ - \ - if (!_queue_->buffer) \ - { \ - 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; \ - \ - return _queue_; \ - } \ - \ - void PFX##_clear(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(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; \ - } \ - } \ - \ - free(_queue_->buffer); \ - free(_queue_); \ - } \ - \ - bool PFX##_enqueue(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(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(SNAME *_queue_) \ - { \ - if (PFX##_empty(_queue_)) \ - return (V){0}; \ - \ - return _queue_->buffer[_queue_->front]; \ - } \ - \ - bool PFX##_contains(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(SNAME *_queue_) \ - { \ - return _queue_->count == 0; \ - } \ - \ - bool PFX##_full(SNAME *_queue_) \ - { \ - return _queue_->count >= _queue_->capacity; \ - } \ - \ - size_t PFX##_count(SNAME *_queue_) \ - { \ - return _queue_->count; \ - } \ - \ - size_t PFX##_capacity(SNAME *_queue_) \ - { \ - return _queue_->capacity; \ - } \ - \ - bool PFX##_resize(SNAME *_queue_, size_t capacity) \ - { \ - if (PFX##_capacity(_queue_) == capacity) \ - return true; \ - \ - if (capacity < PFX##_count(_queue_)) \ - return false; \ - \ - V *new_buffer = 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_); \ - } \ - \ - free(_queue_->buffer); \ - \ - _queue_->buffer = new_buffer; \ - _queue_->capacity = capacity; \ - _queue_->front = 0; \ - _queue_->back = _queue_->count; \ - \ - return true; \ - } \ - \ - SNAME *PFX##_copy_of(SNAME *_queue_, V (*copy_func)(V)) \ - { \ - 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(SNAME *_queue1_, 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; \ - } \ - \ - cmc_string PFX##_to_string(SNAME *_queue_) \ - { \ - cmc_string str; \ - SNAME *q_ = _queue_; \ - const char *name = #SNAME; \ - \ - snprintf(str.s, cmc_string_len, cmc_string_fmt_queue, \ - name, q_, q_->buffer, q_->capacity, q_->count, q_->front, q_->back); \ - \ - return str; \ - } \ - \ - SNAME##_iter *PFX##_iter_new(SNAME *target) \ - { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ - { \ - iter->target = target; \ - iter->cursor = target->front; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - } \ - \ - bool PFX##_iter_start(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(SNAME##_iter *iter) \ - { \ - iter->cursor = iter->target->front; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - } \ - \ - void PFX##_iter_to_end(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - iter->cursor = 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(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(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(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(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(SNAME##_iter *iter, size_t index) \ - { \ - if (index >= PFX##_count(iter->target)) \ - return false; \ - \ - if (iter->index > index) \ - return PFX##_iter_rewind(iter, iter->index - index); \ - else if (iter->index < index) \ - return PFX##_iter_advance(iter, index - iter->index); \ - \ - return true; \ - } \ - \ - V PFX##_iter_value(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){0}; \ - \ - return iter->target->buffer[iter->cursor]; \ - } \ - \ - V *PFX##_iter_rvalue(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->target->buffer[iter->cursor]); \ - } \ - \ - size_t PFX##_iter_index(SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_queue_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _queue_); \ - PFX##_iter_to_start(&iter); \ - \ - return iter; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_queue_) \ - { \ - 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) \ + { \ + if (capacity < 1) \ + return NULL; \ + \ + struct SNAME *_queue_ = malloc(sizeof(struct SNAME)); \ + \ + if (!_queue_) \ + return NULL; \ + \ + _queue_->buffer = calloc(capacity, sizeof(V)); \ + \ + if (!_queue_->buffer) \ + { \ + 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; \ + \ + 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; \ + } \ + } \ + \ + free(_queue_->buffer); \ + free(_queue_); \ + } \ + \ + 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 = 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_); \ + } \ + \ + 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_; \ + const char *name = #SNAME; \ + \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_queue, \ + name, q_, q_->buffer, q_->capacity, q_->count, q_->front, q_->back); \ + \ + 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) \ + { \ + 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 aedeca3..9253e40 100644 --- a/src/cmc/sortedlist.h +++ b/src/cmc/sortedlist.h @@ -43,115 +43,113 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% CMC_GENERATE_SORTEDLIST_SOURCE(PFX, SNAME, V) /* HEADER ********************************************************************/ -#define CMC_GENERATE_SORTEDLIST_HEADER(PFX, SNAME, V) \ - \ - /* List Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Dynamic array of elements */ \ - V *buffer; \ - \ - /* Current array capacity */ \ - size_t capacity; \ - \ - /* Current amount of elements */ \ - size_t count; \ - \ - /* 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_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the list */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* List Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target list */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)); \ - void PFX##_clear(SNAME *_list_, void (*deallocator)(V)); \ - void PFX##_free(SNAME *_list_, void (*deallocator)(V)); \ - /* Collection Input and Output */ \ - bool PFX##_insert(SNAME *_list_, V element); \ - bool PFX##_remove(SNAME *_list_, size_t index); \ - /* Element Access */ \ - bool PFX##_max(SNAME *_list_, V *result); \ - bool PFX##_min(SNAME *_list_, V *result); \ - V PFX##_get(SNAME *_list_, size_t index); \ - size_t PFX##_indexof(SNAME *_list_, V element, bool from_start); \ - /* Collection State */ \ - bool PFX##_contains(SNAME *_list_, V element); \ - bool PFX##_empty(SNAME *_list_); \ - bool PFX##_full(SNAME *_list_); \ - size_t PFX##_count(SNAME *_list_); \ - size_t PFX##_capacity(SNAME *_list_); \ - /* Collection Utility */ \ - bool PFX##_resize(SNAME *_list_, size_t capacity); \ - void PFX##_sort(SNAME *_list_); \ - SNAME *PFX##_copy_of(SNAME *_list_, V (*copy_func)(V)); \ - bool PFX##_equals(SNAME *_list1_, SNAME *_list2_); \ - cmc_string PFX##_to_string(SNAME *_list_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - SNAME##_iter *PFX##_iter_new(SNAME *target); \ - void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(SNAME##_iter *iter); \ - bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(SNAME##_iter *iter); \ - void PFX##_iter_to_end(SNAME##_iter *iter); \ - bool PFX##_iter_next(SNAME##_iter *iter); \ - bool PFX##_iter_prev(SNAME##_iter *iter); \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - V PFX##_iter_value(SNAME##_iter *iter); \ - size_t PFX##_iter_index(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 *); \ + }; \ + \ + /* 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)); \ + void PFX##_clear(struct SNAME *_list_, void (*deallocator)(V)); \ + void PFX##_free(struct SNAME *_list_, void (*deallocator)(V)); \ + /* 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(SNAME *_list_, V value); \ - static size_t PFX##_impl_binary_search_last(SNAME *_list_, V value); \ + 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 SNAME##_iter PFX##_impl_it_start(SNAME *_list_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_list_); \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_list_); \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_list_); \ \ - SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)) \ + struct SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)) \ { \ if (capacity < 1) \ return NULL; \ \ - SNAME *_list_ = malloc(sizeof(SNAME)); \ + struct SNAME *_list_ = malloc(sizeof(struct SNAME)); \ \ if (!_list_) \ return NULL; \ @@ -175,7 +173,7 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% return _list_; \ } \ \ - void PFX##_clear(SNAME *_list_, void (*deallocator)(V)) \ + void PFX##_clear(struct SNAME *_list_, void (*deallocator)(V)) \ { \ if (deallocator) \ { \ @@ -188,7 +186,7 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% _list_->count = 0; \ } \ \ - void PFX##_free(SNAME *_list_, void (*deallocator)(V)) \ + void PFX##_free(struct SNAME *_list_, void (*deallocator)(V)) \ { \ if (deallocator) \ { \ @@ -200,7 +198,7 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% free(_list_); \ } \ \ - bool PFX##_insert(SNAME *_list_, V element) \ + bool PFX##_insert(struct SNAME *_list_, V element) \ { \ if (PFX##_full(_list_)) \ { \ @@ -215,7 +213,7 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% return true; \ } \ \ - bool PFX##_remove(SNAME *_list_, size_t index) \ + bool PFX##_remove(struct SNAME *_list_, size_t index) \ { \ if (index >= _list_->count) \ return false; \ @@ -228,7 +226,7 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% return true; \ } \ \ - bool PFX##_min(SNAME *_list_, V *result) \ + bool PFX##_min(struct SNAME *_list_, V *result) \ { \ if (PFX##_empty(_list_)) \ return false; \ @@ -240,7 +238,7 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% return true; \ } \ \ - bool PFX##_max(SNAME *_list_, V *result) \ + bool PFX##_max(struct SNAME *_list_, V *result) \ { \ if (PFX##_empty(_list_)) \ return false; \ @@ -252,7 +250,7 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% return true; \ } \ \ - V PFX##_get(SNAME *_list_, size_t index) \ + V PFX##_get(struct SNAME *_list_, size_t index) \ { \ if (index >= _list_->count) \ return (V){0}; \ @@ -262,7 +260,7 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% return _list_->buffer[index]; \ } \ \ - size_t PFX##_indexof(SNAME *_list_, V element, bool from_start) \ + size_t PFX##_indexof(struct SNAME *_list_, V element, bool from_start) \ { \ PFX##_sort(_list_); \ \ @@ -274,7 +272,7 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% return PFX##_impl_binary_search_last(_list_, element); \ } \ \ - bool PFX##_contains(SNAME *_list_, V element) \ + bool PFX##_contains(struct SNAME *_list_, V element) \ { \ if (PFX##_empty(_list_)) \ return false; \ @@ -284,27 +282,27 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% return PFX##_impl_binary_search_first(_list_, element) < PFX##_count(_list_); \ } \ \ - bool PFX##_empty(SNAME *_list_) \ + bool PFX##_empty(struct SNAME *_list_) \ { \ return _list_->count == 0; \ } \ \ - bool PFX##_full(SNAME *_list_) \ + bool PFX##_full(struct SNAME *_list_) \ { \ return _list_->count >= _list_->capacity; \ } \ \ - size_t PFX##_count(SNAME *_list_) \ + size_t PFX##_count(struct SNAME *_list_) \ { \ return _list_->count; \ } \ \ - size_t PFX##_capacity(SNAME *_list_) \ + size_t PFX##_capacity(struct SNAME *_list_) \ { \ return _list_->capacity; \ } \ \ - bool PFX##_resize(SNAME *_list_, size_t capacity) \ + bool PFX##_resize(struct SNAME *_list_, size_t capacity) \ { \ if (PFX##_capacity(_list_) == capacity) \ return true; \ @@ -323,7 +321,7 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% return true; \ } \ \ - void PFX##_sort(SNAME *_list_) \ + void PFX##_sort(struct SNAME *_list_) \ { \ if (!_list_->is_sorted && _list_->count > 1) \ { \ @@ -333,9 +331,9 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% } \ } \ \ - SNAME *PFX##_copy_of(SNAME *_list_, V (*copy_func)(V)) \ + struct SNAME *PFX##_copy_of(struct SNAME *_list_, V (*copy_func)(V)) \ { \ - SNAME *result = PFX##_new(_list_->capacity, _list_->cmp); \ + struct SNAME *result = PFX##_new(_list_->capacity, _list_->cmp); \ \ if (!result) \ return NULL; \ @@ -353,7 +351,7 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% return result; \ } \ \ - bool PFX##_equals(SNAME *_list1_, SNAME *_list2_) \ + bool PFX##_equals(struct SNAME *_list1_, struct SNAME *_list2_) \ { \ if (PFX##_count(_list1_) != PFX##_count(_list2_)) \ return false; \ @@ -370,10 +368,10 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% return false; \ } \ \ - cmc_string PFX##_to_string(SNAME *_list_) \ + struct cmc_string PFX##_to_string(struct SNAME *_list_) \ { \ - cmc_string str; \ - SNAME *l_ = _list_; \ + struct cmc_string str; \ + struct SNAME *l_ = _list_; \ const char *name = #SNAME; \ \ snprintf(str.s, cmc_string_len, cmc_string_fmt_sortedlist, \ @@ -383,9 +381,9 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% return str; \ } \ \ - SNAME##_iter *PFX##_iter_new(SNAME *target) \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ + struct SNAME##_iter *iter = malloc(sizeof(struct SNAME##_iter)); \ \ if (!iter) \ return NULL; \ @@ -395,12 +393,12 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% return iter; \ } \ \ - void PFX##_iter_free(SNAME##_iter *iter) \ + void PFX##_iter_free(struct SNAME##_iter *iter) \ { \ free(iter); \ } \ \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ { \ PFX##_sort(target); \ \ @@ -410,17 +408,17 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% iter->end = PFX##_empty(target); \ } \ \ - bool PFX##_iter_start(SNAME##_iter *iter) \ + bool PFX##_iter_start(struct SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->start; \ } \ \ - bool PFX##_iter_end(SNAME##_iter *iter) \ + bool PFX##_iter_end(struct SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->end; \ } \ \ - void PFX##_iter_to_start(SNAME##_iter *iter) \ + void PFX##_iter_to_start(struct SNAME##_iter *iter) \ { \ if (!PFX##_empty(iter->target)) \ { \ @@ -430,7 +428,7 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% } \ } \ \ - void PFX##_iter_to_end(SNAME##_iter *iter) \ + void PFX##_iter_to_end(struct SNAME##_iter *iter) \ { \ if (!PFX##_empty(iter->target)) \ { \ @@ -440,7 +438,7 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% } \ } \ \ - bool PFX##_iter_next(SNAME##_iter *iter) \ + bool PFX##_iter_next(struct SNAME##_iter *iter) \ { \ if (iter->end) \ return false; \ @@ -458,7 +456,7 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% return true; \ } \ \ - bool PFX##_iter_prev(SNAME##_iter *iter) \ + bool PFX##_iter_prev(struct SNAME##_iter *iter) \ { \ if (iter->start) \ return false; \ @@ -477,7 +475,7 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% } \ \ /* Returns true only if the iterator moved */ \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps) \ { \ if (iter->end) \ return false; \ @@ -499,7 +497,7 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% } \ \ /* Returns true only if the iterator moved */ \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps) \ { \ if (iter->start) \ return false; \ @@ -521,7 +519,7 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% } \ \ /* Returns true only if the iterator was able to be positioned at the given index */ \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index) \ { \ if (index >= PFX##_count(iter->target)) \ return false; \ @@ -534,7 +532,7 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% return true; \ } \ \ - V PFX##_iter_value(SNAME##_iter *iter) \ + V PFX##_iter_value(struct SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ return (V){0}; \ @@ -542,12 +540,12 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% return iter->target->buffer[iter->cursor]; \ } \ \ - size_t PFX##_iter_index(SNAME##_iter *iter) \ + size_t PFX##_iter_index(struct SNAME##_iter *iter) \ { \ return iter->cursor; \ } \ \ - static size_t PFX##_impl_binary_search_first(SNAME *_list_, V value) \ + static size_t PFX##_impl_binary_search_first(struct SNAME *_list_, V value) \ { \ if (PFX##_empty(_list_)) \ return 1; \ @@ -572,7 +570,7 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% return PFX##_count(_list_); \ } \ \ - static size_t PFX##_impl_binary_search_last(SNAME *_list_, V value) \ + static size_t PFX##_impl_binary_search_last(struct SNAME *_list_, V value) \ { \ if (PFX##_empty(_list_)) \ return 1; \ @@ -669,9 +667,9 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% } \ } \ \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_list_) \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_list_) \ { \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ \ PFX##_iter_init(&iter, _list_); \ PFX##_iter_to_start(&iter); \ @@ -679,9 +677,9 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% return iter; \ } \ \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_list_) \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_list_) \ { \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ \ PFX##_iter_init(&iter, _list_); \ PFX##_iter_to_end(&iter); \ diff --git a/src/cmc/stack.h b/src/cmc/stack.h index 6df60b9..3432f52 100644 --- a/src/cmc/stack.h +++ b/src/cmc/stack.h @@ -49,467 +49,465 @@ static const char *cmc_string_fmt_stack = "%s at %p { buffer:%p, capacity:%" PRI CMC_GENERATE_STACK_SOURCE(PFX, SNAME, V) /* HEADER ********************************************************************/ -#define CMC_GENERATE_STACK_HEADER(PFX, SNAME, V) \ - \ - /* Stack Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Dynamic array of elements */ \ - V *buffer; \ - \ - /* Current array capacity */ \ - size_t capacity; \ - \ - /* Current amount of elements */ \ - size_t count; \ - \ - /* Function that returns an iterator to the start of the stack */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the stack */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Stack Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target stack */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - SNAME *PFX##_new(size_t capacity); \ - void PFX##_clear(SNAME *_stack_, void (*deallocator)(V)); \ - void PFX##_free(SNAME *_stack_, void (*deallocator)(V)); \ - /* Collection Input and Output */ \ - bool PFX##_push(SNAME *_stack_, V element); \ - bool PFX##_pop(SNAME *_stack_); \ - /* Element Access */ \ - V PFX##_top(SNAME *_stack_); \ - /* Collection State */ \ - bool PFX##_contains(SNAME *_stack_, V element, int (*comparator)(V, V)); \ - bool PFX##_empty(SNAME *_stack_); \ - bool PFX##_full(SNAME *_stack_); \ - size_t PFX##_count(SNAME *_stack_); \ - size_t PFX##_capacity(SNAME *_stack_); \ - /* Collection Utility */ \ - bool PFX##_resize(SNAME *_stack_, size_t capacity); \ - SNAME *PFX##_copy_of(SNAME *_stack_, V (*copy_func)(V)); \ - bool PFX##_equals(SNAME *_stack1_, SNAME *_stack2_, int (*comparator)(V, V)); \ - cmc_string PFX##_to_string(SNAME *_stack_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - SNAME##_iter *PFX##_iter_new(SNAME *target); \ - void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(SNAME##_iter *iter); \ - bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(SNAME##_iter *iter); \ - void PFX##_iter_to_end(SNAME##_iter *iter); \ - bool PFX##_iter_next(SNAME##_iter *iter); \ - bool PFX##_iter_prev(SNAME##_iter *iter); \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - V PFX##_iter_value(SNAME##_iter *iter); \ - V *PFX##_iter_rvalue(SNAME##_iter *iter); \ - size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ +#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 *); \ + }; \ + \ + /* 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); \ + void PFX##_clear(struct SNAME *_stack_, void (*deallocator)(V)); \ + void PFX##_free(struct SNAME *_stack_, void (*deallocator)(V)); \ + /* 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 SNAME##_iter PFX##_impl_it_start(SNAME *_stack_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_stack_); \ - \ - SNAME *PFX##_new(size_t capacity) \ - { \ - if (capacity < 1) \ - return NULL; \ - \ - SNAME *_stack_ = malloc(sizeof(SNAME)); \ - \ - if (!_stack_) \ - return NULL; \ - \ - _stack_->buffer = calloc(capacity, sizeof(V)); \ - \ - if (!_stack_->buffer) \ - { \ - free(_stack_); \ - return NULL; \ - } \ - \ - _stack_->capacity = capacity; \ - _stack_->count = 0; \ - \ - _stack_->it_start = PFX##_impl_it_start; \ - _stack_->it_end = PFX##_impl_it_end; \ - \ - return _stack_; \ - } \ - \ - void PFX##_clear(SNAME *_stack_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _stack_->count; i++) \ - deallocator(_stack_->buffer[i]); \ - } \ - \ - memset(_stack_->buffer, 0, sizeof(V) * _stack_->capacity); \ - \ - _stack_->count = 0; \ - } \ - \ - void PFX##_free(SNAME *_stack_, void (*deallocator)(V)) \ - { \ - free(_stack_->buffer); \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _stack_->count; i++) \ - deallocator(_stack_->buffer[i]); \ - } \ - \ - free(_stack_); \ - } \ - \ - bool PFX##_push(SNAME *_stack_, V element) \ - { \ - if (PFX##_full(_stack_)) \ - { \ - if (!PFX##_resize(_stack_, PFX##_capacity(_stack_) * 2)) \ - return false; \ - } \ - \ - _stack_->buffer[_stack_->count++] = element; \ - \ - return true; \ - } \ - \ - bool PFX##_pop(SNAME *_stack_) \ - { \ - if (PFX##_empty(_stack_)) \ - return false; \ - \ - _stack_->buffer[--_stack_->count] = (V){0}; \ - \ - return true; \ - } \ - \ - V PFX##_top(SNAME *_stack_) \ - { \ - if (PFX##_empty(_stack_)) \ - return (V){0}; \ - \ - return _stack_->buffer[_stack_->count - 1]; \ - } \ - \ - bool PFX##_contains(SNAME *_stack_, V element, int (*comparator)(V, V)) \ - { \ - for (size_t i = 0; i < _stack_->count; i++) \ - { \ - if (comparator(_stack_->buffer[i], element) == 0) \ - return true; \ - } \ - \ - return false; \ - } \ - \ - bool PFX##_empty(SNAME *_stack_) \ - { \ - return _stack_->count == 0; \ - } \ - \ - bool PFX##_full(SNAME *_stack_) \ - { \ - return _stack_->count >= _stack_->capacity; \ - } \ - \ - size_t PFX##_count(SNAME *_stack_) \ - { \ - return _stack_->count; \ - } \ - \ - size_t PFX##_capacity(SNAME *_stack_) \ - { \ - return _stack_->capacity; \ - } \ - \ - bool PFX##_resize(SNAME *_stack_, size_t capacity) \ - { \ - if (PFX##_capacity(_stack_) == capacity) \ - return true; \ - \ - if (capacity < PFX##_count(_stack_)) \ - return false; \ - \ - V *new_buffer = realloc(_stack_->buffer, sizeof(V) * capacity); \ - \ - if (!new_buffer) \ - return false; \ - \ - _stack_->buffer = new_buffer; \ - _stack_->capacity = capacity; \ - \ - return true; \ - } \ - \ - SNAME *PFX##_copy_of(SNAME *_stack_, V (*copy_func)(V)) \ - { \ - SNAME *result = PFX##_new(_stack_->capacity); \ - \ - if (!result) \ - return NULL; \ - \ - if (copy_func) \ - { \ - for (size_t i = 0; i < _stack_->count; i++) \ - result->buffer[i] = copy_func(_stack_->buffer[i]); \ - } \ - else \ - memcpy(result->buffer, _stack_->buffer, sizeof(V) * _stack_->count); \ - \ - result->count = _stack_->count; \ - \ - return result; \ - } \ - \ - bool PFX##_equals(SNAME *_stack1_, SNAME *_stack2_, int (*comparator)(V, V)) \ - { \ - if (PFX##_count(_stack1_) != PFX##_count(_stack2_)) \ - return false; \ - \ - for (size_t i = 0; i < PFX##_count(_stack1_); i++) \ - { \ - if (comparator(_stack1_->buffer[i], _stack2_->buffer[i]) != 0) \ - return false; \ - } \ - \ - return true; \ - } \ - \ - cmc_string PFX##_to_string(SNAME *_stack_) \ - { \ - cmc_string str; \ - SNAME *s_ = _stack_; \ - const char *name = #SNAME; \ - \ - snprintf(str.s, cmc_string_len, cmc_string_fmt_stack, \ - name, s_, s_->buffer, s_->capacity, s_->count); \ - \ - return str; \ - } \ - \ - SNAME##_iter *PFX##_iter_new(SNAME *target) \ - { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ - { \ - iter->target = target; \ - iter->cursor = PFX##_empty(target) ? 0 : iter->target->count - 1; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - } \ - \ - bool PFX##_iter_start(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = iter->target->count - 1; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - } \ - } \ - \ - void PFX##_iter_to_end(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->cursor = 0; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - } \ - } \ - \ - bool PFX##_iter_next(SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->cursor == 0) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - iter->cursor--; \ - \ - return true; \ - } \ - \ - bool PFX##_iter_prev(SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->cursor + 1 == PFX##_count(iter->target)) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - iter->cursor++; \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->end) \ - return false; \ - \ - if (iter->cursor == 0) \ - { \ - iter->end = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->cursor < steps) \ - return false; \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - iter->cursor -= steps; \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator moved */ \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ - { \ - if (iter->start) \ - return false; \ - \ - if (iter->cursor + 1 == PFX##_count(iter->target)) \ - { \ - iter->start = true; \ - return false; \ - } \ - \ - if (steps == 0 || iter->cursor + steps >= PFX##_count(iter->target)) \ - return false; \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - iter->cursor += steps; \ - \ - return true; \ - } \ - \ - /* Returns true only if the iterator was able to be positioned at the */ \ - /* given index */ \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ - { \ - if (index >= PFX##_count(iter->target)) \ - return false; \ - \ - if (iter->cursor > index) \ - return PFX##_iter_rewind(iter, iter->cursor - index); \ - else if (iter->cursor < index) \ - return PFX##_iter_advance(iter, index - iter->cursor); \ - \ - return true; \ - } \ - \ - V PFX##_iter_value(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){0}; \ - \ - return iter->target->buffer[iter->cursor]; \ - } \ - \ - V *PFX##_iter_rvalue(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->target->buffer[iter->cursor]); \ - } \ - \ - size_t PFX##_iter_index(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return 0; \ - \ - return iter->target->count - 1 - iter->cursor; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_stack_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _stack_); \ - PFX##_iter_to_start(&iter); \ - \ - return iter; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_stack_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _stack_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ +#define CMC_GENERATE_STACK_SOURCE(PFX, SNAME, V) \ + \ + /* Implementation Detail Functions */ \ + static 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) \ + { \ + if (capacity < 1) \ + return NULL; \ + \ + struct SNAME *_stack_ = malloc(sizeof(struct SNAME)); \ + \ + if (!_stack_) \ + return NULL; \ + \ + _stack_->buffer = calloc(capacity, sizeof(V)); \ + \ + if (!_stack_->buffer) \ + { \ + free(_stack_); \ + return NULL; \ + } \ + \ + _stack_->capacity = capacity; \ + _stack_->count = 0; \ + \ + _stack_->it_start = PFX##_impl_it_start; \ + _stack_->it_end = PFX##_impl_it_end; \ + \ + return _stack_; \ + } \ + \ + void PFX##_clear(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)) \ + { \ + free(_stack_->buffer); \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _stack_->count; i++) \ + deallocator(_stack_->buffer[i]); \ + } \ + \ + free(_stack_); \ + } \ + \ + 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 = 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_; \ + const char *name = #SNAME; \ + \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_stack, \ + name, s_, s_->buffer, s_->capacity, s_->count); \ + \ + 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) \ + { \ + 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 38d3db4..2dc13e2 100644 --- a/src/cmc/treemap.h +++ b/src/cmc/treemap.h @@ -40,981 +40,980 @@ static const char *cmc_string_fmt_treemap = "%s at %p { root:%p, count:%" PRIuMA CMC_GENERATE_TREEMAP_SOURCE(PFX, SNAME, K, V) /* HEADER ********************************************************************/ -#define CMC_GENERATE_TREEMAP_HEADER(PFX, SNAME, K, V) \ - \ - /* Treemap Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Root node */ \ - struct SNAME##_node_s *root; \ - \ - /* Current amount of keys */ \ - size_t count; \ - \ - /* Key comparison function */ \ - int (*cmp)(K, K); \ - \ - /* Function that returns an iterator to the start of the treemap */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the treemap */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Treemap Node */ \ - typedef struct SNAME##_node_s \ - { \ - /* Node Key */ \ - K key; \ - \ - /* Node Value */ \ - V value; \ - \ - /* Node height used by the AVL tree to keep it strictly balanced */ \ - unsigned char height; \ - \ - /* Right child node or subtree */ \ - struct SNAME##_node_s *right; \ - \ - /* Left child node or subtree */ \ - struct SNAME##_node_s *left; \ - \ - /* Parent node */ \ - struct SNAME##_node_s *parent; \ - \ - } SNAME##_node, *SNAME##_node_ptr; \ - \ - /* Treemap Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target treemap */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's current node */ \ - struct SNAME##_node_s *cursor; \ - \ - /* The first node in the iteration */ \ - struct SNAME##_node_s *first; \ - \ - /* The last node in the iteration */ \ - struct SNAME##_node_s *last; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - SNAME *PFX##_new(int (*compare)(K, K)); \ - void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)); \ - void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)); \ - /* Collection Input and Output */ \ - bool PFX##_insert(SNAME *_map_, K key, V value); \ - bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value); \ - bool PFX##_remove(SNAME *_map_, K key, V *out_value); \ - /* Element Access */ \ - bool PFX##_max(SNAME *_map_, K *key, V *value); \ - bool PFX##_min(SNAME *_map_, K *key, V *value); \ - V PFX##_get(SNAME *_map_, K key); \ - V *PFX##_get_ref(SNAME *_map_, K key); \ - /* Collection State */ \ - bool PFX##_contains(SNAME *_map_, K key); \ - bool PFX##_empty(SNAME *_map_); \ - size_t PFX##_count(SNAME *_map_); \ - /* Collection Utility */ \ - SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)); \ - bool PFX##_equals(SNAME *_map1_, SNAME *_map2_, int (*value_comparator)(V, V)); \ - cmc_string PFX##_to_string(SNAME *_map_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - SNAME##_iter *PFX##_iter_new(SNAME *target); \ - void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(SNAME##_iter *iter); \ - bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(SNAME##_iter *iter); \ - void PFX##_iter_to_end(SNAME##_iter *iter); \ - bool PFX##_iter_next(SNAME##_iter *iter); \ - bool PFX##_iter_prev(SNAME##_iter *iter); \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - K PFX##_iter_key(SNAME##_iter *iter); \ - V PFX##_iter_value(SNAME##_iter *iter); \ - V *PFX##_iter_rvalue(SNAME##_iter *iter); \ - size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ +#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 *); \ + }; \ + \ + /* 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)); \ + void PFX##_clear(struct SNAME *_map_, void (*deallocator)(K, V)); \ + void PFX##_free(struct SNAME *_map_, void (*deallocator)(K, V)); \ + /* 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 SNAME##_node *PFX##_impl_new_node(K key, V value); \ - static SNAME##_node *PFX##_impl_get_node(SNAME *_map_, K key); \ - static unsigned char PFX##_impl_h(SNAME##_node *node); \ - static unsigned char PFX##_impl_hupdate(SNAME##_node *node); \ - static void PFX##_impl_rotate_right(SNAME##_node **Z); \ - static void PFX##_impl_rotate_left(SNAME##_node **Z); \ - static void PFX##_impl_rebalance(SNAME *_map_, SNAME##_node *node); \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_map_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_map_); \ - \ - SNAME *PFX##_new(int (*compare)(K, K)) \ - { \ - SNAME *_map_ = malloc(sizeof(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; \ - \ - return _map_; \ - } \ - \ - void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - SNAME##_node *scan = _map_->root; \ - SNAME##_node *up = NULL; \ - \ - while (scan != NULL) \ - { \ - if (scan->left != NULL) \ - { \ - SNAME##_node *left = scan->left; \ - \ - scan->left = up; \ - up = scan; \ - scan = left; \ - } \ - else if (scan->right != NULL) \ - { \ - 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(SNAME *_map_, void (*deallocator)(K, V)) \ - { \ - PFX##_clear(_map_, deallocator); \ - \ - free(_map_); \ - } \ - \ - bool PFX##_insert(SNAME *_map_, K key, V value) \ - { \ - if (PFX##_empty(_map_)) \ - { \ - _map_->root = PFX##_impl_new_node(key, value); \ - \ - if (!_map_->root) \ - return false; \ - } \ - else \ - { \ - SNAME##_node *scan = _map_->root; \ - 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; \ - } \ - \ - 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(SNAME *_map_, K key, V new_value, V *old_value) \ - { \ - 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(SNAME *_map_, K key, V *out_value) \ - { \ - SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ - \ - if (!node) \ - return false; \ - \ - if (out_value) \ - *out_value = node->value; \ - \ - 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(SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - SNAME##_node *scan = _map_->root; \ - \ - while (scan->right != NULL) \ - scan = scan->right; \ - \ - *key = scan->key; \ - *value = scan->value; \ - \ - return true; \ - } \ - \ - bool PFX##_min(SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - SNAME##_node *scan = _map_->root; \ - \ - while (scan->left != NULL) \ - scan = scan->left; \ - \ - *key = scan->key; \ - *value = scan->value; \ - \ - return true; \ - } \ - \ - V PFX##_get(SNAME *_map_, K key) \ - { \ - SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ - \ - if (!node) \ - return (V){0}; \ - \ - return node->value; \ - } \ - \ - V *PFX##_get_ref(SNAME *_map_, K key) \ - { \ - SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ - \ - if (!node) \ - return NULL; \ - \ - return &(node->value); \ - } \ - \ - bool PFX##_contains(SNAME *_map_, K key) \ - { \ - 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(SNAME *_map_) \ - { \ - return _map_->count == 0; \ - } \ - \ - size_t PFX##_count(SNAME *_map_) \ - { \ - return _map_->count; \ - } \ - \ - SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)) \ - { \ - SNAME *result = PFX##_new(_map_->cmp); \ - \ - if (!result) \ - return NULL; \ - \ - SNAME##_iter iter; \ - PFX##_iter_init(&iter, _map_); \ - \ - if (!PFX##_empty(_map_)) \ - { \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - K key = PFX##_iter_key(&iter); \ - V value = PFX##_iter_value(&iter); \ - \ - if (key_copy_func) \ - key = key_copy_func(key); \ - if (value_copy_func) \ - value = value_copy_func(value); \ - \ - PFX##_insert(result, key, value); \ - } \ - } \ - \ - return result; \ - } \ - \ - bool PFX##_equals(SNAME *_map1_, SNAME *_map2_, int (*value_comparator)(V, V)) \ - { \ - if (PFX##_count(_map1_) != PFX##_count(_map2_)) \ - return false; \ - \ - SNAME##_iter iter; \ - PFX##_iter_init(&iter, _map1_); \ - \ - for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - SNAME##_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; \ - } \ - \ - cmc_string PFX##_to_string(SNAME *_map_) \ - { \ - cmc_string str; \ - SNAME *m_ = _map_; \ - const char *name = #SNAME; \ - \ - snprintf(str.s, cmc_string_len, cmc_string_fmt_treemap, \ - name, m_, m_->root, m_->count, m_->cmp); \ - \ - return str; \ - } \ - \ - SNAME##_iter *PFX##_iter_new(SNAME *target) \ - { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - void PFX##_iter_free(SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ - { \ - memset(iter, 0, sizeof(SNAME##_iter)); \ - \ - iter->target = target; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - \ - 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(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - bool PFX##_iter_end(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - void PFX##_iter_to_start(SNAME##_iter *iter) \ - { \ - if (!PFX##_empty(iter->target)) \ - { \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - iter->cursor = iter->first; \ - } \ - } \ - \ - void PFX##_iter_to_end(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(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(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(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(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(SNAME##_iter *iter, size_t index) \ - { \ - if (index >= PFX##_count(iter->target)) \ - return false; \ - \ - if (iter->index > index) \ - return PFX##_iter_rewind(iter, iter->index - index); \ - else if (iter->index < index) \ - return PFX##_iter_advance(iter, index - iter->index); \ - \ - return true; \ - } \ - \ - K PFX##_iter_key(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (K){0}; \ - \ - return iter->cursor->key; \ - } \ - \ - V PFX##_iter_value(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return (V){0}; \ - \ - return iter->cursor->value; \ - } \ - \ - V *PFX##_iter_rvalue(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->cursor->value); \ - } \ - \ - size_t PFX##_iter_index(SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - static SNAME##_node *PFX##_impl_new_node(K key, V value) \ - { \ - SNAME##_node *node = malloc(sizeof(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 SNAME##_node *PFX##_impl_get_node(SNAME *_map_, K key) \ - { \ - if (PFX##_empty(_map_)) \ - return NULL; \ - \ - 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(SNAME##_node *node) \ - { \ - if (node == NULL) \ - return 0; \ - \ - return node->height; \ - } \ - \ - static unsigned char PFX##_impl_hupdate(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(SNAME##_node **Z) \ - { \ - SNAME##_node *root = *Z; \ - 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(SNAME##_node **Z) \ - { \ - SNAME##_node *root = *Z; \ - 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(SNAME *_map_, SNAME##_node *node) \ - { \ - 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 SNAME##_iter PFX##_impl_it_start(SNAME *_map_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _map_); \ - \ - return iter; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_map_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _map_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ +#define CMC_GENERATE_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 SNAME *_map_ = 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; \ + \ + 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_; \ + const char *name = #SNAME; \ + \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_treemap, \ + name, m_, m_->root, m_->count, m_->cmp); \ + \ + 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 86af1e5..a174220 100644 --- a/src/cmc/treeset.h +++ b/src/cmc/treeset.h @@ -40,153 +40,150 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA CMC_GENERATE_TREESET_SOURCE(PFX, SNAME, V) /* HEADER ********************************************************************/ -#define CMC_GENERATE_TREESET_HEADER(PFX, SNAME, V) \ - \ - /* Treeset Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Root node */ \ - struct SNAME##_node_s *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_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the treeset */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Treeset Node */ \ - typedef struct SNAME##_node_s \ - { \ - /* 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_s *right; \ - \ - /* Left child node or subtree */ \ - struct SNAME##_node_s *left; \ - \ - /* Parent node */ \ - struct SNAME##_node_s *parent; \ - \ - } SNAME##_node, *SNAME##_node_ptr; \ - \ - /* Treeset Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target treeset */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's current node */ \ - struct SNAME##_node_s *cursor; \ - \ - /* The first node in the iteration */ \ - struct SNAME##_node_s *first; \ - \ - /* The last node in the iteration */ \ - struct SNAME##_node_s *last; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - SNAME *PFX##_new(int (*compare)(V, V)); \ - void PFX##_clear(SNAME *_set_, void (*deallocator)(V)); \ - void PFX##_free(SNAME *_set_, void (*deallocator)(V)); \ - /* Collection Input and Output */ \ - bool PFX##_insert(SNAME *_set_, V element); \ - bool PFX##_remove(SNAME *_set_, V element); \ - /* Element Access */ \ - bool PFX##_max(SNAME *_set_, V *value); \ - bool PFX##_min(SNAME *_set_, V *value); \ - /* Collection State */ \ - bool PFX##_contains(SNAME *_set_, V element); \ - bool PFX##_empty(SNAME *_set_); \ - size_t PFX##_count(SNAME *_set_); \ - /* Collection Utility */ \ - SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)); \ - bool PFX##_equals(SNAME *_set1_, SNAME *_set2_); \ - cmc_string PFX##_to_string(SNAME *_set_); \ - \ - /* Set Operations */ \ - SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_); \ - SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_); \ - SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_); \ - SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_); \ - bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_); \ - bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_); \ - bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_); \ - bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_); \ - bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - SNAME##_iter *PFX##_iter_new(SNAME *target); \ - void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(SNAME##_iter *iter); \ - bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(SNAME##_iter *iter); \ - void PFX##_iter_to_end(SNAME##_iter *iter); \ - bool PFX##_iter_next(SNAME##_iter *iter); \ - bool PFX##_iter_prev(SNAME##_iter *iter); \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - V PFX##_iter_value(SNAME##_iter *iter); \ - size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ - /* Default Value */ \ - static inline V PFX##_impl_default_value(void) \ - { \ - V _empty_value_; \ - \ - memset(&_empty_value_, 0, sizeof(V)); \ - \ - return _empty_value_; \ - } \ - \ +#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 *); \ + }; \ + \ + /* 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)); \ + void PFX##_clear(struct SNAME *_set_, void (*deallocator)(V)); \ + void PFX##_free(struct SNAME *_set_, void (*deallocator)(V)); \ + /* 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 SNAME##_node *PFX##_impl_new_node(V element); \ - static SNAME##_node *PFX##_impl_get_node(SNAME *_set_, V element); \ - static unsigned char PFX##_impl_h(SNAME##_node *node); \ - static unsigned char PFX##_impl_hupdate(SNAME##_node *node); \ - static void PFX##_impl_rotate_right(SNAME##_node **Z); \ - static void PFX##_impl_rotate_left(SNAME##_node **Z); \ - static void PFX##_impl_rebalance(SNAME *_set_, SNAME##_node *node); \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_set_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_set_); \ + 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_); \ \ - SNAME *PFX##_new(int (*compare)(V, V)) \ + struct SNAME *PFX##_new(int (*compare)(V, V)) \ { \ - SNAME *_set_ = malloc(sizeof(SNAME)); \ + struct SNAME *_set_ = malloc(sizeof(struct SNAME)); \ \ if (!_set_) \ return NULL; \ @@ -201,16 +198,16 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA return _set_; \ } \ \ - void PFX##_clear(SNAME *_set_, void (*deallocator)(V)) \ + void PFX##_clear(struct SNAME *_set_, void (*deallocator)(V)) \ { \ - SNAME##_node *scan = _set_->root; \ - SNAME##_node *up = NULL; \ + struct SNAME##_node *scan = _set_->root; \ + struct SNAME##_node *up = NULL; \ \ while (scan != NULL) \ { \ if (scan->left != NULL) \ { \ - SNAME##_node *left = scan->left; \ + struct SNAME##_node *left = scan->left; \ \ scan->left = up; \ up = scan; \ @@ -218,7 +215,7 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA } \ else if (scan->right != NULL) \ { \ - SNAME##_node *right = scan->right; \ + struct SNAME##_node *right = scan->right; \ \ scan->left = up; \ scan->right = NULL; \ @@ -262,14 +259,14 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA _set_->root = NULL; \ } \ \ - void PFX##_free(SNAME *_set_, void (*deallocator)(V)) \ + void PFX##_free(struct SNAME *_set_, void (*deallocator)(V)) \ { \ PFX##_clear(_set_, deallocator); \ \ free(_set_); \ } \ \ - bool PFX##_insert(SNAME *_set_, V element) \ + bool PFX##_insert(struct SNAME *_set_, V element) \ { \ if (PFX##_empty(_set_)) \ { \ @@ -280,8 +277,8 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA } \ else \ { \ - SNAME##_node *scan = _set_->root; \ - SNAME##_node *parent = scan; \ + struct SNAME##_node *scan = _set_->root; \ + struct SNAME##_node *parent = scan; \ \ while (scan != NULL) \ { \ @@ -295,7 +292,7 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA return false; \ } \ \ - SNAME##_node *node; \ + struct SNAME##_node *node; \ \ if (_set_->cmp(parent->value, element) > 0) \ { \ @@ -326,14 +323,14 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA return true; \ } \ \ - bool PFX##_remove(SNAME *_set_, V element) \ + bool PFX##_remove(struct SNAME *_set_, V element) \ { \ - SNAME##_node *node = PFX##_impl_get_node(_set_, element); \ + struct SNAME##_node *node = PFX##_impl_get_node(_set_, element); \ \ if (!node) \ return false; \ \ - SNAME##_node *temp = NULL, *unbalanced = NULL; \ + struct SNAME##_node *temp = NULL, *unbalanced = NULL; \ \ bool is_root = node->parent == NULL; \ \ @@ -447,12 +444,12 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA return true; \ } \ \ - bool PFX##_max(SNAME *_set_, V *value) \ + bool PFX##_max(struct SNAME *_set_, V *value) \ { \ if (PFX##_empty(_set_)) \ return false; \ \ - SNAME##_node *scan = _set_->root; \ + struct SNAME##_node *scan = _set_->root; \ \ while (scan->right != NULL) \ scan = scan->right; \ @@ -462,12 +459,12 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA return true; \ } \ \ - bool PFX##_min(SNAME *_set_, V *value) \ + bool PFX##_min(struct SNAME *_set_, V *value) \ { \ if (PFX##_empty(_set_)) \ return false; \ \ - SNAME##_node *scan = _set_->root; \ + struct SNAME##_node *scan = _set_->root; \ \ while (scan->left != NULL) \ scan = scan->left; \ @@ -477,9 +474,9 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA return true; \ } \ \ - bool PFX##_contains(SNAME *_set_, V element) \ + bool PFX##_contains(struct SNAME *_set_, V element) \ { \ - SNAME##_node *scan = _set_->root; \ + struct SNAME##_node *scan = _set_->root; \ \ while (scan != NULL) \ { \ @@ -494,24 +491,24 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA return false; \ } \ \ - bool PFX##_empty(SNAME *_set_) \ + bool PFX##_empty(struct SNAME *_set_) \ { \ return _set_->count == 0; \ } \ \ - size_t PFX##_count(SNAME *_set_) \ + size_t PFX##_count(struct SNAME *_set_) \ { \ return _set_->count; \ } \ \ - SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)) \ + struct SNAME *PFX##_copy_of(struct SNAME *_set_, V (*copy_func)(V)) \ { \ - SNAME *result = PFX##_new(_set_->cmp); \ + struct SNAME *result = PFX##_new(_set_->cmp); \ \ if (!result) \ return NULL; \ \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ PFX##_iter_init(&iter, _set_); \ \ if (!PFX##_empty(_set_)) \ @@ -528,12 +525,12 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA return result; \ } \ \ - bool PFX##_equals(SNAME *_set1_, SNAME *_set2_) \ + bool PFX##_equals(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ if (PFX##_count(_set1_) != PFX##_count(_set2_)) \ return false; \ \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ PFX##_iter_init(&iter, _set1_); \ \ for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ @@ -545,10 +542,10 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA return true; \ } \ \ - cmc_string PFX##_to_string(SNAME *_set_) \ + struct cmc_string PFX##_to_string(struct SNAME *_set_) \ { \ - cmc_string str; \ - SNAME *s_ = _set_; \ + struct cmc_string str; \ + struct SNAME *s_ = _set_; \ const char *name = #SNAME; \ \ snprintf(str.s, cmc_string_len, cmc_string_fmt_treeset, \ @@ -557,14 +554,14 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA return str; \ } \ \ - SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_) \ + struct SNAME *PFX##_union(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ - SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ + struct SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ \ if (!_set_r_) \ return NULL; \ \ - SNAME##_iter iter1, iter2; \ + struct SNAME##_iter iter1, iter2; \ PFX##_iter_init(&iter1, _set1_); \ PFX##_iter_init(&iter2, _set2_); \ \ @@ -581,17 +578,17 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA return _set_r_; \ } \ \ - SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_) \ + struct SNAME *PFX##_intersection(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ - SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ + struct SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ \ if (!_set_r_) \ return NULL; \ \ - SNAME *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; \ - SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \ + struct SNAME *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; \ + struct SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \ \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ PFX##_iter_init(&iter, _set_A_); \ \ for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ @@ -605,14 +602,14 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA return _set_r_; \ } \ \ - SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_) \ + struct SNAME *PFX##_difference(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ - SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ + struct SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ \ if (!_set_r_) \ return NULL; \ \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ PFX##_iter_init(&iter, _set1_); \ \ for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ @@ -626,14 +623,14 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA return _set_r_; \ } \ \ - SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_) \ + struct SNAME *PFX##_symmetric_difference(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ - SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ + struct SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ \ if (!_set_r_) \ return NULL; \ \ - SNAME##_iter iter1, iter2; \ + struct SNAME##_iter iter1, iter2; \ PFX##_iter_init(&iter1, _set1_); \ PFX##_iter_init(&iter2, _set2_); \ \ @@ -659,7 +656,7 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA /* Is _set1_ a subset of _set2_ ? */ \ /* A set X is a subset of a set Y when: X <= Y */ \ /* If X is a subset of Y, then Y is a superset of X */ \ - bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_) \ + 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_ */ \ @@ -670,7 +667,7 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA if (PFX##_empty(_set1_)) \ return true; \ \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ \ PFX##_iter_init(&iter, _set1_); \ \ @@ -688,7 +685,7 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA /* Is _set1_ a superset of _set2_ ? */ \ /* A set X is a superset of a set Y when: X >= Y */ \ /* If X is a superset of Y, then Y is a subset of X */ \ - bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_) \ + bool PFX##_is_superset(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ return PFX##_is_subset(_set2_, _set1_); \ } \ @@ -696,7 +693,7 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA /* Is _set1_ a proper subset of _set2_ ? */ \ /* A set X is a proper subset of a set Y when: X < Y */ \ /* If X is a proper subset of Y, then Y is a proper superset of X */ \ - bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_) \ + 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_ */ \ @@ -713,7 +710,7 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA return false; \ } \ \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ \ PFX##_iter_init(&iter, _set1_); \ \ @@ -731,7 +728,7 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA /* Is _set1_ a proper superset of _set2_ ? */ \ /* A set X is a proper superset of a set Y when: X > Y */ \ /* If X is a proper superset of Y, then Y is a proper subset of X */ \ - bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_) \ + bool PFX##_is_proper_superset(struct SNAME *_set1_, struct SNAME *_set2_) \ { \ return PFX##_is_proper_subset(_set2_, _set1_); \ } \ @@ -739,14 +736,14 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA /* Is _set1_ a disjointset of _set2_ ? */ \ /* A set X is a disjointset of a set Y if their intersection is empty, that is, if */ \ /* there are no elements in common between the two */ \ - bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_) \ + 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; \ \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ \ PFX##_iter_init(&iter, _set1_); \ \ @@ -761,9 +758,9 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA return true; \ } \ \ - SNAME##_iter *PFX##_iter_new(SNAME *target) \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ + struct SNAME##_iter *iter = malloc(sizeof(struct SNAME##_iter)); \ \ if (!iter) \ return NULL; \ @@ -773,14 +770,14 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA return iter; \ } \ \ - void PFX##_iter_free(SNAME##_iter *iter) \ + void PFX##_iter_free(struct SNAME##_iter *iter) \ { \ free(iter); \ } \ \ - void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target) \ { \ - memset(iter, 0, sizeof(SNAME##_iter)); \ + memset(iter, 0, sizeof(struct SNAME##_iter)); \ \ iter->target = target; \ iter->start = true; \ @@ -801,17 +798,17 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA } \ } \ \ - bool PFX##_iter_start(SNAME##_iter *iter) \ + bool PFX##_iter_start(struct SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->start; \ } \ \ - bool PFX##_iter_end(SNAME##_iter *iter) \ + bool PFX##_iter_end(struct SNAME##_iter *iter) \ { \ return PFX##_empty(iter->target) || iter->end; \ } \ \ - void PFX##_iter_to_start(SNAME##_iter *iter) \ + void PFX##_iter_to_start(struct SNAME##_iter *iter) \ { \ if (!PFX##_empty(iter->target)) \ { \ @@ -822,7 +819,7 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA } \ } \ \ - void PFX##_iter_to_end(SNAME##_iter *iter) \ + void PFX##_iter_to_end(struct SNAME##_iter *iter) \ { \ if (!PFX##_empty(iter->target)) \ { \ @@ -833,7 +830,7 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA } \ } \ \ - bool PFX##_iter_next(SNAME##_iter *iter) \ + bool PFX##_iter_next(struct SNAME##_iter *iter) \ { \ if (iter->end) \ return false; \ @@ -873,7 +870,7 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA } \ } \ \ - bool PFX##_iter_prev(SNAME##_iter *iter) \ + bool PFX##_iter_prev(struct SNAME##_iter *iter) \ { \ if (iter->start) \ return false; \ @@ -915,7 +912,7 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA } \ \ /* Returns true only if the iterator moved */ \ - bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps) \ { \ if (iter->end) \ return false; \ @@ -938,7 +935,7 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA } \ \ /* Returns true only if the iterator moved */ \ - bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps) \ { \ if (iter->start) \ return false; \ @@ -961,7 +958,7 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA } \ \ /* Returns true only if the iterator was able to be positioned at the given index */ \ - bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index) \ { \ if (index >= PFX##_count(iter->target)) \ return false; \ @@ -974,7 +971,7 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA return true; \ } \ \ - V PFX##_iter_value(SNAME##_iter *iter) \ + V PFX##_iter_value(struct SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ return (V){0}; \ @@ -982,14 +979,14 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA return iter->cursor->value; \ } \ \ - size_t PFX##_iter_index(SNAME##_iter *iter) \ + size_t PFX##_iter_index(struct SNAME##_iter *iter) \ { \ return iter->index; \ } \ \ - static SNAME##_node *PFX##_impl_new_node(V element) \ + static struct SNAME##_node *PFX##_impl_new_node(V element) \ { \ - SNAME##_node *node = malloc(sizeof(SNAME##_node)); \ + struct SNAME##_node *node = malloc(sizeof(struct SNAME##_node)); \ \ if (!node) \ return NULL; \ @@ -1003,12 +1000,12 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA return node; \ } \ \ - static SNAME##_node *PFX##_impl_get_node(SNAME *_set_, V element) \ + static struct SNAME##_node *PFX##_impl_get_node(struct SNAME *_set_, V element) \ { \ if (PFX##_empty(_set_)) \ return NULL; \ \ - SNAME##_node *scan = _set_->root; \ + struct SNAME##_node *scan = _set_->root; \ \ while (scan != NULL) \ { \ @@ -1023,7 +1020,7 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA return NULL; \ } \ \ - static unsigned char PFX##_impl_h(SNAME##_node *node) \ + static unsigned char PFX##_impl_h(struct SNAME##_node *node) \ { \ if (node == NULL) \ return 0; \ @@ -1031,7 +1028,7 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA return node->height; \ } \ \ - static unsigned char PFX##_impl_hupdate(SNAME##_node *node) \ + static unsigned char PFX##_impl_hupdate(struct SNAME##_node *node) \ { \ if (node == NULL) \ return 0; \ @@ -1042,10 +1039,10 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA return 1 + (h_l > h_r ? h_l : h_r); \ } \ \ - static void PFX##_impl_rotate_right(SNAME##_node **Z) \ + static void PFX##_impl_rotate_right(struct SNAME##_node **Z) \ { \ - SNAME##_node *root = *Z; \ - SNAME##_node *new_root = root->left; \ + struct SNAME##_node *root = *Z; \ + struct SNAME##_node *new_root = root->left; \ \ if (root->parent != NULL) \ { \ @@ -1071,10 +1068,10 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA *Z = new_root; \ } \ \ - static void PFX##_impl_rotate_left(SNAME##_node **Z) \ + static void PFX##_impl_rotate_left(struct SNAME##_node **Z) \ { \ - SNAME##_node *root = *Z; \ - SNAME##_node *new_root = root->right; \ + struct SNAME##_node *root = *Z; \ + struct SNAME##_node *new_root = root->right; \ \ if (root->parent != NULL) \ { \ @@ -1100,9 +1097,9 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA *Z = new_root; \ } \ \ - static void PFX##_impl_rebalance(SNAME *_set_, SNAME##_node *node) \ + static void PFX##_impl_rebalance(struct SNAME *_set_, struct SNAME##_node *node) \ { \ - SNAME##_node *scan = node, *child = NULL; \ + struct SNAME##_node *scan = node, *child = NULL; \ \ int balance; \ bool is_root = false; \ @@ -1144,18 +1141,18 @@ static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMA } \ } \ \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_set_) \ + static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_set_) \ { \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ \ PFX##_iter_init(&iter, _set_); \ \ return iter; \ } \ \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_set_) \ + static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_set_) \ { \ - SNAME##_iter iter; \ + struct SNAME##_iter iter; \ \ PFX##_iter_init(&iter, _set_); \ PFX##_iter_to_end(&iter); \ diff --git a/src/utl/cmc_string.h b/src/utl/cmc_string.h index 1a14043..aa88f2b 100644 --- a/src/utl/cmc_string.h +++ b/src/utl/cmc_string.h @@ -18,9 +18,9 @@ static const size_t cmc_string_len = 200; -typedef struct cmc_string_s +struct cmc_string { char s[200]; -} cmc_string; +}; #endif /* CMC_STRING_H */ diff --git a/src/utl/foreach.h b/src/utl/foreach.h index 450fd4a..d62291a 100644 --- a/src/utl/foreach.h +++ b/src/utl/foreach.h @@ -11,22 +11,22 @@ #ifndef CMC_FOR_EACH_H #define CMC_FOR_EACH_H -#define CMC_FOR_EACH(PFX, SNAME, TARGET, BODY) \ - do \ - { \ - for (SNAME##_iter iter = (TARGET)->it_start(TARGET); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ - { \ - BODY; \ - } \ +#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 (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) #endif /* CMC_FOR_EACH_H */ diff --git a/src/utl/test.h b/src/utl/test.h index f25fd6a..f3cd1b0 100644 --- a/src/utl/test.h +++ b/src/utl/test.h @@ -103,7 +103,7 @@ static void cmc_test_log(const char *unit_name, const char *current_test, bool a const char *current_test = NULL; \ \ struct cmc_test_info tinfo = {0}; \ - cmc_timer timer = {0}; \ + struct cmc_timer timer = {0}; \ \ tinfo.verbose = VERBOSE; \ \ diff --git a/src/utl/timer.h b/src/utl/timer.h index eb6db99..95252f4 100644 --- a/src/utl/timer.h +++ b/src/utl/timer.h @@ -15,33 +15,33 @@ #include -typedef struct cmc_timer_s +struct cmc_timer { clock_t start; clock_t stop; double result; -} cmc_timer; +}; -#define cmc_timer_start(timer) \ - do \ - { \ - cmc_timer *t = &(timer); \ - t->start = clock(); \ - \ +#define cmc_timer_start(timer) \ + do \ + { \ + struct cmc_timer *t = &(timer); \ + t->start = clock(); \ + \ } while (0) -#define cmc_timer_stop(timer) \ - do \ - { \ - cmc_timer *t = &(timer); \ - t->stop = clock(); \ - \ +#define cmc_timer_stop(timer) \ + do \ + { \ + struct cmc_timer *t = &(timer); \ + t->stop = clock(); \ + \ } while (0) #define cmc_timer_calc(timer) \ do \ { \ - cmc_timer *t = &(timer); \ + struct cmc_timer *t = &(timer); \ t->result = (double)(t->stop - t->start) * 1000.0 / CLOCKS_PER_SEC; \ \ } while (0) diff --git a/tests/codecov/main.c b/tests/codecov/main.c index 8828fcf..e24edae 100644 --- a/tests/codecov/main.c +++ b/tests/codecov/main.c @@ -18,7 +18,7 @@ int main(void) { - cmc_timer timer; + struct cmc_timer timer; cmc_timer_start(timer); uintmax_t failed = 0; diff --git a/tests/codecov/src/bidimap.c b/tests/codecov/src/bidimap.c index fe5cce2..8bf45c3 100644 --- a/tests/codecov/src/bidimap.c +++ b/tests/codecov/src/bidimap.c @@ -52,7 +52,7 @@ size_t bm_capacity(bidimap *_map_); double bm_load(bidimap *_map_); bidimap *bm_copy_of(bidimap *_map_, size_t (*key_copy_func)(size_t), size_t (*value_copy_func)(size_t)); _Bool bm_equals(bidimap *_map1_, bidimap *_map2_); -cmc_string bm_to_string(bidimap *_map_); +struct cmc_string bm_to_string(bidimap *_map_); bidimap_iter *bm_iter_new(bidimap *target); void bm_iter_free(bidimap_iter *iter); void bm_iter_init(bidimap_iter *iter, bidimap *target); @@ -201,9 +201,9 @@ size_t bm_capacity(bidimap *_map_) { return _map_->capacity; } double bm_load(bidimap *_map_) { return _map_->load; } bidimap *bm_copy_of(bidimap *_map_, size_t (*key_copy_func)(size_t), size_t (*value_copy_func)(size_t)) { return ((void *)0); } _Bool bm_equals(bidimap *_map1_, bidimap *_map2_) { return 0; } -cmc_string bm_to_string(bidimap *_map_) +struct cmc_string bm_to_string(bidimap *_map_) { - cmc_string str; + struct cmc_string str; bidimap *m_ = _map_; const char *name = "bidimap"; snprintf(str.s, cmc_string_len, cmc_string_fmt_bidimap, name, m_, m_->key_buffer, m_->val_buffer, m_->capacity, m_->count, m_->load, m_->key_cmp, m_->val_cmp, m_->key_hash, m_->val_hash); diff --git a/tests/codecov/src/deque.c b/tests/codecov/src/deque.c index e70d835..5071e28 100644 --- a/tests/codecov/src/deque.c +++ b/tests/codecov/src/deque.c @@ -37,7 +37,7 @@ size_t d_capacity(deque *_deque_); _Bool d_resize(deque *_deque_, size_t capacity); deque *d_copy_of(deque *_deque_, size_t (*copy_func)(size_t)); _Bool d_equals(deque *_deque1_, deque *_deque2_, int (*comparator)(size_t, size_t)); -cmc_string d_to_string(deque *_deque_); +struct cmc_string d_to_string(deque *_deque_); deque_iter *d_iter_new(deque *target); void d_iter_free(deque_iter *iter); void d_iter_init(deque_iter *iter, deque *target); @@ -232,9 +232,9 @@ _Bool d_equals(deque *_deque1_, deque *_deque2_, int (*comparator)(size_t, size_ } return 1; } -cmc_string d_to_string(deque *_deque_) +struct cmc_string d_to_string(deque *_deque_) { - cmc_string str; + struct cmc_string str; deque *d_ = _deque_; const char *name = "deque"; snprintf(str.s, cmc_string_len, cmc_string_fmt_deque, name, d_, d_->buffer, d_->capacity, d_->count, d_->front, d_->back); diff --git a/tests/codecov/src/hashmap.c b/tests/codecov/src/hashmap.c index cc41969..c918e26 100644 --- a/tests/codecov/src/hashmap.c +++ b/tests/codecov/src/hashmap.c @@ -18,7 +18,7 @@ typedef struct hashmap_entry_s size_t key; size_t value; size_t dist; - enum cmc_entry_state_e state; + enum cmc_entry_state state; } hashmap_entry, *hashmap_entry_ptr; typedef struct hashmap_iter_s { @@ -49,7 +49,7 @@ double hm_load(hashmap *_map_); _Bool hm_resize(hashmap *_map_, size_t capacity); hashmap *hm_copy_of(hashmap *_map_, size_t (*key_copy_func)(size_t), size_t (*value_copy_func)(size_t)); _Bool hm_equals(hashmap *_map1_, hashmap *_map2_, int (*value_comparator)(size_t, size_t)); -cmc_string hm_to_string(hashmap *_map_); +struct cmc_string hm_to_string(hashmap *_map_); hashmap_iter *hm_iter_new(hashmap *target); void hm_iter_free(hashmap_iter *iter); void hm_iter_init(hashmap_iter *iter, hashmap *target); @@ -363,9 +363,9 @@ _Bool hm_equals(hashmap *_map1_, hashmap *_map2_, int (*value_comparator)(size_t } return 1; } -cmc_string hm_to_string(hashmap *_map_) +struct cmc_string hm_to_string(hashmap *_map_) { - cmc_string str; + struct cmc_string str; hashmap *m_ = _map_; const char *name = "hashmap"; snprintf(str.s, cmc_string_len, cmc_string_fmt_hashmap, name, m_, m_->buffer, m_->capacity, m_->count, m_->load, m_->cmp, m_->hash); diff --git a/tests/codecov/src/hashset.c b/tests/codecov/src/hashset.c index 6c9f80d..eab0c41 100644 --- a/tests/codecov/src/hashset.c +++ b/tests/codecov/src/hashset.c @@ -17,7 +17,7 @@ typedef struct hashset_entry_s { size_t value; size_t dist; - enum cmc_entry_state_e state; + enum cmc_entry_state state; } hashset_entry, *hashset_entry_ptr; typedef struct hashset_iter_s { @@ -45,7 +45,7 @@ double hs_load(hashset *_set_); _Bool hs_resize(hashset *_set_, size_t capacity); hashset *hs_copy_of(hashset *_set_, size_t (*copy_func)(size_t)); _Bool hs_equals(hashset *_set1_, hashset *_set2_); -cmc_string hs_to_string(hashset *_set_); +struct cmc_string hs_to_string(hashset *_set_); hashset *hs_union(hashset *_set1_, hashset *_set2_); hashset *hs_intersection(hashset *_set1_, hashset *_set2_); hashset *hs_difference(hashset *_set1_, hashset *_set2_); @@ -304,9 +304,9 @@ _Bool hs_equals(hashset *_set1_, hashset *_set2_) } return 1; } -cmc_string hs_to_string(hashset *_set_) +struct cmc_string hs_to_string(hashset *_set_) { - cmc_string str; + struct cmc_string str; hashset *s_ = _set_; const char *name = "hashset"; snprintf(str.s, cmc_string_len, cmc_string_fmt_hashset, name, s_, s_->buffer, s_->capacity, s_->count, s_->load, s_->cmp, s_->hash); diff --git a/tests/codecov/src/heap.c b/tests/codecov/src/heap.c index fb385f0..3f0d824 100644 --- a/tests/codecov/src/heap.c +++ b/tests/codecov/src/heap.c @@ -7,7 +7,7 @@ typedef struct heap_s size_t *buffer; size_t capacity; size_t count; - enum cmc_heap_order_e HO; + enum cmc_heap_order HO; int (*cmp)(size_t, size_t); struct heap_iter_s (*it_start)(struct heap_s *); struct heap_iter_s (*it_end)(struct heap_s *); @@ -19,7 +19,7 @@ typedef struct heap_iter_s _Bool start; _Bool end; } heap_iter, *heap_iter_ptr; -heap *h_new(size_t capacity, cmc_heap_order HO, int (*compare)(size_t, size_t)); +heap *h_new(size_t capacity, enum cmc_heap_order HO, int (*compare)(size_t, size_t)); void h_clear(heap *_heap_, void (*deallocator)(size_t)); void h_free(heap *_heap_, void (*deallocator)(size_t)); _Bool h_insert(heap *_heap_, size_t element); @@ -33,7 +33,7 @@ size_t h_capacity(heap *_heap_); _Bool h_resize(heap *_heap_, size_t capacity); heap *h_copy_of(heap *_heap_, size_t (*copy_func)(size_t)); _Bool h_equals(heap *_heap1_, heap *_heap2_); -cmc_string h_to_string(heap *_heap_); +struct cmc_string h_to_string(heap *_heap_); heap_iter *h_iter_new(heap *target); void h_iter_free(heap_iter *iter); void h_iter_init(heap_iter *iter, heap *target); @@ -52,7 +52,7 @@ static _Bool h_impl_float_up(heap *_heap_, size_t index); static _Bool h_impl_float_down(heap *_heap_, size_t index); static heap_iter h_impl_it_start(heap *_heap_); static heap_iter h_impl_it_end(heap *_heap_); -heap *h_new(size_t capacity, cmc_heap_order HO, int (*compare)(size_t, size_t)) +heap *h_new(size_t capacity, enum cmc_heap_order HO, int (*compare)(size_t, size_t)) { if (capacity < 1) return ((void *)0); @@ -187,9 +187,9 @@ _Bool h_equals(heap *_heap1_, heap *_heap2_) } return 1; } -cmc_string h_to_string(heap *_heap_) +struct cmc_string h_to_string(heap *_heap_) { - cmc_string str; + struct cmc_string str; heap *h_ = _heap_; const char *name = "heap"; const char *t = h_->HO == 1 ? "MaxHeap" : "MinHeap"; diff --git a/tests/codecov/src/intervalheap.c b/tests/codecov/src/intervalheap.c index 9186b2a..fc1f995 100644 --- a/tests/codecov/src/intervalheap.c +++ b/tests/codecov/src/intervalheap.c @@ -41,7 +41,7 @@ size_t ih_capacity(intervalheap *_heap_); _Bool ih_resize(intervalheap *_heap_, size_t capacity); intervalheap *ih_copy_of(intervalheap *_set_, size_t (*copy_func)(size_t)); _Bool ih_equals(intervalheap *_heap1_, intervalheap *_heap2_); -cmc_string ih_to_string(intervalheap *_heap_); +struct cmc_string ih_to_string(intervalheap *_heap_); intervalheap_iter *ih_iter_new(intervalheap *target); void ih_iter_free(intervalheap_iter *iter); void ih_iter_init(intervalheap_iter *iter, intervalheap *target); @@ -323,9 +323,9 @@ _Bool ih_equals(intervalheap *_heap1_, intervalheap *_heap2_) } return 0; } -cmc_string ih_to_string(intervalheap *_heap_) +struct cmc_string ih_to_string(intervalheap *_heap_) { - cmc_string str; + struct cmc_string str; intervalheap *h_ = _heap_; const char *name = "intervalheap"; snprintf(str.s, cmc_string_len, cmc_string_fmt_intervalheap, name, h_, h_->buffer, h_->capacity, h_->size, h_->count, h_->cmp); diff --git a/tests/codecov/src/linkedlist.c b/tests/codecov/src/linkedlist.c index cf52034..bbc61f9 100644 --- a/tests/codecov/src/linkedlist.c +++ b/tests/codecov/src/linkedlist.c @@ -42,7 +42,7 @@ _Bool ll_empty(linkedlist *_list_); size_t ll_count(linkedlist *_list_); linkedlist *ll_copy_of(linkedlist *_list_, size_t (*copy_func)(size_t)); _Bool ll_equals(linkedlist *_list1_, linkedlist *_list2_, int (*comparator)(size_t, size_t)); -cmc_string ll_to_string(linkedlist *_list_); +struct cmc_string ll_to_string(linkedlist *_list_); linkedlist_node *ll_new_node(size_t element); void ll_free_node(linkedlist_node *_node_); linkedlist_node *ll_head(linkedlist *_list_); @@ -308,9 +308,9 @@ _Bool ll_equals(linkedlist *_list1_, linkedlist *_list2_, int (*comparator)(size } return 1; } -cmc_string ll_to_string(linkedlist *_list_) +struct cmc_string ll_to_string(linkedlist *_list_) { - cmc_string str; + struct cmc_string str; linkedlist *l_ = _list_; const char *name = "linkedlist"; snprintf(str.s, cmc_string_len, cmc_string_fmt_linkedlist, name, l_, l_->count, l_->head, l_->tail); diff --git a/tests/codecov/src/list.c b/tests/codecov/src/list.c index d8d9831..d70902f 100644 --- a/tests/codecov/src/list.c +++ b/tests/codecov/src/list.c @@ -46,7 +46,7 @@ size_t l_capacity(list *_list_); _Bool l_resize(list *_list_, size_t capacity); list *l_copy_of(list *_list_, size_t (*copy_func)(size_t)); _Bool l_equals(list *_list1_, list *_list2_, int (*comparator)(size_t, size_t)); -cmc_string l_to_string(list *_list_); +struct cmc_string l_to_string(list *_list_); list_iter *l_iter_new(list *target); void l_iter_free(list_iter *iter); void l_iter_init(list_iter *iter, list *target); @@ -349,9 +349,9 @@ _Bool l_equals(list *_list1_, list *_list2_, int (*comparator)(size_t, size_t)) } return 0; } -cmc_string l_to_string(list *_list_) +struct cmc_string l_to_string(list *_list_) { - cmc_string str; + struct cmc_string str; list *l_ = _list_; const char *name = "list"; snprintf(str.s, cmc_string_len, cmc_string_fmt_list, name, l_, l_->buffer, l_->capacity, l_->count); diff --git a/tests/codecov/src/multimap.c b/tests/codecov/src/multimap.c index 9f598b5..583216d 100644 --- a/tests/codecov/src/multimap.c +++ b/tests/codecov/src/multimap.c @@ -53,7 +53,7 @@ double mm_load(multimap *_map_); _Bool mm_resize(multimap *_map_, size_t capacity); multimap *mm_copy_of(multimap *_map_, size_t (*key_copy_func)(size_t), size_t (*value_copy_func)(size_t)); _Bool mm_equals(multimap *_map1_, multimap *_map2_, _Bool ignore_key_count); -cmc_string mm_to_string(multimap *_map_); +struct cmc_string mm_to_string(multimap *_map_); multimap_iter *mm_iter_new(multimap *target); void mm_iter_free(multimap_iter *iter); void mm_iter_init(multimap_iter *iter, multimap *target); @@ -483,9 +483,9 @@ _Bool mm_equals(multimap *_map1_, multimap *_map2_, _Bool ignore_key_count) } return 1; } -cmc_string mm_to_string(multimap *_map_) +struct cmc_string mm_to_string(multimap *_map_) { - cmc_string str; + struct cmc_string str; multimap *m_ = _map_; const char *name = "multimap"; snprintf(str.s, cmc_string_len, cmc_string_fmt_multimap, name, m_, m_->buffer, m_->capacity, m_->count, m_->load, m_->cmp, m_->hash); diff --git a/tests/codecov/src/multiset.c b/tests/codecov/src/multiset.c index 6961997..9dc8fa5 100644 --- a/tests/codecov/src/multiset.c +++ b/tests/codecov/src/multiset.c @@ -19,7 +19,7 @@ typedef struct multiset_entry_s size_t value; size_t multiplicity; size_t dist; - enum cmc_entry_state_e state; + enum cmc_entry_state state; } multiset_entry, *multiset_entry_ptr; typedef struct multiset_iter_s { @@ -52,7 +52,7 @@ double ms_load(multiset *_set_); _Bool ms_resize(multiset *_set_, size_t capacity); multiset *ms_copy_of(multiset *_set_, size_t (*copy_func)(size_t)); _Bool ms_equals(multiset *_set1_, multiset *_set2_, _Bool ignore_multiplicity); -cmc_string ms_to_string(multiset *_set_); +struct cmc_string ms_to_string(multiset *_set_); multiset *ms_union(multiset *_set1_, multiset *_set2_); multiset *ms_intersection(multiset *_set1_, multiset *_set2_); multiset *ms_difference(multiset *_set1_, multiset *_set2_); @@ -344,9 +344,9 @@ _Bool ms_equals(multiset *_set1_, multiset *_set2_, _Bool ignore_multiplicity) } return 1; } -cmc_string ms_to_string(multiset *_set_) +struct cmc_string ms_to_string(multiset *_set_) { - cmc_string str; + struct cmc_string str; multiset *s_ = _set_; const char *name = "multiset"; snprintf(str.s, cmc_string_len, cmc_string_fmt_multiset, name, s_, s_->buffer, s_->capacity, s_->count, s_->cardinality, s_->load, s_->cmp, s_->hash); diff --git a/tests/codecov/src/queue.c b/tests/codecov/src/queue.c index ca68d2d..d3df74b 100644 --- a/tests/codecov/src/queue.c +++ b/tests/codecov/src/queue.c @@ -34,7 +34,7 @@ size_t q_capacity(queue *_queue_); _Bool q_resize(queue *_queue_, size_t capacity); queue *q_copy_of(queue *_queue_, size_t (*copy_func)(size_t)); _Bool q_equals(queue *_queue1_, queue *_queue2_, int (*comparator)(size_t, size_t)); -cmc_string q_to_string(queue *_queue_); +struct cmc_string q_to_string(queue *_queue_); queue_iter *q_iter_new(queue *target); void q_iter_free(queue_iter *iter); void q_iter_init(queue_iter *iter, queue *target); @@ -202,9 +202,9 @@ _Bool q_equals(queue *_queue1_, queue *_queue2_, int (*comparator)(size_t, size_ } return 1; } -cmc_string q_to_string(queue *_queue_) +struct cmc_string q_to_string(queue *_queue_) { - cmc_string str; + struct cmc_string str; queue *q_ = _queue_; const char *name = "queue"; snprintf(str.s, cmc_string_len, cmc_string_fmt_queue, name, q_, q_->buffer, q_->capacity, q_->count, q_->front, q_->back); diff --git a/tests/codecov/src/sortedlist.c b/tests/codecov/src/sortedlist.c index f0bb940..ff610f5 100644 --- a/tests/codecov/src/sortedlist.c +++ b/tests/codecov/src/sortedlist.c @@ -37,7 +37,7 @@ _Bool sl_resize(sortedlist *_list_, size_t capacity); void sl_sort(sortedlist *_list_); sortedlist *sl_copy_of(sortedlist *_list_, size_t (*copy_func)(size_t)); _Bool sl_equals(sortedlist *_list1_, sortedlist *_list2_); -cmc_string sl_to_string(sortedlist *_list_); +struct cmc_string sl_to_string(sortedlist *_list_); sortedlist_iter *sl_iter_new(sortedlist *target); void sl_iter_free(sortedlist_iter *iter); void sl_iter_init(sortedlist_iter *iter, sortedlist *target); @@ -208,9 +208,9 @@ _Bool sl_equals(sortedlist *_list1_, sortedlist *_list2_) } return 0; } -cmc_string sl_to_string(sortedlist *_list_) +struct cmc_string sl_to_string(sortedlist *_list_) { - cmc_string str; + struct cmc_string str; sortedlist *l_ = _list_; const char *name = "sortedlist"; snprintf(str.s, cmc_string_len, cmc_string_fmt_sortedlist, name, l_, l_->buffer, l_->capacity, l_->count, l_->is_sorted ? "true" : "false", l_->cmp); diff --git a/tests/codecov/src/stack.c b/tests/codecov/src/stack.c index 3ffc109..762f5dc 100644 --- a/tests/codecov/src/stack.c +++ b/tests/codecov/src/stack.c @@ -31,7 +31,7 @@ size_t s_capacity(stack *_stack_); _Bool s_resize(stack *_stack_, size_t capacity); stack *s_copy_of(stack *_stack_, size_t (*copy_func)(size_t)); _Bool s_equals(stack *_stack1_, stack *_stack2_, int (*comparator)(size_t, size_t)); -cmc_string s_to_string(stack *_stack_); +struct cmc_string s_to_string(stack *_stack_); stack_iter *s_iter_new(stack *target); void s_iter_free(stack_iter *iter); void s_iter_init(stack_iter *iter, stack *target); @@ -164,9 +164,9 @@ _Bool s_equals(stack *_stack1_, stack *_stack2_, int (*comparator)(size_t, size_ } return 1; } -cmc_string s_to_string(stack *_stack_) +struct cmc_string s_to_string(stack *_stack_) { - cmc_string str; + struct cmc_string str; stack *s_ = _stack_; const char *name = "stack"; snprintf(str.s, cmc_string_len, cmc_string_fmt_stack, name, s_, s_->buffer, s_->capacity, s_->count); diff --git a/tests/codecov/src/treemap.c b/tests/codecov/src/treemap.c index 3e44c68..8835ec2 100644 --- a/tests/codecov/src/treemap.c +++ b/tests/codecov/src/treemap.c @@ -44,7 +44,7 @@ _Bool tm_empty(treemap *_map_); size_t tm_count(treemap *_map_); treemap *tm_copy_of(treemap *_map_, size_t (*key_copy_func)(size_t), size_t (*value_copy_func)(size_t)); _Bool tm_equals(treemap *_map1_, treemap *_map2_, int (*value_comparator)(size_t, size_t)); -cmc_string tm_to_string(treemap *_map_); +struct cmc_string tm_to_string(treemap *_map_); treemap_iter *tm_iter_new(treemap *target); void tm_iter_free(treemap_iter *iter); void tm_iter_init(treemap_iter *iter, treemap *target); @@ -387,9 +387,9 @@ _Bool tm_equals(treemap *_map1_, treemap *_map2_, int (*value_comparator)(size_t } return 1; } -cmc_string tm_to_string(treemap *_map_) +struct cmc_string tm_to_string(treemap *_map_) { - cmc_string str; + struct cmc_string str; treemap *m_ = _map_; const char *name = "treemap"; snprintf(str.s, cmc_string_len, cmc_string_fmt_treemap, name, m_, m_->root, m_->count, m_->cmp); diff --git a/tests/codecov/src/treeset.c b/tests/codecov/src/treeset.c index 1730619..22f1503 100644 --- a/tests/codecov/src/treeset.c +++ b/tests/codecov/src/treeset.c @@ -40,7 +40,7 @@ _Bool ts_empty(treeset *_set_); size_t ts_count(treeset *_set_); treeset *ts_copy_of(treeset *_set_, size_t (*copy_func)(size_t)); _Bool ts_equals(treeset *_set1_, treeset *_set2_); -cmc_string ts_to_string(treeset *_set_); +struct cmc_string ts_to_string(treeset *_set_); treeset *ts_union(treeset *_set1_, treeset *_set2_); treeset *ts_intersection(treeset *_set1_, treeset *_set2_); treeset *ts_difference(treeset *_set1_, treeset *_set2_); @@ -357,9 +357,9 @@ _Bool ts_equals(treeset *_set1_, treeset *_set2_) } return 1; } -cmc_string ts_to_string(treeset *_set_) +struct cmc_string ts_to_string(treeset *_set_) { - cmc_string str; + struct cmc_string str; treeset *s_ = _set_; const char *name = "treeset"; snprintf(str.s, cmc_string_len, cmc_string_fmt_treeset, name, s_, s_->root, s_->count, s_->cmp); diff --git a/tests/contains.c b/tests/contains.c index 4a40a3e..39753af 100644 --- a/tests/contains.c +++ b/tests/contains.c @@ -37,20 +37,19 @@ CMC_COLLECTION_GENERATE(MULTISET, ms, mset, , int) int main(void) { - list *l = l_new(1000); - stack *s = s_new(1000); - queue *q = q_new(1000); - deque *d = d_new(1000); - linked *ll = ll_new(); - heap *h = h_new(1000, cmc_max_heap, intcmp); - tset *ts = ts_new(intcmp); - tmap *tm = tm_new(intcmp); - hset *hs = hs_new(1000, 0.6, intcmp, inthash); - hmap *hm = hm_new(1000, 0.6, intcmp, inthash); - - iheap *ih = ih_new(1000, intcmp); - mmap *mm = mm_new(1000, 0.8, intcmp, inthash); - mset *ms = ms_new(1000, 0.6, intcmp, inthash); + struct list *l = l_new(1000); + struct stack *s = s_new(1000); + struct queue *q = q_new(1000); + struct deque *d = d_new(1000); + struct linked *ll = ll_new(); + struct heap *h = h_new(1000, cmc_max_heap, intcmp); + struct tset *ts = ts_new(intcmp); + struct tmap *tm = tm_new(intcmp); + struct hset *hs = hs_new(1000, 0.6, intcmp, inthash); + struct hmap *hm = hm_new(1000, 0.6, intcmp, inthash); + struct iheap *ih = ih_new(1000, intcmp); + struct mmap *mm = mm_new(1000, 0.8, intcmp, inthash); + struct mset *ms = ms_new(1000, 0.6, intcmp, inthash); bool a[13] = {false, false, false, false, false, false, false, false, false, false, false, false, false}, b[13] = {false, false, false, false, false, false, false, false, false, false, false, false, false}, diff --git a/tests/foreach.c b/tests/foreach.c index 02db0a4..b4da307 100644 --- a/tests/foreach.c +++ b/tests/foreach.c @@ -37,20 +37,19 @@ CMC_COLLECTION_GENERATE(MULTISET, ms, mset, , int) int main(void) { - list *l = l_new(1000); - stack *s = s_new(1000); - queue *q = q_new(1000); - deque *d = d_new(1000); - linked *ll = ll_new(); - heap *h = h_new(1000, cmc_max_heap, intcmp); - tset *ts = ts_new(intcmp); - tmap *tm = tm_new(intcmp); - hset *hs = hs_new(1000, 0.6, intcmp, inthash); - hmap *hm = hm_new(1000, 0.6, intcmp, inthash); - - iheap *ih = ih_new(1000, intcmp); - mmap *mm = mm_new(1000, 0.8, intcmp, inthash); - mset *ms = ms_new(1000, 0.6, intcmp, inthash); + struct list *l = l_new(1000); + struct stack *s = s_new(1000); + struct queue *q = q_new(1000); + struct deque *d = d_new(1000); + struct linked *ll = ll_new(); + struct heap *h = h_new(1000, cmc_max_heap, intcmp); + struct tset *ts = ts_new(intcmp); + struct tmap *tm = tm_new(intcmp); + struct hset *hs = hs_new(1000, 0.6, intcmp, inthash); + struct hmap *hm = hm_new(1000, 0.6, intcmp, inthash); + struct iheap *ih = ih_new(1000, intcmp); + struct mmap *mm = mm_new(1000, 0.8, intcmp, inthash); + struct mset *ms = ms_new(1000, 0.6, intcmp, inthash); bool p = true; diff --git a/tests/iterators.c b/tests/iterators.c index d60282d..97e8511 100644 --- a/tests/iterators.c +++ b/tests/iterators.c @@ -39,13 +39,13 @@ CMC_COLLECTION_GENERATE(MULTISET, ms, mset, /* K */, int) int sum1 = 0; \ double sum2 = 0.0; \ \ - sname *coll = initfunc; \ + struct sname *coll = initfunc; \ for (int i = 0; i < 10; i++) \ { \ insertbody; \ } \ \ - sname##_iter iter; \ + struct sname##_iter iter; \ PFX##_iter_init(&iter, coll); \ \ for (int j = 0; j < 4; j++) \ diff --git a/tests/main/main.c b/tests/main/main.c index 8828fcf..e24edae 100644 --- a/tests/main/main.c +++ b/tests/main/main.c @@ -18,7 +18,7 @@ int main(void) { - cmc_timer timer; + struct cmc_timer timer; cmc_timer_start(timer); uintmax_t failed = 0; diff --git a/tests/main/unt/bidimap.c b/tests/main/unt/bidimap.c index 7b086d8..05ef3bc 100644 --- a/tests/main/unt/bidimap.c +++ b/tests/main/unt/bidimap.c @@ -9,7 +9,7 @@ CMC_GENERATE_BIDIMAP(bm, bidimap, size_t, size_t) CMC_CREATE_UNIT(bidimap_test, true, { CMC_CREATE_TEST(new, { - bidimap *map = bm_new(100, 0.6, cmp, hash, cmp, hash); + struct bidimap *map = bm_new(100, 0.6, cmp, hash, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -17,7 +17,7 @@ CMC_CREATE_UNIT(bidimap_test, true, { }); CMC_CREATE_TEST(clear[count], { - bidimap *map = bm_new(100, 0.6, cmp, hash, cmp, hash); + struct bidimap *map = bm_new(100, 0.6, cmp, hash, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -34,7 +34,7 @@ CMC_CREATE_UNIT(bidimap_test, true, { }); CMC_CREATE_TEST(buffer_growth[capacity = 1], { - bidimap *map = bm_new(1, 0.7, cmp, hash, cmp, hash); + struct bidimap *map = bm_new(1, 0.7, cmp, hash, cmp, hash); for (size_t i = 1; i <= 10000; i++) cmc_assert(bm_insert(map, i, i)); @@ -55,12 +55,12 @@ CMC_CREATE_UNIT(bidimap_test, true, { }); CMC_CREATE_TEST(copy_of, { - bidimap *map1 = bm_new(100, 0.7, cmp, hash, cmp, hash); + struct bidimap *map1 = bm_new(100, 0.7, cmp, hash, cmp, hash); for (size_t i = 0; i < 100; i++) cmc_assert(bm_insert(map1, i, i)); - bidimap *map2 = bm_copy_of(map1, NULL, NULL); + struct bidimap *map2 = bm_copy_of(map1, NULL, NULL); cmc_assert_not_equals(ptr, NULL, map2); cmc_assert_equals(size_t, bm_count(map1), bm_count(map2)); @@ -76,8 +76,8 @@ CMC_CREATE_UNIT(bidimap_test, true, { }); CMC_CREATE_TEST(equals, { - bidimap *map1 = bm_new(100, 0.7, cmp, hash, cmp, hash); - bidimap *map2 = bm_new(1000, 0.9, cmp, hash, cmp, hash); + struct bidimap *map1 = bm_new(100, 0.7, cmp, hash, cmp, hash); + struct bidimap *map2 = bm_new(1000, 0.9, cmp, hash, cmp, hash); for (size_t i = 0; i < 100; i++) { @@ -100,12 +100,12 @@ CMC_CREATE_UNIT(bidimap_test, true, { }); CMC_CREATE_TEST(equals[from copy], { - bidimap *map1 = bm_new(100, 0.7, cmp, hash, cmp, hash); + struct bidimap *map1 = bm_new(100, 0.7, cmp, hash, cmp, hash); for (size_t i = 0; i < 100; i++) cmc_assert(bm_insert(map1, i, i)); - bidimap *map2 = bm_copy_of(map1, NULL, NULL); + struct bidimap *map2 = bm_copy_of(map1, NULL, NULL); cmc_assert_not_equals(ptr, NULL, map2); diff --git a/tests/main/unt/deque.c b/tests/main/unt/deque.c index dfc386d..950b3b7 100644 --- a/tests/main/unt/deque.c +++ b/tests/main/unt/deque.c @@ -9,7 +9,7 @@ CMC_GENERATE_DEQUE(d, deque, size_t) CMC_CREATE_UNIT(deque_test, true, { CMC_CREATE_TEST(new, { - deque *d = d_new(1000000); + struct deque *d = d_new(1000000); cmc_assert_not_equals(ptr, NULL, d); cmc_assert_not_equals(ptr, NULL, d->buffer); @@ -20,19 +20,19 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(new[capacity = 0], { - deque *d = d_new(0); + struct deque *d = d_new(0); cmc_assert_equals(ptr, NULL, d); }); CMC_CREATE_TEST(new[capacity = UINT64_MAX], { - deque *d = d_new(UINT64_MAX); + struct deque *d = d_new(UINT64_MAX); cmc_assert_equals(ptr, NULL, d); }); CMC_CREATE_TEST(clear[count capacity], { - deque *d = d_new(100); + struct deque *d = d_new(100); cmc_assert_not_equals(ptr, NULL, d); @@ -50,7 +50,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(buffer_growth[capacity = 1], { - deque *d = d_new(1); + struct deque *d = d_new(1); cmc_assert_not_equals(ptr, NULL, d); @@ -64,7 +64,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(buffer_growth[item preservation], { - deque *d = d_new(100); + struct deque *d = d_new(100); cmc_assert_not_equals(ptr, NULL, d); @@ -87,7 +87,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(push_front[count capacity], { - deque *d = d_new(100); + struct deque *d = d_new(100); cmc_assert_not_equals(ptr, NULL, d); @@ -101,7 +101,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(push_front[item preservation], { - deque *d = d_new(100); + struct deque *d = d_new(100); cmc_assert_not_equals(ptr, NULL, d); @@ -121,7 +121,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(push_back[count capacity], { - deque *d = d_new(100); + struct deque *d = d_new(100); cmc_assert_not_equals(ptr, NULL, d); @@ -135,7 +135,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(push_back[item preservation], { - deque *d = d_new(100); + struct deque *d = d_new(100); cmc_assert_not_equals(ptr, NULL, d); @@ -155,7 +155,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(pop_front[count capacity], { - deque *d = d_new(100); + struct deque *d = d_new(100); cmc_assert_not_equals(ptr, NULL, d); @@ -173,7 +173,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(pop_front[item preservation], { - deque *d = d_new(100); + struct deque *d = d_new(100); cmc_assert_not_equals(ptr, NULL, d); @@ -196,7 +196,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(pop_back[count capacity], { - deque *d = d_new(100); + struct deque *d = d_new(100); cmc_assert_not_equals(ptr, NULL, d); @@ -214,7 +214,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(pop_back[item preservation], { - deque *d = d_new(100); + struct deque *d = d_new(100); cmc_assert_not_equals(ptr, NULL, d); @@ -237,7 +237,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(Mixed IO, { - deque *d = d_new(100); + struct deque *d = d_new(100); cmc_assert_not_equals(ptr, NULL, d); @@ -301,7 +301,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(front[count = 0], { - deque *d = d_new(100); + struct deque *d = d_new(100); cmc_assert_not_equals(ptr, NULL, d); @@ -313,7 +313,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(front[sum], { - deque *d = d_new(100); + struct deque *d = d_new(100); cmc_assert_not_equals(ptr, NULL, d); @@ -342,7 +342,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(back[count = 0], { - deque *d = d_new(100); + struct deque *d = d_new(100); cmc_assert_not_equals(ptr, NULL, d); @@ -354,7 +354,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(back[sum], { - deque *d = d_new(100); + struct deque *d = d_new(100); cmc_assert_not_equals(ptr, NULL, d); @@ -383,7 +383,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(contains, { - deque *d = d_new(100); + struct deque *d = d_new(100); cmc_assert_not_equals(ptr, NULL, d); @@ -405,7 +405,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(contains[count = 0], { - deque *d = d_new(100); + struct deque *d = d_new(100); cmc_assert_not_equals(ptr, NULL, d); @@ -415,7 +415,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(contains[count = 1], { - deque *d = d_new(100); + struct deque *d = d_new(100); cmc_assert_not_equals(ptr, NULL, d); @@ -436,7 +436,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(empty, { - deque *d = d_new(100); + struct deque *d = d_new(100); cmc_assert_not_equals(ptr, NULL, d); @@ -450,7 +450,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(full, { - deque *d = d_new(100); + struct deque *d = d_new(100); cmc_assert_not_equals(ptr, NULL, d); @@ -465,7 +465,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(count, { - deque *d = d_new(100); + struct deque *d = d_new(100); cmc_assert_not_equals(ptr, NULL, d); @@ -480,7 +480,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(capacity, { - deque *d = d_new(100); + struct deque *d = d_new(100); cmc_assert_not_equals(ptr, NULL, d); @@ -490,7 +490,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(resize, { - deque *d = d_new(100); + struct deque *d = d_new(100); cmc_assert_not_equals(ptr, NULL, d); @@ -510,7 +510,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(resize[item preservation], { - deque *d = d_new(100); + struct deque *d = d_new(100); cmc_assert_not_equals(ptr, NULL, d); @@ -537,7 +537,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(copy_of, { - deque *d1 = d_new(100); + struct deque *d1 = d_new(100); cmc_assert_not_equals(ptr, NULL, d1); @@ -549,7 +549,7 @@ CMC_CREATE_UNIT(deque_test, true, { cmc_assert(d_push_front(d1, i)); } - deque *d2 = d_copy_of(d1, NULL); + struct deque *d2 = d_copy_of(d1, NULL); cmc_assert_not_equals(ptr, NULL, d2); cmc_assert_equals(size_t, d_count(d1), d_count(d2)); @@ -567,8 +567,8 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(equals, { - deque *d1 = d_new(100); - deque *d2 = d_new(100); + struct deque *d1 = d_new(100); + struct deque *d2 = d_new(100); cmc_assert_not_equals(ptr, NULL, d1); cmc_assert_not_equals(ptr, NULL, d2); @@ -594,7 +594,7 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(equals[from copy], { - deque *d1 = d_new(100); + struct deque *d1 = d_new(100); cmc_assert_not_equals(ptr, NULL, d1); @@ -606,7 +606,7 @@ CMC_CREATE_UNIT(deque_test, true, { cmc_assert(d_push_front(d1, i)); } - deque *d2 = d_copy_of(d1, NULL); + struct deque *d2 = d_copy_of(d1, NULL); cmc_assert_not_equals(ptr, NULL, d2); @@ -617,11 +617,11 @@ CMC_CREATE_UNIT(deque_test, true, { }); CMC_CREATE_TEST(equals[count = 0], { - deque *d1 = d_new(100); + struct deque *d1 = d_new(100); cmc_assert_not_equals(ptr, NULL, d1); - deque *d2 = d_copy_of(d1, NULL); + struct deque *d2 = d_copy_of(d1, NULL); cmc_assert_not_equals(ptr, NULL, d2); diff --git a/tests/main/unt/hashmap.c b/tests/main/unt/hashmap.c index 3f06d7c..b072ebd 100644 --- a/tests/main/unt/hashmap.c +++ b/tests/main/unt/hashmap.c @@ -9,7 +9,7 @@ CMC_GENERATE_HASHMAP(hm, hashmap, size_t, size_t) CMC_CREATE_UNIT(hashmap_test, true, { CMC_CREATE_TEST(new, { - hashmap *map = hm_new(943722, 0.6, cmp, hash); + struct hashmap *map = hm_new(943722, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); cmc_assert_not_equals(ptr, NULL, map->buffer); @@ -20,19 +20,19 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(new[capacity = 0], { - hashmap *map = hm_new(0, 0.6, cmp, hash); + struct hashmap *map = hm_new(0, 0.6, cmp, hash); cmc_assert_equals(ptr, NULL, map); }); CMC_CREATE_TEST(new[capacity = UINT64_MAX], { - hashmap *map = hm_new(UINT64_MAX, 0.99, cmp, hash); + struct hashmap *map = hm_new(UINT64_MAX, 0.99, cmp, hash); cmc_assert_equals(ptr, NULL, map); }); CMC_CREATE_TEST(clear[count capacity], { - hashmap *map = hm_new(100, 0.6, cmp, hash); + struct hashmap *map = hm_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -49,7 +49,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(insert, { - hashmap *map = hm_new(100, 0.6, cmp, hash); + struct hashmap *map = hm_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -60,7 +60,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(insert[smallest capacity], { - hashmap *map = hm_new(1, 0.99, cmp, hash); + struct hashmap *map = hm_new(1, 0.99, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -72,7 +72,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { CMC_CREATE_TEST(insert[element position], { // Using the numhash the key is the hash itself - hashmap *map = hm_new(1, 0.99, cmp, numhash); + struct hashmap *map = hm_new(1, 0.99, cmp, numhash); cmc_assert_not_equals(ptr, NULL, map); @@ -90,7 +90,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(insert[distance], { - hashmap *map = hm_new(500, 0.6, cmp, hash0); + struct hashmap *map = hm_new(500, 0.6, cmp, hash0); cmc_assert_not_equals(ptr, NULL, map); @@ -105,7 +105,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(insert[distance wrap], { - hashmap *map = hm_new(1, 0.99, cmp, hashcapminus1); + struct hashmap *map = hm_new(1, 0.99, cmp, hashcapminus1); cmc_assert_not_equals(ptr, NULL, map); @@ -125,7 +125,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(insert[distances], { - hashmap *map = hm_new(1, 0.99, cmp, hashcapminus4); + struct hashmap *map = hm_new(1, 0.99, cmp, hashcapminus4); cmc_assert_not_equals(ptr, NULL, map); @@ -141,7 +141,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(insert[buffer growth and item preservation], { - hashmap *map = hm_new(1, 0.99, cmp, hash); + struct hashmap *map = hm_new(1, 0.99, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -165,7 +165,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(update, { - hashmap *map = hm_new(100, 0.6, cmp, hash); + struct hashmap *map = hm_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -180,7 +180,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(update[key not found], { - hashmap *map = hm_new(100, 0.6, cmp, hash); + struct hashmap *map = hm_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -193,7 +193,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(remove, { - hashmap *map = hm_new(100, 0.6, cmp, hash); + struct hashmap *map = hm_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -207,7 +207,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(remove[count = 0], { - hashmap *map = hm_new(100, 0.6, cmp, hash); + struct hashmap *map = hm_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -218,7 +218,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(remove[key not found], { - hashmap *map = hm_new(100, 0.6, cmp, hash); + struct hashmap *map = hm_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -232,7 +232,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(max, { - hashmap *map = hm_new(100, 0.6, cmp, hash); + struct hashmap *map = hm_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -250,7 +250,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(max[count = 0], { - hashmap *map = hm_new(100, 0.6, cmp, hash); + struct hashmap *map = hm_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -260,7 +260,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(min, { - hashmap *map = hm_new(100, 0.6, cmp, hash); + struct hashmap *map = hm_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -278,7 +278,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(min[count = 0], { - hashmap *map = hm_new(100, 0.6, cmp, hash); + struct hashmap *map = hm_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -288,7 +288,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(get, { - hashmap *map = hm_new(100, 0.6, cmp, hash); + struct hashmap *map = hm_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -300,7 +300,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(get[count = 0], { - hashmap *map = hm_new(100, 0.6, cmp, hash); + struct hashmap *map = hm_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -310,7 +310,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(get_ref, { - hashmap *map = hm_new(100, 0.6, cmp, hash); + struct hashmap *map = hm_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -325,7 +325,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(get_ref[count = 0], { - hashmap *map = hm_new(100, 0.6, cmp, hash); + struct hashmap *map = hm_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -335,7 +335,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(contains, { - hashmap *map = hm_new(100, 0.6, cmp, hash); + struct hashmap *map = hm_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -347,7 +347,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(contains[count = 0], { - hashmap *map = hm_new(100, 0.6, cmp, hash); + struct hashmap *map = hm_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -357,7 +357,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(contains[sum], { - hashmap *map = hm_new(100, 0.6, cmp, hash); + struct hashmap *map = hm_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -375,7 +375,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(empty, { - hashmap *map = hm_new(100, 0.6, cmp, hash); + struct hashmap *map = hm_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -389,7 +389,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(full, { - hashmap *map = hm_new(cmc_hashtable_primes[0], 0.99999, cmp, hash); + struct hashmap *map = hm_new(cmc_hashtable_primes[0], 0.99999, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -410,7 +410,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(count, { - hashmap *map = hm_new(100, 0.6, cmp, hash); + struct hashmap *map = hm_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -424,7 +424,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(capacity, { - hashmap *map = hm_new(2500, 0.6, cmp, hash); + struct hashmap *map = hm_new(2500, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -434,7 +434,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(capacity[small], { - hashmap *map = hm_new(1, 0.99, cmp, hash); + struct hashmap *map = hm_new(1, 0.99, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -444,7 +444,7 @@ CMC_CREATE_UNIT(hashmap_test, true, { }); CMC_CREATE_TEST(load, { - hashmap *map = hm_new(1, 0.99, cmp, hash); + struct hashmap *map = hm_new(1, 0.99, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); diff --git a/tests/main/unt/hashset.c b/tests/main/unt/hashset.c index 2bb3991..92aa66b 100644 --- a/tests/main/unt/hashset.c +++ b/tests/main/unt/hashset.c @@ -9,7 +9,7 @@ CMC_GENERATE_HASHSET(hs, hashset, size_t) CMC_CREATE_UNIT(hashset_test, true, { CMC_CREATE_TEST(new, { - hashset *set = hs_new(943722, 0.6, cmp, hash); + struct hashset *set = hs_new(943722, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); cmc_assert_not_equals(ptr, NULL, set->buffer); @@ -20,19 +20,19 @@ CMC_CREATE_UNIT(hashset_test, true, { }); CMC_CREATE_TEST(new[capacity = 0], { - hashset *set = hs_new(0, 0.6, cmp, hash); + struct hashset *set = hs_new(0, 0.6, cmp, hash); cmc_assert_equals(ptr, NULL, set); }); CMC_CREATE_TEST(new[capacity = UINT64_MAX], { - hashset *set = hs_new(UINT64_MAX, 0.99, cmp, hash); + struct hashset *set = hs_new(UINT64_MAX, 0.99, cmp, hash); cmc_assert_equals(ptr, NULL, set); }); CMC_CREATE_TEST(clear[count capacity], { - hashset *set = hs_new(100, 0.6, cmp, hash); + struct hashset *set = hs_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); @@ -49,7 +49,7 @@ CMC_CREATE_UNIT(hashset_test, true, { }); CMC_CREATE_TEST(insert, { - hashset *set = hs_new(100, 0.6, cmp, hash); + struct hashset *set = hs_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); @@ -60,7 +60,7 @@ CMC_CREATE_UNIT(hashset_test, true, { }); CMC_CREATE_TEST(insert[smallest capacity], { - hashset *set = hs_new(1, 0.99, cmp, hash); + struct hashset *set = hs_new(1, 0.99, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); @@ -72,7 +72,7 @@ CMC_CREATE_UNIT(hashset_test, true, { CMC_CREATE_TEST(insert[element position], { // Using the numhash the key is the hash itself - hashset *set = hs_new(1, 0.99, cmp, numhash); + struct hashset *set = hs_new(1, 0.99, cmp, numhash); cmc_assert_not_equals(ptr, NULL, set); @@ -90,7 +90,7 @@ CMC_CREATE_UNIT(hashset_test, true, { }); CMC_CREATE_TEST(insert[distance], { - hashset *set = hs_new(500, 0.6, cmp, hash0); + struct hashset *set = hs_new(500, 0.6, cmp, hash0); cmc_assert_not_equals(ptr, NULL, set); @@ -105,7 +105,7 @@ CMC_CREATE_UNIT(hashset_test, true, { }); CMC_CREATE_TEST(insert[distance wrap], { - hashset *set = hs_new(1, 0.99, cmp, hashcapminus1); + struct hashset *set = hs_new(1, 0.99, cmp, hashcapminus1); cmc_assert_not_equals(ptr, NULL, set); @@ -125,7 +125,7 @@ CMC_CREATE_UNIT(hashset_test, true, { }); CMC_CREATE_TEST(insert[buffer growth and item preservation], { - hashset *set = hs_new(1, 0.99, cmp, hash); + struct hashset *set = hs_new(1, 0.99, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); @@ -149,7 +149,7 @@ CMC_CREATE_UNIT(hashset_test, true, { }); CMC_CREATE_TEST(remove, { - hashset *set = hs_new(100, 0.6, cmp, hash); + struct hashset *set = hs_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); @@ -163,7 +163,7 @@ CMC_CREATE_UNIT(hashset_test, true, { }); CMC_CREATE_TEST(remove[count = 0], { - hashset *set = hs_new(100, 0.6, cmp, hash); + struct hashset *set = hs_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); @@ -174,7 +174,7 @@ CMC_CREATE_UNIT(hashset_test, true, { }); CMC_CREATE_TEST(remove[key not found], { - hashset *set = hs_new(100, 0.6, cmp, hash); + struct hashset *set = hs_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); @@ -188,7 +188,7 @@ CMC_CREATE_UNIT(hashset_test, true, { }); CMC_CREATE_TEST(max, { - hashset *set = hs_new(100, 0.6, cmp, hash); + struct hashset *set = hs_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); @@ -204,7 +204,7 @@ CMC_CREATE_UNIT(hashset_test, true, { }); CMC_CREATE_TEST(max[count = 0], { - hashset *set = hs_new(100, 0.6, cmp, hash); + struct hashset *set = hs_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); @@ -214,7 +214,7 @@ CMC_CREATE_UNIT(hashset_test, true, { }); CMC_CREATE_TEST(min, { - hashset *set = hs_new(100, 0.6, cmp, hash); + struct hashset *set = hs_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); @@ -230,7 +230,7 @@ CMC_CREATE_UNIT(hashset_test, true, { }); CMC_CREATE_TEST(min[count = 0], { - hashset *set = hs_new(100, 0.6, cmp, hash); + struct hashset *set = hs_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); @@ -240,7 +240,7 @@ CMC_CREATE_UNIT(hashset_test, true, { }); CMC_CREATE_TEST(contains, { - hashset *set = hs_new(100, 0.6, cmp, hash); + struct hashset *set = hs_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); @@ -252,7 +252,7 @@ CMC_CREATE_UNIT(hashset_test, true, { }); CMC_CREATE_TEST(contains[count = 0], { - hashset *set = hs_new(100, 0.6, cmp, hash); + struct hashset *set = hs_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); @@ -262,7 +262,7 @@ CMC_CREATE_UNIT(hashset_test, true, { }); CMC_CREATE_TEST(contains[sum], { - hashset *set = hs_new(100, 0.6, cmp, hash); + struct hashset *set = hs_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); @@ -280,7 +280,7 @@ CMC_CREATE_UNIT(hashset_test, true, { }); CMC_CREATE_TEST(empty, { - hashset *set = hs_new(100, 0.6, cmp, hash); + struct hashset *set = hs_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); @@ -294,7 +294,7 @@ CMC_CREATE_UNIT(hashset_test, true, { }); CMC_CREATE_TEST(full, { - hashset *set = hs_new(cmc_hashtable_primes[0], 0.99999, cmp, hash); + struct hashset *set = hs_new(cmc_hashtable_primes[0], 0.99999, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); @@ -315,7 +315,7 @@ CMC_CREATE_UNIT(hashset_test, true, { }); CMC_CREATE_TEST(count, { - hashset *set = hs_new(100, 0.6, cmp, hash); + struct hashset *set = hs_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); @@ -329,7 +329,7 @@ CMC_CREATE_UNIT(hashset_test, true, { }); CMC_CREATE_TEST(capacity, { - hashset *set = hs_new(2500, 0.6, cmp, hash); + struct hashset *set = hs_new(2500, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); @@ -339,7 +339,7 @@ CMC_CREATE_UNIT(hashset_test, true, { }); CMC_CREATE_TEST(capacity[small], { - hashset *set = hs_new(1, 0.99, cmp, hash); + struct hashset *set = hs_new(1, 0.99, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); @@ -349,7 +349,7 @@ CMC_CREATE_UNIT(hashset_test, true, { }); CMC_CREATE_TEST(load, { - hashset *set = hs_new(1, 0.99, cmp, hash); + struct hashset *set = hs_new(1, 0.99, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); diff --git a/tests/main/unt/heap.c b/tests/main/unt/heap.c index b7715e5..4532e33 100644 --- a/tests/main/unt/heap.c +++ b/tests/main/unt/heap.c @@ -9,7 +9,7 @@ CMC_GENERATE_HEAP(h, heap, size_t) CMC_CREATE_UNIT(heap_test, true, { CMC_CREATE_TEST(new, { - heap *h = h_new(1000000, cmc_max_heap, cmp); + struct heap *h = h_new(1000000, cmc_max_heap, cmp); cmc_assert_not_equals(ptr, NULL, h); cmc_assert_not_equals(ptr, NULL, h->buffer); @@ -20,19 +20,19 @@ CMC_CREATE_UNIT(heap_test, true, { }); CMC_CREATE_TEST(new[edge_case capacity = 0], { - heap *h = h_new(0, cmc_max_heap, cmp); + struct heap *h = h_new(0, cmc_max_heap, cmp); cmc_assert_equals(ptr, NULL, h); }); CMC_CREATE_TEST(new[edge_case capacity = UINT64_MAX], { - heap *h = h_new(UINT64_MAX, cmc_max_heap, cmp); + struct heap *h = h_new(UINT64_MAX, cmc_max_heap, cmp); cmc_assert_equals(ptr, NULL, h); }); CMC_CREATE_TEST(clear[count capacity], { - heap *h = h_new(100, cmc_max_heap, cmp); + struct heap *h = h_new(100, cmc_max_heap, cmp); cmc_assert_not_equals(ptr, NULL, h); @@ -50,7 +50,7 @@ CMC_CREATE_UNIT(heap_test, true, { }); CMC_CREATE_TEST(buffer_growth[edge_case capacity = 1], { - heap *h = h_new(1, cmc_max_heap, cmp); + struct heap *h = h_new(1, cmc_max_heap, cmp); cmc_assert_not_equals(ptr, NULL, h); @@ -63,7 +63,7 @@ CMC_CREATE_UNIT(heap_test, true, { }); CMC_CREATE_TEST(insert, { - heap *h = h_new(100, cmc_max_heap, cmp); + struct heap *h = h_new(100, cmc_max_heap, cmp); cmc_assert_not_equals(ptr, NULL, h); @@ -73,7 +73,7 @@ CMC_CREATE_UNIT(heap_test, true, { }); CMC_CREATE_TEST(insert[item preservation], { - heap *h = h_new(50, cmc_max_heap, cmp); + struct heap *h = h_new(50, cmc_max_heap, cmp); cmc_assert_not_equals(ptr, NULL, h); @@ -90,7 +90,7 @@ CMC_CREATE_UNIT(heap_test, true, { }); CMC_CREATE_TEST(remove, { - heap *h = h_new(50, cmc_max_heap, cmp); + struct heap *h = h_new(50, cmc_max_heap, cmp); cmc_assert_not_equals(ptr, NULL, h); @@ -106,7 +106,7 @@ CMC_CREATE_UNIT(heap_test, true, { }); CMC_CREATE_TEST(remove[count = 0], { - heap *h = h_new(100, cmc_max_heap, cmp); + struct heap *h = h_new(100, cmc_max_heap, cmp); cmc_assert_not_equals(ptr, NULL, h); @@ -117,7 +117,7 @@ CMC_CREATE_UNIT(heap_test, true, { }); CMC_CREATE_TEST(remove[sorted], { - heap *h = h_new(100, cmc_min_heap, cmp); + struct heap *h = h_new(100, cmc_min_heap, cmp); cmc_assert_not_equals(ptr, NULL, h); @@ -140,7 +140,7 @@ CMC_CREATE_UNIT(heap_test, true, { }); CMC_CREATE_TEST(peek, { - heap *h = h_new(100, cmc_max_heap, cmp); + struct heap *h = h_new(100, cmc_max_heap, cmp); cmc_assert_not_equals(ptr, NULL, h); @@ -153,7 +153,7 @@ CMC_CREATE_UNIT(heap_test, true, { }); CMC_CREATE_TEST(peek[count = 0], { - heap *h = h_new(100, cmc_max_heap, cmp); + struct heap *h = h_new(100, cmc_max_heap, cmp); cmc_assert_not_equals(ptr, NULL, h); diff --git a/tests/main/unt/intervalheap.c b/tests/main/unt/intervalheap.c index c64cc10..cc1df47 100644 --- a/tests/main/unt/intervalheap.c +++ b/tests/main/unt/intervalheap.c @@ -9,7 +9,7 @@ CMC_GENERATE_INTERVALHEAP(ih, intervalheap, size_t) CMC_CREATE_UNIT(intervalheap_test, true, { CMC_CREATE_TEST(new, { - intervalheap *ih = ih_new(1000000, cmp); + struct intervalheap *ih = ih_new(1000000, cmp); cmc_assert_not_equals(ptr, NULL, ih); cmc_assert_not_equals(ptr, NULL, ih->buffer); @@ -20,7 +20,7 @@ CMC_CREATE_UNIT(intervalheap_test, true, { }); CMC_CREATE_TEST(new[capacity = 0], { - intervalheap *ih = ih_new(0, cmp); + struct intervalheap *ih = ih_new(0, cmp); cmc_assert_equals(ptr, NULL, ih); @@ -29,7 +29,7 @@ CMC_CREATE_UNIT(intervalheap_test, true, { }); CMC_CREATE_TEST(new[capacity], { - intervalheap *ih = ih_new(1, cmp); + struct intervalheap *ih = ih_new(1, cmp); cmc_assert_not_equals(ptr, NULL, ih); cmc_assert_equals(size_t, 1, ih_capacity(ih)); @@ -59,7 +59,7 @@ CMC_CREATE_UNIT(intervalheap_test, true, { }); CMC_CREATE_TEST(new[capacity = UINT64_MAX], { - intervalheap *ih = ih_new(UINT64_MAX, cmp); + struct intervalheap *ih = ih_new(UINT64_MAX, cmp); cmc_assert_equals(ptr, NULL, ih); @@ -68,7 +68,7 @@ CMC_CREATE_UNIT(intervalheap_test, true, { }); CMC_CREATE_TEST(clear[count capacity], { - intervalheap *ih = ih_new(100, cmp); + struct intervalheap *ih = ih_new(100, cmp); cmc_assert_not_equals(ptr, NULL, ih); @@ -86,7 +86,7 @@ CMC_CREATE_UNIT(intervalheap_test, true, { }); CMC_CREATE_TEST(buffer_growth[capacity = 1], { - intervalheap *ih = ih_new(1, cmp); + struct intervalheap *ih = ih_new(1, cmp); cmc_assert_not_equals(ptr, NULL, ih); @@ -100,7 +100,7 @@ CMC_CREATE_UNIT(intervalheap_test, true, { }); CMC_CREATE_TEST(insert[count], { - intervalheap *ih = ih_new(100, cmp); + struct intervalheap *ih = ih_new(100, cmp); cmc_assert_not_equals(ptr, NULL, ih); @@ -113,7 +113,7 @@ CMC_CREATE_UNIT(intervalheap_test, true, { }); CMC_CREATE_TEST(insert[max min], { - intervalheap *ih = ih_new(1, cmp); + struct intervalheap *ih = ih_new(1, cmp); cmc_assert_not_equals(ptr, NULL, ih); diff --git a/tests/main/unt/linkedlist.c b/tests/main/unt/linkedlist.c index f377165..b13ec31 100644 --- a/tests/main/unt/linkedlist.c +++ b/tests/main/unt/linkedlist.c @@ -9,7 +9,7 @@ CMC_GENERATE_LINKEDLIST(ll, linkedlist, size_t) CMC_CREATE_UNIT(linkedlist_test, true, { CMC_CREATE_TEST(new, { - linkedlist *ll = ll_new(); + struct linkedlist *ll = ll_new(); cmc_assert_not_equals(ptr, NULL, ll); cmc_assert_equals(size_t, 0, ll_count(ll)); @@ -20,7 +20,7 @@ CMC_CREATE_UNIT(linkedlist_test, true, { }); CMC_CREATE_TEST(clear[count capacity], { - linkedlist *ll = ll_new(); + struct linkedlist *ll = ll_new(); cmc_assert_not_equals(ptr, NULL, ll); @@ -37,7 +37,7 @@ CMC_CREATE_UNIT(linkedlist_test, true, { }); CMC_CREATE_TEST(clear[count = 0], { - linkedlist *ll = ll_new(); + struct linkedlist *ll = ll_new(); cmc_assert_not_equals(ptr, NULL, ll); @@ -49,7 +49,7 @@ CMC_CREATE_UNIT(linkedlist_test, true, { }); CMC_CREATE_TEST(push_front[count], { - linkedlist *ll = ll_new(); + struct linkedlist *ll = ll_new(); cmc_assert_not_equals(ptr, NULL, ll); @@ -63,7 +63,7 @@ CMC_CREATE_UNIT(linkedlist_test, true, { }); CMC_CREATE_TEST(push_front[item preservation], { - linkedlist *ll = ll_new(); + struct linkedlist *ll = ll_new(); cmc_assert_not_equals(ptr, NULL, ll); diff --git a/tests/main/unt/list.c b/tests/main/unt/list.c index 2740e03..8cc30da 100644 --- a/tests/main/unt/list.c +++ b/tests/main/unt/list.c @@ -9,7 +9,7 @@ CMC_GENERATE_LIST(l, list, size_t) CMC_CREATE_UNIT(list_test, true, { CMC_CREATE_TEST(new, { - list *l = l_new(1000000); + struct list *l = l_new(1000000); cmc_assert_not_equals(ptr, NULL, l); cmc_assert_not_equals(ptr, NULL, l->buffer); @@ -20,13 +20,13 @@ CMC_CREATE_UNIT(list_test, true, { }); CMC_CREATE_TEST(new[capacity = 0], { - list *l = l_new(0); + struct list *l = l_new(0); cmc_assert_equals(ptr, NULL, l); }); CMC_CREATE_TEST(new[capacity = UINT64_MAX], { - list *l = l_new(UINT64_MAX); + struct list *l = l_new(UINT64_MAX); cmc_assert_equals(ptr, NULL, l); }); @@ -39,7 +39,7 @@ CMC_CREATE_UNIT(list_test, true, { v[i] = i; } - list *l = l_new_from(v, 5); + struct list *l = l_new_from(v, 5); cmc_assert_not_equals(ptr, NULL, l); @@ -54,7 +54,7 @@ CMC_CREATE_UNIT(list_test, true, { size_t *values = &a; - list *l = l_new_from(values, 1); + struct list *l = l_new_from(values, 1); cmc_assert_not_equals(ptr, NULL, l); @@ -62,7 +62,7 @@ CMC_CREATE_UNIT(list_test, true, { }); CMC_CREATE_TEST(clear[count capacity], { - list *l = l_new(100); + struct list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); @@ -80,7 +80,7 @@ CMC_CREATE_UNIT(list_test, true, { }); CMC_CREATE_TEST(buffer_growth[capacity = 1], { - list *l = l_new(1); + struct list *l = l_new(1); cmc_assert_not_equals(ptr, NULL, l); @@ -96,7 +96,7 @@ CMC_CREATE_UNIT(list_test, true, { }); CMC_CREATE_TEST(push_front[count], { - list *l = l_new(100); + struct list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); @@ -109,7 +109,7 @@ CMC_CREATE_UNIT(list_test, true, { }); CMC_CREATE_TEST(push_front[capacity], { - list *l = l_new(100); + struct list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); @@ -122,7 +122,7 @@ CMC_CREATE_UNIT(list_test, true, { }); CMC_CREATE_TEST(push_front[item preservation], { - list *l = l_new(100); + struct list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); @@ -136,7 +136,7 @@ CMC_CREATE_UNIT(list_test, true, { }); CMC_CREATE_TEST(push_at[count], { - list *l = l_new(100); + struct list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); @@ -152,7 +152,7 @@ CMC_CREATE_UNIT(list_test, true, { }); CMC_CREATE_TEST(push_at[capacity], { - list *l = l_new(100); + struct list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); @@ -168,7 +168,7 @@ CMC_CREATE_UNIT(list_test, true, { }); CMC_CREATE_TEST(push_at[item preservation], { - list *l = l_new(100); + struct list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); @@ -185,7 +185,7 @@ CMC_CREATE_UNIT(list_test, true, { }); CMC_CREATE_TEST(push_back[count], { - list *l = l_new(100); + struct list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); @@ -198,7 +198,7 @@ CMC_CREATE_UNIT(list_test, true, { }); CMC_CREATE_TEST(push_back[capacity], { - list *l = l_new(100); + struct list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); @@ -211,7 +211,7 @@ CMC_CREATE_UNIT(list_test, true, { }); CMC_CREATE_TEST(push_back[item preservation], { - list *l = l_new(100); + struct list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); @@ -225,7 +225,7 @@ CMC_CREATE_UNIT(list_test, true, { }); CMC_CREATE_TEST(pop_front[count], { - list *l = l_new(100); + struct list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); @@ -238,7 +238,7 @@ CMC_CREATE_UNIT(list_test, true, { }); CMC_CREATE_TEST(pop_front[item preservation], { - list *l = l_new(100); + struct list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); @@ -254,7 +254,7 @@ CMC_CREATE_UNIT(list_test, true, { }); CMC_CREATE_TEST(pop_front[count = 0], { - list *l = l_new(100); + struct list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); cmc_assert(!l_pop_front(l)); @@ -263,7 +263,7 @@ CMC_CREATE_UNIT(list_test, true, { }); CMC_CREATE_TEST(pop_front[count = 1], { - list *l = l_new(100); + struct list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); cmc_assert(l_push_back(l, 10)); @@ -273,7 +273,7 @@ CMC_CREATE_UNIT(list_test, true, { }); CMC_CREATE_TEST(pop_front[buffer_clear], { - list *l = l_new(100); + struct list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); cmc_assert(l_push_back(l, 1)); @@ -287,7 +287,7 @@ CMC_CREATE_UNIT(list_test, true, { }); CMC_CREATE_TEST(pop_at[count = 0], { - list *l = l_new(100); + struct list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); cmc_assert(!l_pop_at(l, 1)); @@ -296,7 +296,7 @@ CMC_CREATE_UNIT(list_test, true, { }); CMC_CREATE_TEST(pop_at[count = 1], { - list *l = l_new(100); + struct list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); cmc_assert(l_push_back(l, 1)); @@ -308,7 +308,7 @@ CMC_CREATE_UNIT(list_test, true, { }); CMC_CREATE_TEST(pop_at[buffer_clear], { - list *l = l_new(100); + struct list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); cmc_assert(l_push_back(l, 1)); @@ -320,7 +320,7 @@ CMC_CREATE_UNIT(list_test, true, { }); CMC_CREATE_TEST(pop_back[count = 0], { - list *l = l_new(100); + struct list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); cmc_assert(!l_pop_back(l)); @@ -329,7 +329,7 @@ CMC_CREATE_UNIT(list_test, true, { }); CMC_CREATE_TEST(pop_back[count = 1], { - list *l = l_new(100); + struct list *l = l_new(100); cmc_assert_not_equals(ptr, NULL, l); cmc_assert(l_push_back(l, 10)); diff --git a/tests/main/unt/multimap.c b/tests/main/unt/multimap.c index b7f771b..4604c9c 100644 --- a/tests/main/unt/multimap.c +++ b/tests/main/unt/multimap.c @@ -9,7 +9,7 @@ CMC_GENERATE_MULTIMAP(mm, multimap, size_t, size_t) CMC_CREATE_UNIT(multimap_test, true, { CMC_CREATE_TEST(new, { - multimap *map = mm_new(943722, 0.8, cmp, hash); + struct multimap *map = mm_new(943722, 0.8, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); cmc_assert_not_equals(ptr, NULL, map->buffer); @@ -20,19 +20,19 @@ CMC_CREATE_UNIT(multimap_test, true, { }); CMC_CREATE_TEST(new[capacity = 0], { - multimap *map = mm_new(0, 0.8, cmp, hash); + struct multimap *map = mm_new(0, 0.8, cmp, hash); cmc_assert_equals(ptr, NULL, map); }); CMC_CREATE_TEST(new[capacity = UINT64_MAX], { - multimap *map = mm_new(UINT64_MAX, 0.99, cmp, hash); + struct multimap *map = mm_new(UINT64_MAX, 0.99, cmp, hash); cmc_assert_equals(ptr, NULL, map); }); CMC_CREATE_TEST(clear[count capacity], { - multimap *map = mm_new(100, 0.8, cmp, hash); + struct multimap *map = mm_new(100, 0.8, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -49,7 +49,7 @@ CMC_CREATE_UNIT(multimap_test, true, { }); CMC_CREATE_TEST(insert[count], { - multimap *map = mm_new(100, 0.8, cmp, hash); + struct multimap *map = mm_new(100, 0.8, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -62,7 +62,7 @@ CMC_CREATE_UNIT(multimap_test, true, { }); CMC_CREATE_TEST(remove[count], { - multimap *map = mm_new(100, 0.8, cmp, hash); + struct multimap *map = mm_new(100, 0.8, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -80,7 +80,7 @@ CMC_CREATE_UNIT(multimap_test, true, { }); CMC_CREATE_TEST(remove[count = 0], { - multimap *map = mm_new(100, 0.8, cmp, hash); + struct multimap *map = mm_new(100, 0.8, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -92,7 +92,7 @@ CMC_CREATE_UNIT(multimap_test, true, { }); CMC_CREATE_TEST(remove[count = 1], { - multimap *map = mm_new(100, 0.8, cmp, hash); + struct multimap *map = mm_new(100, 0.8, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -105,7 +105,7 @@ CMC_CREATE_UNIT(multimap_test, true, { }); CMC_CREATE_TEST(get[key ordering], { - multimap *map = mm_new(100, 0.8, cmp, hash); + struct multimap *map = mm_new(100, 0.8, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); @@ -121,7 +121,7 @@ CMC_CREATE_UNIT(multimap_test, true, { }); CMC_CREATE_TEST(key_count, { - multimap *map = mm_new(50, 0.8, cmp, hash); + struct multimap *map = mm_new(50, 0.8, cmp, hash); cmc_assert_not_equals(ptr, NULL, map); diff --git a/tests/main/unt/multiset.c b/tests/main/unt/multiset.c index 9ce2a69..5f71c04 100644 --- a/tests/main/unt/multiset.c +++ b/tests/main/unt/multiset.c @@ -9,7 +9,7 @@ CMC_GENERATE_MULTISET(ms, multiset, size_t) CMC_CREATE_UNIT(multiset_test, true, { CMC_CREATE_TEST(new, { - multiset *set = ms_new(943722, 0.6, cmp, hash); + struct multiset *set = ms_new(943722, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); cmc_assert_not_equals(ptr, NULL, set->buffer); @@ -20,19 +20,19 @@ CMC_CREATE_UNIT(multiset_test, true, { }); CMC_CREATE_TEST(new[capacity = 0], { - multiset *set = ms_new(0, 0.6, cmp, hash); + struct multiset *set = ms_new(0, 0.6, cmp, hash); cmc_assert_equals(ptr, NULL, set); }); CMC_CREATE_TEST(new[capacity = UINT64_MAX], { - multiset *set = ms_new(UINT64_MAX, 0.99, cmp, hash); + struct multiset *set = ms_new(UINT64_MAX, 0.99, cmp, hash); cmc_assert_equals(ptr, NULL, set); }); CMC_CREATE_TEST(clear[count capacity], { - multiset *set = ms_new(100, 0.6, cmp, hash); + struct multiset *set = ms_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); @@ -49,7 +49,7 @@ CMC_CREATE_UNIT(multiset_test, true, { }); CMC_CREATE_TEST(insert[count cardinality multiplicity], { - multiset *set = ms_new(100, 0.6, cmp, hash); + struct multiset *set = ms_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); @@ -70,7 +70,7 @@ CMC_CREATE_UNIT(multiset_test, true, { }); CMC_CREATE_TEST(remove[count cardinality multiplicity], { - multiset *set = ms_new(100, 0.6, cmp, hash); + struct multiset *set = ms_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); @@ -103,7 +103,7 @@ CMC_CREATE_UNIT(multiset_test, true, { }); CMC_CREATE_TEST(remove_all[count cardinality multiplicity], { - multiset *set = ms_new(100, 0.6, cmp, hash); + struct multiset *set = ms_new(100, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); @@ -135,7 +135,7 @@ CMC_CREATE_UNIT(multiset_test, true, { }); CMC_CREATE_TEST(multiplicity, { - multiset *set = ms_new(50, 0.6, cmp, hash); + struct multiset *set = ms_new(50, 0.6, cmp, hash); cmc_assert_not_equals(ptr, NULL, set); diff --git a/tests/main/unt/queue.c b/tests/main/unt/queue.c index f069b8b..4b08285 100644 --- a/tests/main/unt/queue.c +++ b/tests/main/unt/queue.c @@ -9,7 +9,7 @@ CMC_GENERATE_QUEUE(q, queue, size_t) CMC_CREATE_UNIT(queue_test, true, { CMC_CREATE_TEST(new, { - queue *q = q_new(1000000); + struct queue *q = q_new(1000000); cmc_assert_not_equals(ptr, NULL, q); cmc_assert_not_equals(ptr, NULL, q->buffer); @@ -21,19 +21,19 @@ CMC_CREATE_UNIT(queue_test, true, { }); CMC_CREATE_TEST(new[capacity = 0], { - queue *q = q_new(0); + struct queue *q = q_new(0); cmc_assert_equals(ptr, NULL, q); }); CMC_CREATE_TEST(new[capacity = UINT64_MAX], { - queue *q = q_new(UINT64_MAX); + struct queue *q = q_new(UINT64_MAX); cmc_assert_equals(ptr, NULL, q); }); CMC_CREATE_TEST(clear[count capacity], { - queue *q = q_new(100); + struct queue *q = q_new(100); cmc_assert_not_equals(ptr, NULL, q); @@ -51,7 +51,7 @@ CMC_CREATE_UNIT(queue_test, true, { }); CMC_CREATE_TEST(buffer_growth[capacity = 1], { - queue *q = q_new(1); + struct queue *q = q_new(1); cmc_assert_not_equals(ptr, NULL, q); @@ -64,7 +64,7 @@ CMC_CREATE_UNIT(queue_test, true, { }); CMC_CREATE_TEST(buffer_growth[item preservation], { - queue *q = q_new(100); + struct queue *q = q_new(100); cmc_assert_not_equals(ptr, NULL, q); @@ -84,7 +84,7 @@ CMC_CREATE_UNIT(queue_test, true, { }); CMC_CREATE_TEST(enqueue[count capacity], { - queue *q = q_new(100); + struct queue *q = q_new(100); cmc_assert_not_equals(ptr, NULL, q); @@ -98,7 +98,7 @@ CMC_CREATE_UNIT(queue_test, true, { }); CMC_CREATE_TEST(enqueue[item preservation], { - queue *q = q_new(100); + struct queue *q = q_new(100); cmc_assert_not_equals(ptr, NULL, q); @@ -118,7 +118,7 @@ CMC_CREATE_UNIT(queue_test, true, { }); CMC_CREATE_TEST(dequeue[count capacity], { - queue *q = q_new(100); + struct queue *q = q_new(100); cmc_assert_not_equals(ptr, NULL, q); @@ -136,7 +136,7 @@ CMC_CREATE_UNIT(queue_test, true, { }); CMC_CREATE_TEST(dequeue[item preservation], { - queue *q = q_new(100); + struct queue *q = q_new(100); cmc_assert_not_equals(ptr, NULL, q); @@ -159,7 +159,7 @@ CMC_CREATE_UNIT(queue_test, true, { }); CMC_CREATE_TEST(peek[count = 0], { - queue *q = q_new(100); + struct queue *q = q_new(100); cmc_assert_not_equals(ptr, NULL, q); @@ -171,7 +171,7 @@ CMC_CREATE_UNIT(queue_test, true, { }); CMC_CREATE_TEST(peek[sum], { - queue *q = q_new(100); + struct queue *q = q_new(100); cmc_assert_not_equals(ptr, NULL, q); @@ -195,7 +195,7 @@ CMC_CREATE_UNIT(queue_test, true, { }); CMC_CREATE_TEST(contains, { - queue *q = q_new(100); + struct queue *q = q_new(100); cmc_assert_not_equals(ptr, NULL, q); @@ -214,7 +214,7 @@ CMC_CREATE_UNIT(queue_test, true, { }); CMC_CREATE_TEST(contains[count = 0], { - queue *q = q_new(100); + struct queue *q = q_new(100); cmc_assert_not_equals(ptr, NULL, q); @@ -224,7 +224,7 @@ CMC_CREATE_UNIT(queue_test, true, { }); CMC_CREATE_TEST(contains[count = 1], { - queue *q = q_new(100); + struct queue *q = q_new(100); cmc_assert_not_equals(ptr, NULL, q); @@ -239,7 +239,7 @@ CMC_CREATE_UNIT(queue_test, true, { }); CMC_CREATE_TEST(empty, { - queue *q = q_new(100); + struct queue *q = q_new(100); cmc_assert_not_equals(ptr, NULL, q); @@ -253,7 +253,7 @@ CMC_CREATE_UNIT(queue_test, true, { }); CMC_CREATE_TEST(full, { - queue *q = q_new(100); + struct queue *q = q_new(100); cmc_assert_not_equals(ptr, NULL, q); @@ -268,7 +268,7 @@ CMC_CREATE_UNIT(queue_test, true, { }); CMC_CREATE_TEST(count, { - queue *q = q_new(100); + struct queue *q = q_new(100); cmc_assert_not_equals(ptr, NULL, q); @@ -283,7 +283,7 @@ CMC_CREATE_UNIT(queue_test, true, { }); CMC_CREATE_TEST(capacity, { - queue *q = q_new(100); + struct queue *q = q_new(100); cmc_assert_not_equals(ptr, NULL, q); @@ -293,7 +293,7 @@ CMC_CREATE_UNIT(queue_test, true, { }); CMC_CREATE_TEST(resize, { - queue *q = q_new(100); + struct queue *q = q_new(100); cmc_assert_not_equals(ptr, NULL, q); @@ -308,7 +308,7 @@ CMC_CREATE_UNIT(queue_test, true, { }); CMC_CREATE_TEST(resize[item preservation], { - queue *q = q_new(100); + struct queue *q = q_new(100); cmc_assert_not_equals(ptr, NULL, q); @@ -330,14 +330,14 @@ CMC_CREATE_UNIT(queue_test, true, { }); CMC_CREATE_TEST(copy_of, { - queue *d1 = q_new(100); + struct queue *d1 = q_new(100); cmc_assert_not_equals(ptr, NULL, d1); for (size_t i = 1; i <= 150; i++) cmc_assert(q_enqueue(d1, i)); - queue *d2 = q_copy_of(d1, NULL); + struct queue *d2 = q_copy_of(d1, NULL); cmc_assert_not_equals(ptr, NULL, d2); cmc_assert_equals(size_t, q_count(d1), q_count(d2)); @@ -355,8 +355,8 @@ CMC_CREATE_UNIT(queue_test, true, { }); CMC_CREATE_TEST(equals, { - queue *d1 = q_new(100); - queue *d2 = q_new(100); + struct queue *d1 = q_new(100); + struct queue *d2 = q_new(100); cmc_assert_not_equals(ptr, NULL, d1); cmc_assert_not_equals(ptr, NULL, d2); @@ -374,7 +374,7 @@ CMC_CREATE_UNIT(queue_test, true, { }); CMC_CREATE_TEST(equals[from copy], { - queue *d1 = q_new(100); + struct queue *d1 = q_new(100); cmc_assert_not_equals(ptr, NULL, d1); @@ -383,7 +383,7 @@ CMC_CREATE_UNIT(queue_test, true, { cmc_assert(q_enqueue(d1, i)); } - queue *d2 = q_copy_of(d1, NULL); + struct queue *d2 = q_copy_of(d1, NULL); cmc_assert_not_equals(ptr, NULL, d2); @@ -394,11 +394,11 @@ CMC_CREATE_UNIT(queue_test, true, { }); CMC_CREATE_TEST(equals[count = 0], { - queue *d1 = q_new(100); + struct queue *d1 = q_new(100); cmc_assert_not_equals(ptr, NULL, d1); - queue *d2 = q_copy_of(d1, NULL); + struct queue *d2 = q_copy_of(d1, NULL); cmc_assert_not_equals(ptr, NULL, d2); diff --git a/tests/main/unt/sortedlist.c b/tests/main/unt/sortedlist.c index 8a9476a..d609675 100644 --- a/tests/main/unt/sortedlist.c +++ b/tests/main/unt/sortedlist.c @@ -9,7 +9,7 @@ CMC_GENERATE_SORTEDLIST(sl, sortedlist, size_t) CMC_CREATE_UNIT(sortedlist_test, true, { CMC_CREATE_TEST(new, { - sortedlist *sl = sl_new(1000000, cmp); + struct sortedlist *sl = sl_new(1000000, cmp); cmc_assert_not_equals(ptr, NULL, sl); cmc_assert_not_equals(ptr, NULL, sl->buffer); @@ -21,19 +21,19 @@ CMC_CREATE_UNIT(sortedlist_test, true, { }); CMC_CREATE_TEST(new[capacity = 0], { - sortedlist *sl = sl_new(0, cmp); + struct sortedlist *sl = sl_new(0, cmp); cmc_assert_equals(ptr, NULL, sl); }); CMC_CREATE_TEST(new[capacity = UINT64_MAX], { - sortedlist *sl = sl_new(UINT64_MAX, cmp); + struct sortedlist *sl = sl_new(UINT64_MAX, cmp); cmc_assert_equals(ptr, NULL, sl); }); CMC_CREATE_TEST(clear[count capacity], { - sortedlist *sl = sl_new(100, cmp); + struct sortedlist *sl = sl_new(100, cmp); cmc_assert_not_equals(ptr, NULL, sl); @@ -51,7 +51,7 @@ CMC_CREATE_UNIT(sortedlist_test, true, { }); CMC_CREATE_TEST(buffer_growth[capacity = 1], { - sortedlist *sl = sl_new(1, cmp); + struct sortedlist *sl = sl_new(1, cmp); cmc_assert_not_equals(ptr, NULL, sl); @@ -67,7 +67,7 @@ CMC_CREATE_UNIT(sortedlist_test, true, { }); CMC_CREATE_TEST(insert, { - sortedlist *sl = sl_new(100, cmp); + struct sortedlist *sl = sl_new(100, cmp); cmc_assert_not_equals(ptr, NULL, sl); @@ -77,7 +77,7 @@ CMC_CREATE_UNIT(sortedlist_test, true, { }); CMC_CREATE_TEST(remove, { - sortedlist *sl = sl_new(100, cmp); + struct sortedlist *sl = sl_new(100, cmp); cmc_assert_not_equals(ptr, NULL, sl); @@ -89,7 +89,7 @@ CMC_CREATE_UNIT(sortedlist_test, true, { }); CMC_CREATE_TEST(remove[count = 0], { - sortedlist *sl = sl_new(100, cmp); + struct sortedlist *sl = sl_new(100, cmp); cmc_assert_not_equals(ptr, NULL, sl); @@ -99,7 +99,7 @@ CMC_CREATE_UNIT(sortedlist_test, true, { }); CMC_CREATE_TEST(remove[out of range], { - sortedlist *sl = sl_new(100, cmp); + struct sortedlist *sl = sl_new(100, cmp); cmc_assert_not_equals(ptr, NULL, sl); @@ -111,7 +111,7 @@ CMC_CREATE_UNIT(sortedlist_test, true, { }); CMC_CREATE_TEST(indexof, { - sortedlist *sl = sl_new(1, cmp); + struct sortedlist *sl = sl_new(1, cmp); cmc_assert_not_equals(ptr, NULL, sl); diff --git a/tests/main/unt/stack.c b/tests/main/unt/stack.c index 963f550..e4e4b77 100644 --- a/tests/main/unt/stack.c +++ b/tests/main/unt/stack.c @@ -9,7 +9,7 @@ CMC_GENERATE_STACK(s, stack, size_t) CMC_CREATE_UNIT(stack_test, true, { CMC_CREATE_TEST(new, { - stack *s = s_new(1000000); + struct stack *s = s_new(1000000); cmc_assert_not_equals(ptr, NULL, s); cmc_assert_not_equals(ptr, NULL, s->buffer); @@ -21,19 +21,19 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(new[capacity = 0], { - stack *s = s_new(0); + struct stack *s = s_new(0); cmc_assert_equals(ptr, NULL, s); }); CMC_CREATE_TEST(new[capacity = UINT64_MAX], { - stack *s = s_new(UINT64_MAX); + struct stack *s = s_new(UINT64_MAX); cmc_assert_equals(ptr, NULL, s); }); CMC_CREATE_TEST(clear[count capacity], { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -51,7 +51,7 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(buffer_growth[capacity = 1], { - stack *s = s_new(1); + struct stack *s = s_new(1); cmc_assert_not_equals(ptr, NULL, s); @@ -65,7 +65,7 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(push[count], { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -78,7 +78,7 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(push[capacity], { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -91,7 +91,7 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(push[item preservation], { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -105,7 +105,7 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(pop[count], { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -120,7 +120,7 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(pop[capacity], { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -135,7 +135,7 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(pop[item preservation], { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -152,7 +152,7 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(pop[count = 0], { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -162,7 +162,7 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(top, { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -178,7 +178,7 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(top[count = 0], { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -192,7 +192,7 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(top[count = 1], { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -204,7 +204,7 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(contains, { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -218,7 +218,7 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(contains[count = 0], { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -228,7 +228,7 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(empty, { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -238,7 +238,7 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(empty[after_io], { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -250,7 +250,7 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(full, { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -263,7 +263,7 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(full[capacity = 1], { - stack *s = s_new(1); + struct stack *s = s_new(1); cmc_assert_not_equals(ptr, NULL, s); @@ -275,11 +275,11 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(iter_alloc, { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); - stack_iter *iter = s_iter_new(s); + struct stack_iter *iter = s_iter_new(s); cmc_assert_not_equals(ptr, NULL, iter); @@ -288,11 +288,11 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(iter_init[count = 0], { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); - stack_iter iter; + struct stack_iter iter; s_iter_init(&iter, s); @@ -305,11 +305,11 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(iter_start[count = 0], { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); - stack_iter iter; + struct stack_iter iter; s_iter_init(&iter, s); @@ -319,11 +319,11 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(iter_end[count = 0], { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); - stack_iter iter; + struct stack_iter iter; s_iter_init(&iter, s); @@ -333,7 +333,7 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(iteration, { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -342,14 +342,14 @@ CMC_CREATE_UNIT(stack_test, true, { size_t total = 0; - for (stack_iter it = s->it_start(s); !s_iter_end(&it); s_iter_next(&it)) + for (struct stack_iter it = s->it_start(s); !s_iter_end(&it); s_iter_next(&it)) { total += s_iter_value(&it); } cmc_assert_equals(size_t, 20100, total); - for (stack_iter it = s->it_end(s); !s_iter_start(&it); s_iter_prev(&it)) + for (struct stack_iter it = s->it_end(s); !s_iter_start(&it); s_iter_prev(&it)) { total += s_iter_value(&it); } @@ -360,7 +360,7 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(iteration[while loop], { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -368,7 +368,7 @@ CMC_CREATE_UNIT(stack_test, true, { cmc_assert(s_push(s, i)); size_t total = 0; - stack_iter it = s->it_start(s); + struct stack_iter it = s->it_start(s); do { @@ -390,19 +390,19 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(iteration[count = 1], { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); cmc_assert(s_push(s, 10)); size_t total = 0; - for (stack_iter it = s->it_start(s); !s_iter_end(&it); s_iter_next(&it)) + for (struct stack_iter it = s->it_start(s); !s_iter_end(&it); s_iter_next(&it)) { total += s_iter_value(&it); } - for (stack_iter it = s->it_end(s); !s_iter_start(&it); s_iter_prev(&it)) + for (struct stack_iter it = s->it_end(s); !s_iter_start(&it); s_iter_prev(&it)) { total += s_iter_value(&it); } @@ -413,7 +413,7 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(iteration[count = capacity], { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -424,14 +424,14 @@ CMC_CREATE_UNIT(stack_test, true, { size_t total = 0; - for (stack_iter it = s->it_start(s); !s_iter_end(&it); s_iter_next(&it)) + for (struct stack_iter it = s->it_start(s); !s_iter_end(&it); s_iter_next(&it)) { total += s_iter_value(&it); } cmc_assert_equals(size_t, 1000, total); - for (stack_iter it = s->it_end(s); !s_iter_start(&it); s_iter_prev(&it)) + for (struct stack_iter it = s->it_end(s); !s_iter_start(&it); s_iter_prev(&it)) { total += *s_iter_rvalue(&it); } @@ -442,18 +442,18 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(iteration[to_start = it_start and to_end = it_end], { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); for (size_t i = 0; i < 50; i++) cmc_assert(s_push(s, i)); - stack_iter it1; - stack_iter it2; + struct stack_iter it1; + struct stack_iter it2; - memset(&it1, 0, sizeof(stack_iter)); - memset(&it2, 0, sizeof(stack_iter)); + memset(&it1, 0, sizeof(struct stack_iter)); + memset(&it2, 0, sizeof(struct stack_iter)); s_iter_init(&it2, s); @@ -477,11 +477,11 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(iteration[boundaries count = 0], { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); - stack_iter iter; + struct stack_iter iter; s_iter_init(&iter, s); s_iter_to_end(&iter); @@ -496,14 +496,14 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(iteration[boundaries count > 0], { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); for (size_t i = 0; i < 200; i++) cmc_assert(s_push(s, i)); - stack_iter iter; + struct stack_iter iter; s_iter_init(&iter, s); s_iter_to_end(&iter); @@ -518,11 +518,11 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(iter_value[count = 0], { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); - stack_iter iter; + struct stack_iter iter; s_iter_init(&iter, s); @@ -532,11 +532,11 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(iter_rvalue[count = 0], { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); - stack_iter iter; + struct stack_iter iter; s_iter_init(&iter, s); @@ -546,7 +546,7 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(index, { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); @@ -557,24 +557,24 @@ CMC_CREATE_UNIT(stack_test, true, { size_t total = 0; - for (stack_iter it = s->it_start(s); false;) + for (struct stack_iter it = s->it_start(s); false;) { cmc_assert_equals(size_t, 0, s_iter_index(&it)); } - for (stack_iter it = s->it_start(s); false;) + for (struct stack_iter it = s->it_start(s); false;) { cmc_assert_equals(size_t, s_count(s) - 1, s_iter_index(&it)); } - for (stack_iter it = s->it_start(s); !s_iter_end(&it); s_iter_next(&it)) + for (struct stack_iter it = s->it_start(s); !s_iter_end(&it); s_iter_next(&it)) { total += s_iter_index(&it); } cmc_assert_equals(size_t, 45, total); - for (stack_iter it = s->it_end(s); !s_iter_start(&it); s_iter_prev(&it)) + for (struct stack_iter it = s->it_end(s); !s_iter_start(&it); s_iter_prev(&it)) { total += s_iter_index(&it); } @@ -585,11 +585,11 @@ CMC_CREATE_UNIT(stack_test, true, { }); CMC_CREATE_TEST(index[count = 0], { - stack *s = s_new(100); + struct stack *s = s_new(100); cmc_assert_not_equals(ptr, NULL, s); - stack_iter iter; + struct stack_iter iter; s_iter_init(&iter, s); cmc_assert_equals(size_t, 0, s_iter_index(&iter)); diff --git a/tests/main/unt/treemap.c b/tests/main/unt/treemap.c index a6c423b..3f72f27 100644 --- a/tests/main/unt/treemap.c +++ b/tests/main/unt/treemap.c @@ -9,7 +9,7 @@ CMC_GENERATE_TREEMAP(tm, treemap, size_t, size_t) CMC_CREATE_UNIT(treemap_test, true, { CMC_CREATE_TEST(new, { - treemap *map = tm_new(cmp); + struct treemap *map = tm_new(cmp); cmc_assert_not_equals(ptr, NULL, map); @@ -17,7 +17,7 @@ CMC_CREATE_UNIT(treemap_test, true, { }); CMC_CREATE_TEST(clear[count], { - treemap *map = tm_new(cmp); + struct treemap *map = tm_new(cmp); cmc_assert_not_equals(ptr, NULL, map); diff --git a/tests/main/unt/treeset.c b/tests/main/unt/treeset.c index 7972d8f..3492aae 100644 --- a/tests/main/unt/treeset.c +++ b/tests/main/unt/treeset.c @@ -9,7 +9,7 @@ CMC_GENERATE_TREESET(ts, treeset, size_t) CMC_CREATE_UNIT(treeset_test, true, { CMC_CREATE_TEST(new, { - treeset *set = ts_new(cmp); + struct treeset *set = ts_new(cmp); cmc_assert_not_equals(ptr, NULL, set); @@ -17,7 +17,7 @@ CMC_CREATE_UNIT(treeset_test, true, { }); CMC_CREATE_TEST(clear[count], { - treeset *set = ts_new(cmp); + struct treeset *set = ts_new(cmp); cmc_assert_not_equals(ptr, NULL, set); diff --git a/tests/sep/main.c b/tests/sep/main.c index 0b812ce..74a231c 100644 --- a/tests/sep/main.c +++ b/tests/sep/main.c @@ -20,20 +20,19 @@ size_t inthash(int t) int main(void) { - list *l = l_new(1000); - stack *s = s_new(1000); - queue *q = q_new(1000); - deque *d = d_new(1000); - linked *ll = ll_new(); - heap *h = h_new(1000, cmc_max_heap, intcmp); - tset *ts = ts_new(intcmp); - tmap *tm = tm_new(intcmp); - hset *hs = hs_new(1000, 0.6, intcmp, inthash); - hmap *hm = hm_new(1000, 0.6, intcmp, inthash); - - iheap *ih = ih_new(1000, intcmp); - mmap *mm = mm_new(1000, 0.8, intcmp, inthash); - mset *ms = ms_new(1000, 0.6, intcmp, inthash); + struct list *l = l_new(1000); + struct stack *s = s_new(1000); + struct queue *q = q_new(1000); + struct deque *d = d_new(1000); + struct linked *ll = ll_new(); + struct heap *h = h_new(1000, cmc_max_heap, intcmp); + struct tset *ts = ts_new(intcmp); + struct tmap *tm = tm_new(intcmp); + struct hset *hs = hs_new(1000, 0.6, intcmp, inthash); + struct hmap *hm = hm_new(1000, 0.6, intcmp, inthash); + struct iheap *ih = ih_new(1000, intcmp); + struct mmap *mm = mm_new(1000, 0.8, intcmp, inthash); + struct mset *ms = ms_new(1000, 0.6, intcmp, inthash); printf("+--------------------------------------------------+\n"); printf("| Separate Header and Source is Working |\n");