Added _equals function to all collections and fixed some issues with multimap

This commit is contained in:
Leonardo committed 2019-08-29 23:25:32 -03:00
1 parent 1f50add1bb
commit f070d274f4
13 files changed
+928 -619

No files matched your search

+124 -105
View File
@@ -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; \
+26
View File
@@ -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; \
+21
View File
@@ -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; \
+15
View File
@@ -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; \
+21
View File
@@ -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; \
+15
View File
@@ -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; \
+119 -100
View File
@@ -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; \
+426 -411
View File
@@ -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 */
+26
View File
@@ -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; \
+18
View File
@@ -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; \
+18
View File
@@ -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; \
+70 -3
View File
@@ -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; \
+29
View File
@@ -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; \