diff --git a/src/cmc/bidimap.h b/src/cmc/bidimap.h index 552f10f..d7371d6 100644 --- a/src/cmc/bidimap.h +++ b/src/cmc/bidimap.h @@ -19,8 +19,6 @@ #include "../utl/cmc_string.h" /** - * THIS IS A PREVIEW ONLY - * * BidiMap * * A bidirectional map is a map that allows you to create a bijection in both @@ -197,6 +195,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, 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_); \ @@ -227,7 +226,6 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, #define CMC_GENERATE_BIDIMAP_SOURCE(PFX, SNAME, K, V) \ \ /* Implementation Detail Functions */ \ - static bool PFX##_impl_grow(SNAME *_map_); \ 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); \ @@ -314,7 +312,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, { \ if (PFX##_full(_map_)) \ { \ - if (!PFX##_impl_grow(_map_)) \ + if (!PFX##_resize(_map_, PFX##_capacity(_map_) + 1)) \ return false; \ } \ \ @@ -431,14 +429,145 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, 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)) \ { \ - return NULL; \ + 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_) \ { \ - return false; \ + 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_) \ @@ -674,12 +803,6 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return iter->index; \ } \ \ - static bool PFX##_impl_grow(SNAME *_map_) \ - { \ - /* TODO */ \ - return false; \ - } \ - \ static SNAME##_entry *PFX##_impl_new_entry(K key, V value) \ { \ SNAME##_entry *entry = malloc(sizeof(SNAME##_entry)); \ diff --git a/src/cmc/deque.h b/src/cmc/deque.h index 9928836..a767054 100644 --- a/src/cmc/deque.h +++ b/src/cmc/deque.h @@ -164,7 +164,7 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI if (!_deque_) \ return NULL; \ \ - _deque_->buffer = malloc(sizeof(V) * capacity); \ + _deque_->buffer = calloc(capacity, sizeof(V)); \ \ if (!_deque_->buffer) \ { \ @@ -172,8 +172,6 @@ static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRI return NULL; \ } \ \ - memset(_deque_->buffer, 0, sizeof(V) * capacity); \ - \ _deque_->capacity = capacity; \ _deque_->count = 0; \ _deque_->front = 0; \ diff --git a/src/cmc/hashmap.h b/src/cmc/hashmap.h index 9bba615..7360021 100644 --- a/src/cmc/hashmap.h +++ b/src/cmc/hashmap.h @@ -239,7 +239,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, if (!_map_) \ return NULL; \ \ - _map_->buffer = malloc(sizeof(SNAME##_entry) * real_capacity); \ + _map_->buffer = calloc(real_capacity, sizeof(SNAME##_entry)); \ \ if (!_map_->buffer) \ { \ @@ -247,8 +247,6 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return NULL; \ } \ \ - memset(_map_->buffer, 0, sizeof(SNAME##_entry) * real_capacity); \ - \ _map_->count = 0; \ _map_->capacity = real_capacity; \ _map_->load = load; \ diff --git a/src/cmc/hashset.h b/src/cmc/hashset.h index a89fea3..d4470a8 100644 --- a/src/cmc/hashset.h +++ b/src/cmc/hashset.h @@ -239,7 +239,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, if (!_set_) \ return NULL; \ \ - _set_->buffer = malloc(sizeof(SNAME##_entry) * real_capacity); \ + _set_->buffer = calloc(real_capacity, sizeof(SNAME##_entry)); \ \ if (!_set_->buffer) \ { \ @@ -247,8 +247,6 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return NULL; \ } \ \ - memset(_set_->buffer, 0, sizeof(SNAME##_entry) * real_capacity); \ - \ _set_->count = 0; \ _set_->capacity = real_capacity; \ _set_->load = load; \ diff --git a/src/cmc/heap.h b/src/cmc/heap.h index 06693a8..42e7975 100644 --- a/src/cmc/heap.h +++ b/src/cmc/heap.h @@ -167,7 +167,7 @@ typedef enum cmc_heap_order_e if (!_heap_) \ return NULL; \ \ - _heap_->buffer = malloc(sizeof(V) * capacity); \ + _heap_->buffer = calloc(capacity, sizeof(V)); \ \ if (!_heap_->buffer) \ { \ @@ -175,8 +175,6 @@ typedef enum cmc_heap_order_e return NULL; \ } \ \ - memset(_heap_->buffer, 0, sizeof(V) * capacity); \ - \ _heap_->capacity = capacity; \ _heap_->count = 0; \ _heap_->HO = HO; \ diff --git a/src/cmc/intervalheap.h b/src/cmc/intervalheap.h index 77289c8..69c7908 100644 --- a/src/cmc/intervalheap.h +++ b/src/cmc/intervalheap.h @@ -169,7 +169,7 @@ static const char *cmc_string_fmt_intervalheap = "%s at %p { buffer:%p, capacity /* Round the capacity of nodes up */ \ capacity = capacity % 2 == 0 ? capacity / 2 : (capacity + 1) / 2; \ \ - _heap_->buffer = malloc(sizeof(SNAME##_node) * capacity); \ + _heap_->buffer = calloc(capacity, sizeof(SNAME##_node)); \ \ if (!_heap_->buffer) \ { \ @@ -177,8 +177,6 @@ static const char *cmc_string_fmt_intervalheap = "%s at %p { buffer:%p, capacity return NULL; \ } \ \ - memset(_heap_->buffer, 0, sizeof(SNAME##_node) * capacity); \ - \ _heap_->capacity = capacity; \ _heap_->size = 0; \ _heap_->count = 0; \ diff --git a/src/cmc/list.h b/src/cmc/list.h index 09425a0..50e5fd7 100644 --- a/src/cmc/list.h +++ b/src/cmc/list.h @@ -180,7 +180,7 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu if (!_list_) \ return NULL; \ \ - _list_->buffer = malloc(capacity * sizeof(V)); \ + _list_->buffer = calloc(capacity, sizeof(V)); \ \ if (!_list_->buffer) \ { \ @@ -188,8 +188,6 @@ static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIu return NULL; \ } \ \ - memset(_list_->buffer, 0, capacity * sizeof(V)); \ - \ _list_->capacity = capacity; \ _list_->count = 0; \ \ diff --git a/src/cmc/multimap.h b/src/cmc/multimap.h index 4a917f3..5d09ada 100644 --- a/src/cmc/multimap.h +++ b/src/cmc/multimap.h @@ -256,7 +256,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, if (!_map_) \ return NULL; \ \ - _map_->buffer = malloc(sizeof(SNAME##_entry_ptr[2]) * real_capacity); \ + _map_->buffer = calloc(real_capacity, sizeof(SNAME##_entry_ptr[2])); \ \ if (!_map_->buffer) \ { \ @@ -264,8 +264,6 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return NULL; \ } \ \ - memset(_map_->buffer, 0, sizeof(SNAME##_entry_ptr[2]) * real_capacity); \ - \ _map_->count = 0; \ _map_->capacity = real_capacity; \ _map_->load = load; \ diff --git a/src/cmc/multiset.h b/src/cmc/multiset.h index e072e59..8db56eb 100644 --- a/src/cmc/multiset.h +++ b/src/cmc/multiset.h @@ -256,7 +256,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, if (!_set_) \ return NULL; \ \ - _set_->buffer = malloc(sizeof(SNAME##_entry) * real_capacity); \ + _set_->buffer = calloc(real_capacity, sizeof(SNAME##_entry)); \ \ if (!_set_->buffer) \ { \ @@ -264,8 +264,6 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return NULL; \ } \ \ - memset(_set_->buffer, 0, sizeof(SNAME##_entry) * real_capacity); \ - \ _set_->count = 0; \ _set_->cardinality = 0; \ _set_->capacity = real_capacity; \ diff --git a/src/cmc/queue.h b/src/cmc/queue.h index 4fdf2ff..8215e96 100644 --- a/src/cmc/queue.h +++ b/src/cmc/queue.h @@ -173,7 +173,7 @@ static const char *cmc_string_fmt_queue = "%s at %p { buffer:%p, capacity:%" PRI if (!_queue_) \ return NULL; \ \ - _queue_->buffer = malloc(sizeof(V) * capacity); \ + _queue_->buffer = calloc(capacity, sizeof(V)); \ \ if (!_queue_->buffer) \ { \ @@ -181,8 +181,6 @@ static const char *cmc_string_fmt_queue = "%s at %p { buffer:%p, capacity:%" PRI return NULL; \ } \ \ - memset(_queue_->buffer, 0, sizeof(V) * capacity); \ - \ _queue_->capacity = capacity; \ _queue_->count = 0; \ _queue_->front = 0; \ diff --git a/src/cmc/sortedlist.h b/src/cmc/sortedlist.h index a63efcc..aedeca3 100644 --- a/src/cmc/sortedlist.h +++ b/src/cmc/sortedlist.h @@ -9,8 +9,6 @@ */ /** - * THIS IS ONLY A PREVIEW - * * SortedList * * A sorted list is a dynamic array, meaning that you can store as many elements @@ -360,6 +358,9 @@ static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:% if (PFX##_count(_list1_) != PFX##_count(_list2_)) \ return false; \ \ + PFX##_sort(_list1_); \ + PFX##_sort(_list2_); \ + \ for (size_t i = 0; i < PFX##_count(_list1_); i++) \ { \ if (_list1_->cmp(_list1_->buffer[i], _list2_->buffer[i]) != 0) \ diff --git a/src/cmc/stack.h b/src/cmc/stack.h index 50a0b49..6df60b9 100644 --- a/src/cmc/stack.h +++ b/src/cmc/stack.h @@ -149,7 +149,7 @@ static const char *cmc_string_fmt_stack = "%s at %p { buffer:%p, capacity:%" PRI if (!_stack_) \ return NULL; \ \ - _stack_->buffer = malloc(sizeof(V) * capacity); \ + _stack_->buffer = calloc(capacity, sizeof(V)); \ \ if (!_stack_->buffer) \ { \ @@ -157,8 +157,6 @@ static const char *cmc_string_fmt_stack = "%s at %p { buffer:%p, capacity:%" PRI return NULL; \ } \ \ - memset(_stack_->buffer, 0, sizeof(V) * capacity); \ - \ _stack_->capacity = capacity; \ _stack_->count = 0; \ \