From f070d274f4de069f33666b6df8cdbb43e4561971 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Thu, 29 Aug 2019 23:25:32 -0300 Subject: [PATCH] Added _equals function to all collections and fixed some issues with multimap --- src/cmc/deque.h | 229 +++++------ src/cmc/hashmap.h | 26 ++ src/cmc/hashset.h | 21 ++ src/cmc/heap.h | 15 + src/cmc/linkedlist.h | 21 ++ src/cmc/list.h | 15 + src/cmc/queue.h | 219 ++++++----- src/cmc/stack.h | 837 +++++++++++++++++++++-------------------- src/cmc/treemap.h | 26 ++ src/cmc/treeset.h | 18 + src/ext/intervalheap.h | 18 + src/ext/multimap.h | 73 +++- src/ext/multiset.h | 29 ++ 13 files changed, 928 insertions(+), 619 deletions(-) diff --git a/src/cmc/deque.h b/src/cmc/deque.h index 4a7e6c6..3e36c72 100644 --- a/src/cmc/deque.h +++ b/src/cmc/deque.h @@ -48,111 +48,112 @@ DEQUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) /* HEADER ********************************************************************/ -#define DEQUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - \ - /* Deque Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Dynamic circular array of elements */ \ - V *buffer; \ - \ - /* Current circular array capacity */ \ - size_t capacity; \ - \ - /* Current amount of elements */ \ - size_t count; \ - \ - /* Index representing the front of the deque */ \ - size_t front; \ - \ - /* Index representing the back of the deque */ \ - size_t back; \ - \ - /* Function that returns an iterator to the start of the deque */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the deque */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Deque Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target deque */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - FMOD SNAME *PFX##_new(size_t capacity); \ - FMOD void PFX##_clear(SNAME *_deque_, void (*deallocator)(V)); \ - FMOD void PFX##_free(SNAME *_deque_, void (*deallocator)(V)); \ - /* Collection Input and Output */ \ - FMOD bool PFX##_push_front(SNAME *_deque_, V element); \ - FMOD bool PFX##_push_back(SNAME *_deque_, V element); \ - FMOD bool PFX##_pop_front(SNAME *_deque_); \ - FMOD bool PFX##_pop_back(SNAME *_deque_); \ - /* Conditional Input and Output */ \ - FMOD bool PFX##_push_front_if(SNAME *_deque_, V element, bool condition); \ - FMOD bool PFX##_push_back_if(SNAME *_deque_, V element, bool condition); \ - FMOD bool PFX##_pop_front_if(SNAME *_deque_, bool condition); \ - FMOD bool PFX##_pop_back_if(SNAME *_deque_, bool condition); \ - /* Element Access */ \ - FMOD V PFX##_front(SNAME *_deque_); \ - FMOD V PFX##_back(SNAME *_deque_); \ - /* Collection State */ \ - FMOD bool PFX##_contains(SNAME *_deque_, V element, int (*comparator)(V, V)); \ - FMOD bool PFX##_empty(SNAME *_deque_); \ - FMOD bool PFX##_full(SNAME *_deque_); \ - FMOD size_t PFX##_count(SNAME *_deque_); \ - FMOD size_t PFX##_capacity(SNAME *_deque_); \ - /* Collection Utility */ \ - FMOD SNAME *PFX##_copy_of(SNAME *_deque_, V (*copy_func)(V)); \ - FMOD cmc_string PFX##_to_string(SNAME *_deque_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ - FMOD void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ - /* Iterator Access */ \ - FMOD V PFX##_iter_value(SNAME##_iter *iter); \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ - /* Default Value */ \ - static inline V PFX##_impl_default_value(void) \ - { \ - V _empty_value_; \ - \ - memset(&_empty_value_, 0, sizeof(V)); \ - \ - return _empty_value_; \ - } \ - \ +#define DEQUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ + \ + /* Deque Structure */ \ + typedef struct SNAME##_s \ + { \ + /* Dynamic circular array of elements */ \ + V *buffer; \ + \ + /* Current circular array capacity */ \ + size_t capacity; \ + \ + /* Current amount of elements */ \ + size_t count; \ + \ + /* Index representing the front of the deque */ \ + size_t front; \ + \ + /* Index representing the back of the deque */ \ + size_t back; \ + \ + /* Function that returns an iterator to the start of the deque */ \ + struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + \ + /* Function that returns an iterator to the end of the deque */ \ + struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + \ + } SNAME, *SNAME##_ptr; \ + \ + /* Deque Iterator */ \ + typedef struct SNAME##_iter_s \ + { \ + /* Target deque */ \ + struct SNAME##_s *target; \ + \ + /* Cursor's position (index) */ \ + size_t cursor; \ + \ + /* Keeps track of relative index to the iteration of elements */ \ + size_t index; \ + \ + /* If the iterator has reached the start of the iteration */ \ + bool start; \ + \ + /* If the iterator has reached the end of the iteration */ \ + bool end; \ + \ + } SNAME##_iter, *SNAME##_iter_ptr; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + FMOD SNAME *PFX##_new(size_t capacity); \ + FMOD void PFX##_clear(SNAME *_deque_, void (*deallocator)(V)); \ + FMOD void PFX##_free(SNAME *_deque_, void (*deallocator)(V)); \ + /* Collection Input and Output */ \ + FMOD bool PFX##_push_front(SNAME *_deque_, V element); \ + FMOD bool PFX##_push_back(SNAME *_deque_, V element); \ + FMOD bool PFX##_pop_front(SNAME *_deque_); \ + FMOD bool PFX##_pop_back(SNAME *_deque_); \ + /* Conditional Input and Output */ \ + FMOD bool PFX##_push_front_if(SNAME *_deque_, V element, bool condition); \ + FMOD bool PFX##_push_back_if(SNAME *_deque_, V element, bool condition); \ + FMOD bool PFX##_pop_front_if(SNAME *_deque_, bool condition); \ + FMOD bool PFX##_pop_back_if(SNAME *_deque_, bool condition); \ + /* Element Access */ \ + FMOD V PFX##_front(SNAME *_deque_); \ + FMOD V PFX##_back(SNAME *_deque_); \ + /* Collection State */ \ + FMOD bool PFX##_contains(SNAME *_deque_, V element, int (*comparator)(V, V)); \ + FMOD bool PFX##_empty(SNAME *_deque_); \ + FMOD bool PFX##_full(SNAME *_deque_); \ + FMOD size_t PFX##_count(SNAME *_deque_); \ + FMOD size_t PFX##_capacity(SNAME *_deque_); \ + /* Collection Utility */ \ + FMOD SNAME *PFX##_copy_of(SNAME *_deque_, V (*copy_func)(V)); \ + FMOD bool PFX##_equals(SNAME *_deque1_, SNAME *_deque2_, int (*comparator)(V, V)); \ + FMOD cmc_string PFX##_to_string(SNAME *_deque_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ + FMOD void PFX##_iter_free(SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ + /* Iterator State */ \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ + /* Iterator Movement */ \ + FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ + FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ + /* Iterator Access */ \ + FMOD V PFX##_iter_value(SNAME##_iter *iter); \ + FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \ + FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ + \ + /* Default Value */ \ + static inline V PFX##_impl_default_value(void) \ + { \ + V _empty_value_; \ + \ + memset(&_empty_value_, 0, sizeof(V)); \ + \ + return _empty_value_; \ + } \ + \ /* SOURCE ********************************************************************/ #define DEQUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ \ @@ -391,6 +392,24 @@ return result; \ } \ \ + FMOD bool PFX##_equals(SNAME *_deque1_, SNAME *_deque2_, int (*comparator)(V, V)) \ + { \ + if (PFX##_count(_deque1_) != PFX##_count(_deque2_)) \ + return false; \ + \ + size_t i, j, k; \ + for (i = _deque1_->front, j = _deque2_->front, k = 0; k < PFX##_count(_deque1_); k++) \ + { \ + if (comparator(_deque1_->buffer[i], _deque2_->buffer[j]) == 0) \ + return false; \ + \ + i = (i + 1) % _deque1_->capacity; \ + j = (j + 1) % _deque2_->capacity; \ + } \ + \ + return true; \ + } \ + \ FMOD cmc_string PFX##_to_string(SNAME *_deque_) \ { \ cmc_string str; \ diff --git a/src/cmc/hashmap.h b/src/cmc/hashmap.h index 45b5ee7..13047a6 100644 --- a/src/cmc/hashmap.h +++ b/src/cmc/hashmap.h @@ -179,6 +179,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, FMOD size_t PFX##_capacity(SNAME *_map_); \ /* Collection Utility */ \ FMOD SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)); \ + FMOD bool PFX##_equals(SNAME *_map1_, SNAME *_map2_, int (*value_comparator)(V, V)); \ FMOD cmc_string PFX##_to_string(SNAME *_map_); \ \ /* Iterator Functions */ \ @@ -571,6 +572,31 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return result; \ } \ \ + FMOD bool PFX##_equals(SNAME *_map1_, SNAME *_map2_, int (*value_comparator)(V, V)) \ + { \ + if (PFX##_count(_map1_) != PFX##_count(_map2_)) \ + return false; \ + \ + SNAME##_iter iter; \ + PFX##_iter_init(&iter, _map1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + SNAME##_entry *entry = PFX##_impl_get_entry(_map2_, PFX##_iter_key(&iter)); \ + \ + if (entry == NULL) \ + return false; \ + \ + if (value_comparator) \ + { \ + if (value_comparator(entry->value, PFX##_iter_value(&iter)) != 0) \ + return false; \ + } \ + } \ + \ + return true; \ + } \ + \ FMOD cmc_string PFX##_to_string(SNAME *_map_) \ { \ cmc_string str; \ diff --git a/src/cmc/hashset.h b/src/cmc/hashset.h index 264b259..f9151f9 100644 --- a/src/cmc/hashset.h +++ b/src/cmc/hashset.h @@ -170,6 +170,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, FMOD size_t PFX##_capacity(SNAME *_set_); \ /* Collection Utility */ \ FMOD SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)); \ + FMOD bool PFX##_equals(SNAME *_set1_, SNAME *_set2_); \ FMOD cmc_string PFX##_to_string(SNAME *_set_); \ \ /* Set Operations */ \ @@ -486,6 +487,26 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return result; \ } \ \ + FMOD bool PFX##_equals(SNAME *_set1_, SNAME *_set2_) \ + { \ + if (PFX##_count(_set1_) != PFX##_count(_set2_)) \ + return false; \ + \ + if (PFX##_count(_set1_) == 0) \ + return true; \ + \ + SNAME##_iter iter; \ + PFX##_iter_init(&iter, _set1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + if (PFX##_impl_get_entry(_set2_, PFX##_iter_value(&iter)) == NULL) \ + return false; \ + } \ + \ + return true; \ + } \ + \ FMOD cmc_string PFX##_to_string(SNAME *_set_) \ { \ cmc_string str; \ diff --git a/src/cmc/heap.h b/src/cmc/heap.h index c1602b0..6d99d84 100644 --- a/src/cmc/heap.h +++ b/src/cmc/heap.h @@ -120,6 +120,7 @@ typedef enum cmc_heap_order_e FMOD size_t PFX##_capacity(SNAME *_heap_); \ /* Collection Utility */ \ FMOD SNAME *PFX##_copy_of(SNAME *_heap_, V (*copy_func)(V)); \ + FMOD bool PFX##_equals(SNAME *_heap1_, SNAME *_heap2_); \ FMOD cmc_string PFX##_to_string(SNAME *_heap_); \ \ /* Iterator Functions */ \ @@ -345,6 +346,20 @@ typedef enum cmc_heap_order_e return result; \ } \ \ + FMOD bool PFX##_equals(SNAME *_heap1_, SNAME *_heap2_) \ + { \ + if (PFX##_count(_heap1_) != PFX##_count(_heap2_)) \ + return false; \ + \ + for (size_t i = 0; i < PFX##_count(_heap1_); i++) \ + { \ + if (_heap1_->cmp(_heap1_->buffer[i], _heap2_->buffer[i]) != 0) \ + return false; \ + } \ + \ + return true; \ + } \ + \ FMOD cmc_string PFX##_to_string(SNAME *_heap_) \ { \ cmc_string str; \ diff --git a/src/cmc/linkedlist.h b/src/cmc/linkedlist.h index a5d2b5e..71aedce 100644 --- a/src/cmc/linkedlist.h +++ b/src/cmc/linkedlist.h @@ -127,6 +127,7 @@ FMOD size_t PFX##_count(SNAME *_list_); \ /* Collection Utility */ \ FMOD SNAME *PFX##_copy_of(SNAME *_list_, V (*copy_func)(V)); \ + FMOD bool PFX##_equals(SNAME *_list1_, SNAME *_list2_, int (*comparator)(V, V)); \ FMOD cmc_string PFX##_to_string(SNAME *_list_); \ \ /* Node Related Functions */ \ @@ -508,6 +509,26 @@ return result; \ } \ \ + FMOD bool PFX##_equals(SNAME *_list1_, SNAME *_list2_, int (*comparator)(V, V)) \ + { \ + if (PFX##_count(_list1_) != PFX##_count(_list2_)) \ + return false; \ + \ + SNAME##_node *scan1 = _list1_->head; \ + SNAME##_node *scan2 = _list2_->head; \ + \ + while (scan1 != NULL && scan2 != NULL) \ + { \ + if (comparator(scan1->data, scan2->data) != 0) \ + return false; \ + \ + scan1 = scan1->next; \ + scan2 = scan2->next; \ + } \ + \ + return true; \ + } \ + \ FMOD cmc_string PFX##_to_string(SNAME *_list_) \ { \ cmc_string str; \ diff --git a/src/cmc/list.h b/src/cmc/list.h index 6bc72ea..f1a84d3 100644 --- a/src/cmc/list.h +++ b/src/cmc/list.h @@ -136,6 +136,7 @@ FMOD size_t PFX##_capacity(SNAME *_list_); \ /* Collection Utility */ \ FMOD SNAME *PFX##_copy_of(SNAME *_list_, V (*copy_func)(V)); \ + FMOD bool PFX##_equals(SNAME *_list1_, SNAME *_list2_, int (*comparator)(V, V)); \ FMOD cmc_string PFX##_to_string(SNAME *_list_); \ \ /* Iterator Functions */ \ @@ -585,6 +586,20 @@ return result; \ } \ \ + FMOD bool PFX##_equals(SNAME *_list1_, SNAME *_list2_, int (*comparator)(V, V)) \ + { \ + if (PFX##_count(_list1_) != PFX##_count(_list2_)) \ + return false; \ + \ + for (size_t i = 0; i < PFX##_count(_list1_); i++) \ + { \ + if (comparator(_list1_->buffer[i], _list2_->buffer[i]) != 0) \ + return false; \ + } \ + \ + return false; \ + } \ + \ FMOD cmc_string PFX##_to_string(SNAME *_list_) \ { \ cmc_string str; \ diff --git a/src/cmc/queue.h b/src/cmc/queue.h index 97a495f..e1c1996 100644 --- a/src/cmc/queue.h +++ b/src/cmc/queue.h @@ -60,106 +60,107 @@ QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) /* HEADER ********************************************************************/ -#define QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - \ - /* Queue Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Dynamic circular array of elements */ \ - V *buffer; \ - \ - /* Current circular array capacity */ \ - size_t capacity; \ - \ - /* Current amount of elements */ \ - size_t count; \ - \ - /* Index representing the front of the queue */ \ - size_t front; \ - \ - /* Index representing the back of the queue */ \ - size_t back; \ - \ - /* Function that returns an iterator to the start of the queue */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the queue */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Queue Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target queue */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - FMOD SNAME *PFX##_new(size_t capacity); \ - FMOD void PFX##_clear(SNAME *_queue_, void (*deallocator)(V)); \ - FMOD void PFX##_free(SNAME *_queue_, void (*deallocator)(V)); \ - /* Collection Input and Output */ \ - FMOD bool PFX##_enqueue(SNAME *_queue_, V element); \ - FMOD bool PFX##_dequeue(SNAME *_queue_); \ - /* Conditional Input and Output */ \ - FMOD bool PFX##_enqueue_if(SNAME *_queue_, V element, bool condition); \ - FMOD bool PFX##_dequeue_if(SNAME *_queue_, bool condition); \ - /* Element Access */ \ - FMOD V PFX##_peek(SNAME *_queue_); \ - /* Collection State */ \ - FMOD bool PFX##_contains(SNAME *_queue_, V element, int (*comparator)(V, V)); \ - FMOD bool PFX##_empty(SNAME *_queue_); \ - FMOD bool PFX##_full(SNAME *_queue_); \ - FMOD size_t PFX##_count(SNAME *_queue_); \ - FMOD size_t PFX##_capacity(SNAME *_queue_); \ - /* Collection Utility */ \ - FMOD SNAME *PFX##_copy_of(SNAME *_queue_, V (*copy_func)(V)); \ - FMOD cmc_string PFX##_to_string(SNAME *_queue_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ - FMOD void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ - /* Iterator Access */ \ - FMOD V PFX##_iter_value(SNAME##_iter *iter); \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ - /* Default Value */ \ - static inline V PFX##_impl_default_value(void) \ - { \ - V _empty_value_; \ - \ - memset(&_empty_value_, 0, sizeof(V)); \ - \ - return _empty_value_; \ - } \ - \ +#define QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ + \ + /* Queue Structure */ \ + typedef struct SNAME##_s \ + { \ + /* Dynamic circular array of elements */ \ + V *buffer; \ + \ + /* Current circular array capacity */ \ + size_t capacity; \ + \ + /* Current amount of elements */ \ + size_t count; \ + \ + /* Index representing the front of the queue */ \ + size_t front; \ + \ + /* Index representing the back of the queue */ \ + size_t back; \ + \ + /* Function that returns an iterator to the start of the queue */ \ + struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + \ + /* Function that returns an iterator to the end of the queue */ \ + struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + \ + } SNAME, *SNAME##_ptr; \ + \ + /* Queue Iterator */ \ + typedef struct SNAME##_iter_s \ + { \ + /* Target queue */ \ + struct SNAME##_s *target; \ + \ + /* Cursor's position (index) */ \ + size_t cursor; \ + \ + /* Keeps track of relative index to the iteration of elements */ \ + size_t index; \ + \ + /* If the iterator has reached the start of the iteration */ \ + bool start; \ + \ + /* If the iterator has reached the end of the iteration */ \ + bool end; \ + \ + } SNAME##_iter, *SNAME##_iter_ptr; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + FMOD SNAME *PFX##_new(size_t capacity); \ + FMOD void PFX##_clear(SNAME *_queue_, void (*deallocator)(V)); \ + FMOD void PFX##_free(SNAME *_queue_, void (*deallocator)(V)); \ + /* Collection Input and Output */ \ + FMOD bool PFX##_enqueue(SNAME *_queue_, V element); \ + FMOD bool PFX##_dequeue(SNAME *_queue_); \ + /* Conditional Input and Output */ \ + FMOD bool PFX##_enqueue_if(SNAME *_queue_, V element, bool condition); \ + FMOD bool PFX##_dequeue_if(SNAME *_queue_, bool condition); \ + /* Element Access */ \ + FMOD V PFX##_peek(SNAME *_queue_); \ + /* Collection State */ \ + FMOD bool PFX##_contains(SNAME *_queue_, V element, int (*comparator)(V, V)); \ + FMOD bool PFX##_empty(SNAME *_queue_); \ + FMOD bool PFX##_full(SNAME *_queue_); \ + FMOD size_t PFX##_count(SNAME *_queue_); \ + FMOD size_t PFX##_capacity(SNAME *_queue_); \ + /* Collection Utility */ \ + FMOD SNAME *PFX##_copy_of(SNAME *_queue_, V (*copy_func)(V)); \ + FMOD bool PFX##_equals(SNAME *_queue1_, SNAME *_queue2_, int (*comparator)(V, V)); \ + FMOD cmc_string PFX##_to_string(SNAME *_queue_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ + FMOD void PFX##_iter_free(SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ + /* Iterator State */ \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ + /* Iterator Movement */ \ + FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ + FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ + /* Iterator Access */ \ + FMOD V PFX##_iter_value(SNAME##_iter *iter); \ + FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \ + FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ + \ + /* Default Value */ \ + static inline V PFX##_impl_default_value(void) \ + { \ + V _empty_value_; \ + \ + memset(&_empty_value_, 0, sizeof(V)); \ + \ + return _empty_value_; \ + } \ + \ /* SOURCE ********************************************************************/ #define QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ \ @@ -341,6 +342,24 @@ return result; \ } \ \ + FMOD 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; \ + } \ + \ FMOD cmc_string PFX##_to_string(SNAME *_queue_) \ { \ cmc_string str; \ diff --git a/src/cmc/stack.h b/src/cmc/stack.h index 46bc5ad..7a2ea22 100644 --- a/src/cmc/stack.h +++ b/src/cmc/stack.h @@ -45,418 +45,433 @@ STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, V) /* HEADER ********************************************************************/ -#define STACK_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - \ - /* Stack Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Dynamic array of elements */ \ - V *buffer; \ - \ - /* Current array capacity */ \ - size_t capacity; \ - \ - /* Current amount of elements */ \ - size_t count; \ - \ - /* Function that returns an iterator to the start of the stack */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the stack */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Stack Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target stack */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - FMOD SNAME *PFX##_new(size_t capacity); \ - FMOD void PFX##_clear(SNAME *_stack_, void (*deallocator)(V)); \ - FMOD void PFX##_free(SNAME *_stack_, void (*deallocator)(V)); \ - /* Collection Input and Output */ \ - FMOD bool PFX##_push(SNAME *_stack_, V element); \ - FMOD bool PFX##_pop(SNAME *_stack_); \ - /* Conditional Input and Output */ \ - FMOD bool PFX##_push_if(SNAME *_stack_, V element, bool condition); \ - FMOD bool PFX##_pop_if(SNAME *_stack_, bool condition); \ - /* Element Access */ \ - FMOD V PFX##_top(SNAME *_stack_); \ - /* Collection State */ \ - FMOD bool PFX##_contains(SNAME *_stack_, V element, int (*comparator)(V, V)); \ - FMOD bool PFX##_empty(SNAME *_stack_); \ - FMOD bool PFX##_full(SNAME *_stack_); \ - FMOD size_t PFX##_count(SNAME *_stack_); \ - FMOD size_t PFX##_capacity(SNAME *_stack_); \ - /* Collection Utility */ \ - FMOD SNAME *PFX##_copy_of(SNAME *_stack_, V (*copy_func)(V)); \ - FMOD cmc_string PFX##_to_string(SNAME *_stack_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ - FMOD void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ - /* Iterator Access */ \ - FMOD V PFX##_iter_value(SNAME##_iter *iter); \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ - /* Default Value */ \ - static inline V PFX##_impl_default_value(void) \ - { \ - V _empty_value_; \ - \ - memset(&_empty_value_, 0, sizeof(V)); \ - \ - return _empty_value_; \ - } \ - \ +#define STACK_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ + \ + /* Stack Structure */ \ + typedef struct SNAME##_s \ + { \ + /* Dynamic array of elements */ \ + V *buffer; \ + \ + /* Current array capacity */ \ + size_t capacity; \ + \ + /* Current amount of elements */ \ + size_t count; \ + \ + /* Function that returns an iterator to the start of the stack */ \ + struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + \ + /* Function that returns an iterator to the end of the stack */ \ + struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + \ + } SNAME, *SNAME##_ptr; \ + \ + /* Stack Iterator */ \ + typedef struct SNAME##_iter_s \ + { \ + /* Target stack */ \ + struct SNAME##_s *target; \ + \ + /* Cursor's position (index) */ \ + size_t cursor; \ + \ + /* If the iterator has reached the start of the iteration */ \ + bool start; \ + \ + /* If the iterator has reached the end of the iteration */ \ + bool end; \ + \ + } SNAME##_iter, *SNAME##_iter_ptr; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + FMOD SNAME *PFX##_new(size_t capacity); \ + FMOD void PFX##_clear(SNAME *_stack_, void (*deallocator)(V)); \ + FMOD void PFX##_free(SNAME *_stack_, void (*deallocator)(V)); \ + /* Collection Input and Output */ \ + FMOD bool PFX##_push(SNAME *_stack_, V element); \ + FMOD bool PFX##_pop(SNAME *_stack_); \ + /* Conditional Input and Output */ \ + FMOD bool PFX##_push_if(SNAME *_stack_, V element, bool condition); \ + FMOD bool PFX##_pop_if(SNAME *_stack_, bool condition); \ + /* Element Access */ \ + FMOD V PFX##_top(SNAME *_stack_); \ + /* Collection State */ \ + FMOD bool PFX##_contains(SNAME *_stack_, V element, int (*comparator)(V, V)); \ + FMOD bool PFX##_empty(SNAME *_stack_); \ + FMOD bool PFX##_full(SNAME *_stack_); \ + FMOD size_t PFX##_count(SNAME *_stack_); \ + FMOD size_t PFX##_capacity(SNAME *_stack_); \ + /* Collection Utility */ \ + FMOD SNAME *PFX##_copy_of(SNAME *_stack_, V (*copy_func)(V)); \ + FMOD bool PFX##_equals(SNAME *_stack1_, SNAME *_stack2_, int (*comparator)(V, V)); \ + FMOD cmc_string PFX##_to_string(SNAME *_stack_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ + FMOD void PFX##_iter_free(SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ + /* Iterator State */ \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ + /* Iterator Movement */ \ + FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ + FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ + /* Iterator Access */ \ + FMOD V PFX##_iter_value(SNAME##_iter *iter); \ + FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \ + FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ + \ + /* Default Value */ \ + static inline V PFX##_impl_default_value(void) \ + { \ + V _empty_value_; \ + \ + memset(&_empty_value_, 0, sizeof(V)); \ + \ + return _empty_value_; \ + } \ + \ /* SOURCE ********************************************************************/ -#define STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ - \ - /* Implementation Detail Functions */ \ - static bool PFX##_impl_grow(SNAME *_stack_); \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_stack_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_stack_); \ - \ - FMOD SNAME *PFX##_new(size_t capacity) \ - { \ - if (capacity < 1) \ - return NULL; \ - \ - SNAME *_stack_ = malloc(sizeof(SNAME)); \ - \ - if (!_stack_) \ - return NULL; \ - \ - _stack_->buffer = malloc(sizeof(V) * capacity); \ - \ - if (!_stack_->buffer) \ - { \ - free(_stack_); \ - return NULL; \ - } \ - \ - memset(_stack_->buffer, 0, sizeof(V) * capacity); \ - \ - _stack_->capacity = capacity; \ - _stack_->count = 0; \ - \ - _stack_->it_start = PFX##_impl_it_start; \ - _stack_->it_end = PFX##_impl_it_end; \ - \ - return _stack_; \ - } \ - \ - FMOD void PFX##_clear(SNAME *_stack_, void (*deallocator)(V)) \ - { \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _stack_->count; i++) \ - deallocator(_stack_->buffer[i]); \ - } \ - \ - memset(_stack_->buffer, 0, sizeof(V) * _stack_->capacity); \ - \ - _stack_->count = 0; \ - } \ - \ - FMOD void PFX##_free(SNAME *_stack_, void (*deallocator)(V)) \ - { \ - free(_stack_->buffer); \ - if (deallocator) \ - { \ - for (size_t i = 0; i < _stack_->count; i++) \ - deallocator(_stack_->buffer[i]); \ - } \ - \ - free(_stack_); \ - } \ - \ - FMOD bool PFX##_push(SNAME *_stack_, V element) \ - { \ - if (PFX##_full(_stack_)) \ - { \ - if (!PFX##_impl_grow(_stack_)) \ - return false; \ - } \ - \ - _stack_->buffer[_stack_->count++] = element; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_pop(SNAME *_stack_) \ - { \ - if (PFX##_empty(_stack_)) \ - return false; \ - \ - _stack_->buffer[--_stack_->count] = PFX##_impl_default_value(); \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_push_if(SNAME *_stack_, V element, bool condition) \ - { \ - if (condition) \ - return PFX##_push(_stack_, element); \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_pop_if(SNAME *_stack_, bool condition) \ - { \ - if (condition) \ - return PFX##_pop(_stack_); \ - \ - return false; \ - } \ - \ - FMOD V PFX##_top(SNAME *_stack_) \ - { \ - if (PFX##_empty(_stack_)) \ - return PFX##_impl_default_value(); \ - \ - return _stack_->buffer[_stack_->count - 1]; \ - } \ - \ - FMOD bool PFX##_contains(SNAME *_stack_, V element, int (*comparator)(V, V)) \ - { \ - for (size_t i = 0; i < _stack_->count; i++) \ - { \ - if (comparator(_stack_->buffer[i], element) == 0) \ - return true; \ - } \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_empty(SNAME *_stack_) \ - { \ - return _stack_->count == 0; \ - } \ - \ - FMOD bool PFX##_full(SNAME *_stack_) \ - { \ - return _stack_->count >= _stack_->capacity; \ - } \ - \ - FMOD size_t PFX##_count(SNAME *_stack_) \ - { \ - return _stack_->count; \ - } \ - \ - FMOD size_t PFX##_capacity(SNAME *_stack_) \ - { \ - return _stack_->capacity; \ - } \ - \ - FMOD SNAME *PFX##_copy_of(SNAME *_stack_, V (*copy_func)(V)) \ - { \ - SNAME *result = PFX##_new(_stack_->capacity); \ - \ - if (!result) \ - return NULL; \ - \ - if (copy_func) \ - { \ - for (size_t i = 0; i < _stack_->count; i++) \ - result->buffer[i] = copy_func(_stack_->buffer[i]); \ - } \ - else \ - memcpy(result->buffer, _stack_->buffer, sizeof(V) * _stack_->count); \ - \ - result->count = _stack_->count; \ - \ - return result; \ - } \ - \ - FMOD cmc_string PFX##_to_string(SNAME *_stack_) \ - { \ - cmc_string str; \ - SNAME *s_ = _stack_; \ - const char *name = #SNAME; \ - \ - snprintf(str.s, cmc_string_len, cmc_string_fmt_stack, \ - name, s_, s_->buffer, s_->capacity, s_->count); \ - \ - return str; \ - } \ - \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ - { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - FMOD void PFX##_iter_free(SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ - { \ - iter->target = target; \ - \ - if (PFX##_empty(target)) \ - iter->cursor = 0; \ - else \ - iter->cursor = iter->target->count - 1; \ - \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - } \ - \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ - { \ - iter->cursor = iter->target->count - 1; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - } \ - \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ - { \ - iter->cursor = 0; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - } \ - \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - if (iter->cursor == 0) \ - { \ - iter->end = true; \ - \ - return false; \ - } \ - else \ - iter->cursor--; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - if (iter->cursor == iter->target->count - 1) \ - { \ - iter->start = true; \ - \ - return false; \ - } \ - else \ - iter->cursor++; \ - \ - return true; \ - } \ - \ - FMOD V PFX##_iter_value(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return PFX##_impl_default_value(); \ - \ - return iter->target->buffer[iter->cursor]; \ - } \ - \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->target->buffer[iter->cursor]); \ - } \ - \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return 0; \ - \ - return iter->target->count - 1 - iter->cursor; \ - } \ - \ - static bool PFX##_impl_grow(SNAME *_stack_) \ - { \ - size_t new_capacity = _stack_->capacity * 2; \ - \ - V *new_buffer = realloc(_stack_->buffer, sizeof(V) * new_capacity); \ - \ - if (!new_buffer) \ - return false; \ - \ - _stack_->buffer = new_buffer; \ - _stack_->capacity = new_capacity; \ - \ - return true; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_stack_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _stack_); \ - PFX##_iter_to_start(&iter); \ - \ - return iter; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_stack_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _stack_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ +#define STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ + \ + /* Implementation Detail Functions */ \ + static bool PFX##_impl_grow(SNAME *_stack_); \ + static SNAME##_iter PFX##_impl_it_start(SNAME *_stack_); \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_stack_); \ + \ + FMOD SNAME *PFX##_new(size_t capacity) \ + { \ + if (capacity < 1) \ + return NULL; \ + \ + SNAME *_stack_ = malloc(sizeof(SNAME)); \ + \ + if (!_stack_) \ + return NULL; \ + \ + _stack_->buffer = malloc(sizeof(V) * capacity); \ + \ + if (!_stack_->buffer) \ + { \ + free(_stack_); \ + return NULL; \ + } \ + \ + memset(_stack_->buffer, 0, sizeof(V) * capacity); \ + \ + _stack_->capacity = capacity; \ + _stack_->count = 0; \ + \ + _stack_->it_start = PFX##_impl_it_start; \ + _stack_->it_end = PFX##_impl_it_end; \ + \ + return _stack_; \ + } \ + \ + FMOD void PFX##_clear(SNAME *_stack_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _stack_->count; i++) \ + deallocator(_stack_->buffer[i]); \ + } \ + \ + memset(_stack_->buffer, 0, sizeof(V) * _stack_->capacity); \ + \ + _stack_->count = 0; \ + } \ + \ + FMOD void PFX##_free(SNAME *_stack_, void (*deallocator)(V)) \ + { \ + free(_stack_->buffer); \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _stack_->count; i++) \ + deallocator(_stack_->buffer[i]); \ + } \ + \ + free(_stack_); \ + } \ + \ + FMOD bool PFX##_push(SNAME *_stack_, V element) \ + { \ + if (PFX##_full(_stack_)) \ + { \ + if (!PFX##_impl_grow(_stack_)) \ + return false; \ + } \ + \ + _stack_->buffer[_stack_->count++] = element; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_pop(SNAME *_stack_) \ + { \ + if (PFX##_empty(_stack_)) \ + return false; \ + \ + _stack_->buffer[--_stack_->count] = PFX##_impl_default_value(); \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_push_if(SNAME *_stack_, V element, bool condition) \ + { \ + if (condition) \ + return PFX##_push(_stack_, element); \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_pop_if(SNAME *_stack_, bool condition) \ + { \ + if (condition) \ + return PFX##_pop(_stack_); \ + \ + return false; \ + } \ + \ + FMOD V PFX##_top(SNAME *_stack_) \ + { \ + if (PFX##_empty(_stack_)) \ + return PFX##_impl_default_value(); \ + \ + return _stack_->buffer[_stack_->count - 1]; \ + } \ + \ + FMOD bool PFX##_contains(SNAME *_stack_, V element, int (*comparator)(V, V)) \ + { \ + for (size_t i = 0; i < _stack_->count; i++) \ + { \ + if (comparator(_stack_->buffer[i], element) == 0) \ + return true; \ + } \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_empty(SNAME *_stack_) \ + { \ + return _stack_->count == 0; \ + } \ + \ + FMOD bool PFX##_full(SNAME *_stack_) \ + { \ + return _stack_->count >= _stack_->capacity; \ + } \ + \ + FMOD size_t PFX##_count(SNAME *_stack_) \ + { \ + return _stack_->count; \ + } \ + \ + FMOD size_t PFX##_capacity(SNAME *_stack_) \ + { \ + return _stack_->capacity; \ + } \ + \ + FMOD SNAME *PFX##_copy_of(SNAME *_stack_, V (*copy_func)(V)) \ + { \ + SNAME *result = PFX##_new(_stack_->capacity); \ + \ + if (!result) \ + return NULL; \ + \ + if (copy_func) \ + { \ + for (size_t i = 0; i < _stack_->count; i++) \ + result->buffer[i] = copy_func(_stack_->buffer[i]); \ + } \ + else \ + memcpy(result->buffer, _stack_->buffer, sizeof(V) * _stack_->count); \ + \ + result->count = _stack_->count; \ + \ + return result; \ + } \ + \ + FMOD bool PFX##_equals(SNAME *_stack1_, SNAME *_stack2_, int (*comparator)(V, V)) \ + { \ + if (PFX##_count(_stack1_) != PFX##_count(_stack2_)) \ + return false; \ + \ + for (size_t i = 0; i < PFX##_count(_stack1_); i++) \ + { \ + if (comparator(_stack1_->buffer[i], _stack2_->buffer[i]) != 0) \ + return false; \ + } \ + \ + return true; \ + } \ + \ + FMOD cmc_string PFX##_to_string(SNAME *_stack_) \ + { \ + cmc_string str; \ + SNAME *s_ = _stack_; \ + const char *name = #SNAME; \ + \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_stack, \ + name, s_, s_->buffer, s_->capacity, s_->count); \ + \ + return str; \ + } \ + \ + FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ + { \ + SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + FMOD void PFX##_iter_free(SNAME##_iter *iter) \ + { \ + free(iter); \ + } \ + \ + FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + { \ + iter->target = target; \ + \ + if (PFX##_empty(target)) \ + iter->cursor = 0; \ + else \ + iter->cursor = iter->target->count - 1; \ + \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + } \ + \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ + { \ + iter->cursor = iter->target->count - 1; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ + \ + FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ + { \ + iter->cursor = 0; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + } \ + \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ + { \ + if (iter->end) \ + return false; \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + if (iter->cursor == 0) \ + { \ + iter->end = true; \ + \ + return false; \ + } \ + else \ + iter->cursor--; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + if (iter->cursor == iter->target->count - 1) \ + { \ + iter->start = true; \ + \ + return false; \ + } \ + else \ + iter->cursor++; \ + \ + return true; \ + } \ + \ + FMOD V PFX##_iter_value(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return PFX##_impl_default_value(); \ + \ + return iter->target->buffer[iter->cursor]; \ + } \ + \ + FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return NULL; \ + \ + return &(iter->target->buffer[iter->cursor]); \ + } \ + \ + FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return 0; \ + \ + return iter->target->count - 1 - iter->cursor; \ + } \ + \ + static bool PFX##_impl_grow(SNAME *_stack_) \ + { \ + size_t new_capacity = _stack_->capacity * 2; \ + \ + V *new_buffer = realloc(_stack_->buffer, sizeof(V) * new_capacity); \ + \ + if (!new_buffer) \ + return false; \ + \ + _stack_->buffer = new_buffer; \ + _stack_->capacity = new_capacity; \ + \ + return true; \ + } \ + \ + static SNAME##_iter PFX##_impl_it_start(SNAME *_stack_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _stack_); \ + PFX##_iter_to_start(&iter); \ + \ + return iter; \ + } \ + \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_stack_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _stack_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_STACK_H */ diff --git a/src/cmc/treemap.h b/src/cmc/treemap.h index 952b908..9cb87e2 100644 --- a/src/cmc/treemap.h +++ b/src/cmc/treemap.h @@ -131,6 +131,7 @@ FMOD size_t PFX##_count(SNAME *_map_); \ /* Collection Utility */ \ FMOD SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)); \ + FMOD bool PFX##_equals(SNAME *_map1_, SNAME *_map2_, int (*value_comparator)(V, V)); \ FMOD cmc_string PFX##_to_string(SNAME *_map_); \ \ /* Iterator Functions */ \ @@ -603,6 +604,31 @@ return result; \ } \ \ + FMOD bool PFX##_equals(SNAME *_map1_, SNAME *_map2_, int (*value_comparator)(V, V)) \ + { \ + if (PFX##_count(_map1_) != PFX##_count(_map2_)) \ + return false; \ + \ + SNAME##_iter iter; \ + PFX##_iter_init(&iter, _map1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + SNAME##_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; \ + } \ + \ FMOD cmc_string PFX##_to_string(SNAME *_map_) \ { \ cmc_string str; \ diff --git a/src/cmc/treeset.h b/src/cmc/treeset.h index 37d52ad..d6ede3a 100644 --- a/src/cmc/treeset.h +++ b/src/cmc/treeset.h @@ -124,6 +124,7 @@ FMOD size_t PFX##_count(SNAME *_set_); \ /* Collection Utility */ \ FMOD SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)); \ + FMOD bool PFX##_equals(SNAME *_set1_, SNAME *_set2_); \ FMOD cmc_string PFX##_to_string(SNAME *_set_); \ \ /* Set Operations */ \ @@ -539,6 +540,23 @@ return result; \ } \ \ + FMOD bool PFX##_equals(SNAME *_set1_, SNAME *_set2_) \ + { \ + if (PFX##_count(_set1_) != PFX##_count(_set2_)) \ + return false; \ + \ + SNAME##_iter iter; \ + PFX##_iter_init(&iter, _set1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + if (PFX##_impl_get_node(_set2_, PFX##_iter_value(&iter)) == NULL) \ + return false; \ + } \ + \ + return true; \ + } \ + \ FMOD cmc_string PFX##_to_string(SNAME *_set_) \ { \ cmc_string str; \ diff --git a/src/ext/intervalheap.h b/src/ext/intervalheap.h index 323d885..ce5f43d 100644 --- a/src/ext/intervalheap.h +++ b/src/ext/intervalheap.h @@ -119,6 +119,7 @@ FMOD size_t PFX##_capacity(SNAME *_heap_); \ /* Collection Utility */ \ FMOD SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)); \ + FMOD bool PFX##_equals(SNAME *_heap1_, SNAME *_heap2_); \ FMOD cmc_string PFX##_to_string(SNAME *_heap_); \ \ /* Iterator Functions */ \ @@ -530,6 +531,23 @@ return result; \ } \ \ + FMOD 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; \ + } \ + \ FMOD cmc_string PFX##_to_string(SNAME *_heap_) \ { \ cmc_string str; \ diff --git a/src/ext/multimap.h b/src/ext/multimap.h index 6b6f02f..7555d63 100644 --- a/src/ext/multimap.h +++ b/src/ext/multimap.h @@ -196,11 +196,13 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, FMOD size_t PFX##_remove_all(SNAME *_map_, K key); \ /* Collection State */ \ FMOD bool PFX##_contains(SNAME *_map_, K key); \ + FMOD bool PFX##_key_count(SNAME *_map_, K key); \ FMOD bool PFX##_empty(SNAME *_map_); \ FMOD size_t PFX##_count(SNAME *_map_); \ FMOD size_t PFX##_capacity(SNAME *_map_); \ /* Collection Utility */ \ FMOD SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)); \ + FMOD bool PFX##_equals(SNAME *_map1_, SNAME *_map2_, bool ignore_key_count); \ FMOD cmc_string PFX##_to_string(SNAME *_map_); \ \ /* Iterator Functions */ \ @@ -285,6 +287,9 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, _map_->cmp = compare; \ _map_->hash = hash; \ \ + _map_->it_start = PFX##_impl_it_start; \ + _map_->it_end = PFX##_impl_it_end; \ + \ return _map_; \ } \ \ @@ -300,7 +305,12 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, if (scan != NULL) \ { \ if (scan->next == NULL && scan->prev == NULL) \ + { \ + if (deallocator) \ + deallocator(scan->key, scan->value); \ + \ free(scan); \ + } \ else \ { \ while (scan != NULL) \ @@ -309,7 +319,8 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ scan = scan->next; \ \ - deallocator(tmp->key, tmp->scan); \ + if (deallocator) \ + deallocator(tmp->key, tmp->value); \ \ free(tmp); \ } \ @@ -345,7 +356,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ scan = scan->next; \ \ - deallocator(tmp->key, tmp->scan); \ + deallocator(tmp->key, tmp->value); \ \ free(tmp); \ } \ @@ -695,6 +706,28 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return PFX##_impl_get_entry(_map_, key) != NULL; \ } \ \ + FMOD bool PFX##_key_count(SNAME *_map_, K key) \ + { \ + size_t hash = _map_->hash(key); \ + \ + SNAME##_entry *entry = _map_->buffer[hash % _map_->capacity][0]; \ + \ + size_t total_count = 0; \ + \ + if (!entry) \ + return total_count; \ + \ + while (entry != NULL) \ + { \ + if (_map_->cmp(entry->key, key) == 0) \ + total_count++; \ + \ + entry = entry->next; \ + } \ + \ + return total_count; \ + } \ + \ FMOD bool PFX##_empty(SNAME *_map_) \ { \ return _map_->count == 0; \ @@ -739,13 +772,47 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return result; \ } \ \ + FMOD bool PFX##_equals(SNAME *_map1_, SNAME *_map2_, bool ignore_key_count) \ + { \ + if (ignore_key_count) \ + { \ + SNAME##_iter iter; \ + PFX##_iter_init(&iter, _map1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + if (PFX##_impl_get_entry(_map2_, PFX##_iter_key(&iter)) == NULL) \ + return false; \ + } \ + } \ + else \ + { \ + /* Since the key count matters this can be checked and an early exit */ \ + if (PFX##_count(_map1_) != PFX##_count(_map2_)) \ + return false; \ + \ + SNAME##_iter iter; \ + PFX##_iter_init(&iter, _map1_); \ + \ + for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ + { \ + K key = PFX##_iter_key(&iter); \ + \ + if (PFX##_key_count(_map1_, key) != PFX##_key_count(_map2_, key)) \ + return false; \ + } \ + } \ + \ + return true; \ + } \ + \ FMOD cmc_string PFX##_to_string(SNAME *_map_) \ { \ cmc_string str; \ SNAME *m_ = _map_; \ const char *name = #SNAME; \ \ - snprintf(str.s, cmc_string_len, cmc_string_fmt_hashmap, \ + 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; \ diff --git a/src/ext/multiset.h b/src/ext/multiset.h index 6578c42..3603385 100644 --- a/src/ext/multiset.h +++ b/src/ext/multiset.h @@ -184,6 +184,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, FMOD size_t PFX##_capacity(SNAME *_set_); \ /* Collection Utility */ \ FMOD SNAME *PFX##_copy_of(SNAME *_set_, V (*copy_func)(V)); \ + FMOD bool PFX##_equals(SNAME *_set1_, SNAME *_set2_, bool ignore_multiplicity); \ FMOD cmc_string PFX##_to_string(SNAME *_set_); \ \ /* Set Operations */ \ @@ -553,6 +554,34 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return result; \ } \ \ + FMOD bool PFX##_equals(SNAME *_set1_, SNAME *_set2_, bool ignore_multiplicity) \ + { \ + if (PFX##_count(_set1_) != PFX##_count(_set2_)) \ + return false; \ + \ + if (!ignore_multiplicity && PFX##_cardinality(_set1_) != PFX##_cardinality(_set2_)) \ + return false; \ + \ + if (PFX##_count(_set1_) == 0) \ + return true; \ + \ + 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)); \ + \ + if (entry == NULL) \ + return false; \ + \ + if (!ignore_multiplicity && entry->multiplicity != PFX##_iter_multiplicity(&iter)) \ + return false; \ + } \ + \ + return true; \ + } \ + \ FMOD cmc_string PFX##_to_string(SNAME *_set_) \ { \ cmc_string str; \