Added _equals function to all collections and fixed some issues with multimap
This commit is contained in:
1 parent
1f50add1bb
commit
f070d274f4
13 files changed
+928
-619
No files matched your search
+124
-105
@@ -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; \
|
||||
|
||||
@@ -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; \
|
||||
|
||||
@@ -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; \
|
||||
|
||||
@@ -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; \
|
||||
|
||||
@@ -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; \
|
||||
|
||||
@@ -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
@@ -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
@@ -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 */
|
||||
@@ -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; \
|
||||
|
||||
@@ -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; \
|
||||
|
||||
@@ -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
@@ -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; \
|
||||
|
||||
@@ -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; \
|
||||
|
||||
Reference in new issue
Block a user