diff --git a/Documentation.md b/Documentation.md
index 757de4e..52faf03 100644
--- a/Documentation.md
+++ b/Documentation.md
@@ -136,15 +136,15 @@ The iterator is a simple structure that is capable of going back and forwards. A
## [ \_new() ](#list_function_index)
-Allocates and returns a new list with an internal capacity of `size`. If allocation fails, `NULL` is returned.
+Allocates and returns a new list with an internal capacity of the specified value. If allocation fails, `NULL` is returned.
#### Declaration
-> `FMOD SNAME *PFX##_new(size_t size);`
+> `FMOD SNAME *PFX##_new(size_t capacity);`
#### Parameters
-1. `size_t size` - The initial capacity for the list.
+1. `size_t capacity` - The initial capacity for the list.
#### Returns
@@ -1028,15 +1028,15 @@ A Stack is used in algorithms like backtracking, depth-first search, expression
## [ \_new() ](#stack_function_index)
-Allocates and returns a new stack with an internal capacity of `size`. If allocation fails, `NULL` is returned.
+Allocates and returns a new stack with an internal capacity of the specified value. If allocation fails, `NULL` is returned.
#### Declaration
-> `FMOD SNAME *PFX##_new(size_t size);`
+> `FMOD SNAME *PFX##_new(size_t capacity);`
#### Parameters
-1. `size_t size` - The initial capacity for the stack.
+1. `size_t capacity` - The initial capacity for the stack.
#### Returns
@@ -1545,15 +1545,15 @@ The queue is used in many applications where a resource is shared among multiple
## [ \_new() ](#queue_function_index)
-Allocates and returns a new queue with an internal capacity of `size`. If allocation fails, `NULL` is returned.
+Allocates and returns a new queue with an internal capacity of the specified value. If allocation fails, `NULL` is returned.
#### Declaration
-> `FMOD SNAME *PFX##_new(size_t size);`
+> `FMOD SNAME *PFX##_new(size_t capacity);`
#### Parameters
-1. `size_t size` - The initial capacity for the queue.
+1. `size_t capacity` - The initial capacity for the queue.
#### Returns
@@ -2062,15 +2062,15 @@ A double-ended queue backed by a circular buffer. Elements can be added and remo
## [ \_new() ](#deque_function_index)
-Allocates and returns a new deque with an internal capacity of `size`. If allocation fails, `NULL` is returned.
+Allocates and returns a new deque with an internal capacity of the specified value. If allocation fails, `NULL` is returned.
#### Declaration
-> `FMOD SNAME *PFX##_new(size_t size);`
+> `FMOD SNAME *PFX##_new(size_t capacity);`
#### Parameters
-1. `size_t size` - The initial capacity for the deque.
+1. `size_t capacity` - The initial capacity for the deque.
#### Returns
diff --git a/TODO b/TODO
index 224148c..43505a9 100644
--- a/TODO
+++ b/TODO
@@ -25,27 +25,24 @@ Before 2.0
OK - Allow for struct to be a possible data type (instead of just pointer to struct)
OK - Set functions: is_subset, is_proper_subset, is_superset, is_proper_superset, is_disjointset
Iterator move and move_to
- from_array - Creates a collection with all the elements in a specified array
- to_array - Creates an array with all the elements inside the collection
1.6
+ from_array - Creates a collection with all the elements in a specified array
+ to_array - Creates an array with all the elements inside the collection
LinkedList - Insert/Remove/Append/Prepend/Extract
Resize buffer function
Add dispose method to each collection in order to automatically free its data
+ Add copy functions (copy of a collection)
2.0
- Add multiset, multimap and new heap implementation
+ Add new heap collection implementation
+ Add stack based collections
2.1
- Adapt multiset, multimap and new heap implementation to the current standards
+ Add variadic macros (generate only the necessary functions)
2.2
Add serialization functions
- Header:
- %d - Type specifier (LIST = 0, DEQUE = 1, STACK = 2, etc) for quick check
- %llu - How many elements there are
- %d - If data varies in size
- %llu - Data size
2.3
Iterator functions (functions that operate relative to iterators position) like add or remove ranges
diff --git a/src/deque.h b/src/deque.h
index 8bbc193..e4f78c7 100644
--- a/src/deque.h
+++ b/src/deque.h
@@ -80,7 +80,7 @@
\
/* Collection Functions */ \
/* Collection Allocation and Deallocation */ \
- FMOD SNAME *PFX##_new(size_t size); \
+ FMOD SNAME *PFX##_new(size_t capacity); \
FMOD void PFX##_clear(SNAME *_deque_); \
FMOD void PFX##_free(SNAME *_deque_); \
/* Collection Input and Output */ \
@@ -140,9 +140,9 @@
static SNAME##_iter PFX##_impl_it_start(SNAME *_deque_); \
static SNAME##_iter PFX##_impl_it_end(SNAME *_deque_); \
\
- FMOD SNAME *PFX##_new(size_t size) \
+ FMOD SNAME *PFX##_new(size_t capacity) \
{ \
- if (size < 1) \
+ if (capacity < 1) \
return NULL; \
\
SNAME *_deque_ = malloc(sizeof(SNAME)); \
@@ -150,7 +150,7 @@
if (!_deque_) \
return NULL; \
\
- _deque_->buffer = malloc(sizeof(V) * size); \
+ _deque_->buffer = malloc(sizeof(V) * capacity); \
\
if (!_deque_->buffer) \
{ \
@@ -158,9 +158,9 @@
return NULL; \
} \
\
- memset(_deque_->buffer, 0, sizeof(V) * size); \
+ memset(_deque_->buffer, 0, sizeof(V) * capacity); \
\
- _deque_->capacity = size; \
+ _deque_->capacity = capacity; \
_deque_->count = 0; \
_deque_->front = 0; \
_deque_->back = 0; \
diff --git a/src/hashmap.h b/src/hashmap.h
index 4eca9a5..6efde97 100644
--- a/src/hashmap.h
+++ b/src/hashmap.h
@@ -74,642 +74,642 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
HASHMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V)
/* HEADER ********************************************************************/
-#define HASHMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \
- \
- /* Hashmap Structure */ \
- typedef struct SNAME##_s \
- { \
- /* Array of Entries */ \
- struct SNAME##_entry_s *buffer; \
- \
- /* Current array capacity */ \
- size_t capacity; \
- \
- /* Current amount of keys */ \
- size_t count; \
- \
- /* Load factor in range (0.0, 1.0) */ \
- double load; \
- \
- /* Key comparison function */ \
- int (*cmp)(K, K); \
- \
- /* Key hash function */ \
- size_t (*hash)(K); \
- \
- /* Function that returns an iterator to the start of the hashmap */ \
- struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
- \
- /* Function that returns an iterator to the end of the hashmap */ \
- struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
- \
- } SNAME, *SNAME##_ptr; \
- \
- /* Hashmap Entry */ \
- typedef struct SNAME##_entry_s \
- { \
- /* Entry Key */ \
- K key; \
- \
- /* Entry Value */ \
- V value; \
- \
- /* The distance of this node to its original position, used by robin-hood hashing */ \
- size_t dist; \
- \
- /* The sate of this node (DELETED, EMPTY, FILLED) */ \
- enum EntryState_e state; \
- \
- } SNAME##_entry, *SNAME##_entry_ptr; \
- \
- /* Hashmap Iterator */ \
- typedef struct SNAME##_iter_s \
- { \
- /* Target hashmap */ \
- struct SNAME##_s *target; \
- \
- /* Cursor's position (index) */ \
- size_t cursor; \
- \
- /* Keeps track of relative index to the iteration of elements */ \
- size_t index; \
- \
- /* The index of the first element */ \
- size_t first; \
- \
- /* The index of the last element */ \
- size_t last; \
- \
- /* If the iterator has reached the start of the iteration */ \
- bool start; \
- \
- /* If the iterator has reached the end of the iteration */ \
- bool end; \
- \
- } SNAME##_iter, *SNAME##_iter_ptr; \
- \
- /* Collection Functions */ \
- /* Collection Allocation and Deallocation */ \
- FMOD SNAME *PFX##_new(size_t size, double load, int (*compare)(K, K), size_t (*hash)(K)); \
- FMOD void PFX##_clear(SNAME *_map_); \
- FMOD void PFX##_free(SNAME *_map_); \
- /* Collection Input and Output */ \
- FMOD bool PFX##_insert(SNAME *_map_, K key, V value); \
- FMOD bool PFX##_remove(SNAME *_map_, K key, V *value); \
- /* Conditional Input and Output */ \
- FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition); \
- FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition); \
- /* Element Access */ \
- FMOD bool PFX##_max(SNAME *_map_, K *key, V *value); \
- FMOD bool PFX##_min(SNAME *_map_, K *key, V *value); \
- FMOD V PFX##_get(SNAME *_map_, K key); \
- FMOD V *PFX##_get_ref(SNAME *_map_, K key); \
- /* Collection State */ \
- FMOD bool PFX##_contains(SNAME *_map_, K key); \
- FMOD bool PFX##_empty(SNAME *_map_); \
- FMOD size_t PFX##_count(SNAME *_map_); \
- FMOD size_t PFX##_capacity(SNAME *_map_); \
- \
- /* 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 K PFX##_iter_key(SNAME##_iter *iter); \
- 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 Key */ \
- static inline K PFX##_impl_default_key(void) \
- { \
- K _empty_key_; \
- \
- memset(&_empty_key_, 0, sizeof(K)); \
- \
- return _empty_key_; \
- } \
- \
- /* Default Value */ \
- static inline V PFX##_impl_default_value(void) \
- { \
- V _empty_value_; \
- \
- memset(&_empty_value_, 0, sizeof(V)); \
- \
- return _empty_value_; \
- } \
- \
+#define HASHMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \
+ \
+ /* Hashmap Structure */ \
+ typedef struct SNAME##_s \
+ { \
+ /* Array of Entries */ \
+ struct SNAME##_entry_s *buffer; \
+ \
+ /* Current array capacity */ \
+ size_t capacity; \
+ \
+ /* Current amount of keys */ \
+ size_t count; \
+ \
+ /* Load factor in range (0.0, 1.0) */ \
+ double load; \
+ \
+ /* Key comparison function */ \
+ int (*cmp)(K, K); \
+ \
+ /* Key hash function */ \
+ size_t (*hash)(K); \
+ \
+ /* Function that returns an iterator to the start of the hashmap */ \
+ struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
+ \
+ /* Function that returns an iterator to the end of the hashmap */ \
+ struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
+ \
+ } SNAME, *SNAME##_ptr; \
+ \
+ /* Hashmap Entry */ \
+ typedef struct SNAME##_entry_s \
+ { \
+ /* Entry Key */ \
+ K key; \
+ \
+ /* Entry Value */ \
+ V value; \
+ \
+ /* The distance of this node to its original position, used by robin-hood hashing */ \
+ size_t dist; \
+ \
+ /* The sate of this node (DELETED, EMPTY, FILLED) */ \
+ enum EntryState_e state; \
+ \
+ } SNAME##_entry, *SNAME##_entry_ptr; \
+ \
+ /* Hashmap Iterator */ \
+ typedef struct SNAME##_iter_s \
+ { \
+ /* Target hashmap */ \
+ struct SNAME##_s *target; \
+ \
+ /* Cursor's position (index) */ \
+ size_t cursor; \
+ \
+ /* Keeps track of relative index to the iteration of elements */ \
+ size_t index; \
+ \
+ /* The index of the first element */ \
+ size_t first; \
+ \
+ /* The index of the last element */ \
+ size_t last; \
+ \
+ /* If the iterator has reached the start of the iteration */ \
+ bool start; \
+ \
+ /* If the iterator has reached the end of the iteration */ \
+ bool end; \
+ \
+ } SNAME##_iter, *SNAME##_iter_ptr; \
+ \
+ /* Collection Functions */ \
+ /* Collection Allocation and Deallocation */ \
+ FMOD SNAME *PFX##_new(size_t capacity, double load, int (*compare)(K, K), size_t (*hash)(K)); \
+ FMOD void PFX##_clear(SNAME *_map_); \
+ FMOD void PFX##_free(SNAME *_map_); \
+ /* Collection Input and Output */ \
+ FMOD bool PFX##_insert(SNAME *_map_, K key, V value); \
+ FMOD bool PFX##_remove(SNAME *_map_, K key, V *value); \
+ /* Conditional Input and Output */ \
+ FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition); \
+ FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition); \
+ /* Element Access */ \
+ FMOD bool PFX##_max(SNAME *_map_, K *key, V *value); \
+ FMOD bool PFX##_min(SNAME *_map_, K *key, V *value); \
+ FMOD V PFX##_get(SNAME *_map_, K key); \
+ FMOD V *PFX##_get_ref(SNAME *_map_, K key); \
+ /* Collection State */ \
+ FMOD bool PFX##_contains(SNAME *_map_, K key); \
+ FMOD bool PFX##_empty(SNAME *_map_); \
+ FMOD size_t PFX##_count(SNAME *_map_); \
+ FMOD size_t PFX##_capacity(SNAME *_map_); \
+ \
+ /* 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 K PFX##_iter_key(SNAME##_iter *iter); \
+ 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 Key */ \
+ static inline K PFX##_impl_default_key(void) \
+ { \
+ K _empty_key_; \
+ \
+ memset(&_empty_key_, 0, sizeof(K)); \
+ \
+ return _empty_key_; \
+ } \
+ \
+ /* Default Value */ \
+ static inline V PFX##_impl_default_value(void) \
+ { \
+ V _empty_value_; \
+ \
+ memset(&_empty_value_, 0, sizeof(V)); \
+ \
+ return _empty_value_; \
+ } \
+ \
/* SOURCE ********************************************************************/
-#define HASHMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) \
- \
- /* Implementation Detail Functions */ \
- static bool PFX##_impl_grow(SNAME *_map_); \
- static SNAME##_entry *PFX##_impl_get_entry(SNAME *_map_, K key); \
- static size_t PFX##_impl_calculate_size(size_t required); \
- static SNAME##_iter PFX##_impl_it_start(SNAME *_map_); \
- static SNAME##_iter PFX##_impl_it_end(SNAME *_map_); \
- \
- FMOD SNAME *PFX##_new(size_t size, double load, int (*compare)(K, K), size_t (*hash)(K)) \
- { \
- if (size == 0 || load <= 0 || load >= 1) \
- return NULL; \
- \
- size_t real_size = PFX##_impl_calculate_size(size); \
- \
- SNAME *_map_ = malloc(sizeof(SNAME)); \
- \
- if (!_map_) \
- return NULL; \
- \
- _map_->buffer = malloc(sizeof(SNAME##_entry) * real_size); \
- \
- if (!_map_->buffer) \
- { \
- free(_map_); \
- return NULL; \
- } \
- \
- memset(_map_->buffer, 0, sizeof(SNAME##_entry) * real_size); \
- \
- _map_->count = 0; \
- _map_->capacity = real_size; \
- _map_->load = load; \
- _map_->cmp = compare; \
- _map_->hash = hash; \
- \
- _map_->it_start = PFX##_impl_it_start; \
- _map_->it_end = PFX##_impl_it_end; \
- \
- return _map_; \
- } \
- \
- FMOD void PFX##_clear(SNAME *_map_) \
- { \
- memset(_map_->buffer, 0, sizeof(SNAME##_entry) * _map_->capacity); \
- \
- _map_->count = 0; \
- } \
- \
- FMOD void PFX##_free(SNAME *_map_) \
- { \
- free(_map_->buffer); \
- free(_map_); \
- } \
- \
- FMOD bool PFX##_insert(SNAME *_map_, K key, V value) \
- { \
- if ((double)_map_->capacity * _map_->load <= (double)_map_->count) \
- { \
- if (!PFX##_impl_grow(_map_)) \
- return false; \
- } \
- \
- size_t hash = _map_->hash(key); \
- size_t original_pos = hash % _map_->capacity; \
- size_t pos = original_pos; \
- \
- SNAME##_entry *target = &(_map_->buffer[pos]); \
- \
- if (PFX##_impl_get_entry(_map_, key) != NULL) \
- return false; \
- \
- if (target->state == ES_EMPTY || target->state == ES_DELETED) \
- { \
- target->key = key; \
- target->value = value; \
- target->dist = original_pos - pos; \
- target->state = ES_FILLED; \
- } \
- else \
- { \
- while (true) \
- { \
- pos++; \
- target = &(_map_->buffer[pos % _map_->capacity]); \
- \
- if (target->state == ES_EMPTY || target->state == ES_DELETED) \
- { \
- target->key = key; \
- target->value = value; \
- target->dist = pos - original_pos; \
- target->state = ES_FILLED; \
- \
- break; \
- } \
- else if (target->dist < original_pos - pos) \
- { \
- K tmp_k = target->key; \
- V tmp_v = target->value; \
- size_t tmp_dist = target->dist; \
- \
- target->key = key; \
- target->value = value; \
- target->dist = pos - original_pos; \
- \
- key = tmp_k; \
- value = tmp_v; \
- original_pos = pos - tmp_dist; \
- } \
- } \
- } \
- \
- _map_->count++; \
- \
- return true; \
- } \
- \
- FMOD bool PFX##_remove(SNAME *_map_, K key, V *value) \
- { \
- SNAME##_entry *result = PFX##_impl_get_entry(_map_, key); \
- \
- if (result == NULL) \
- return false; \
- \
- *value = result->value; \
- \
- result->key = PFX##_impl_default_key(); \
- result->value = PFX##_impl_default_value(); \
- result->dist = 0; \
- result->state = ES_DELETED; \
- \
- _map_->count--; \
- \
- return true; \
- } \
- \
- FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition) \
- { \
- if (condition) \
- return PFX##_insert(_map_, key, value); \
- \
- return false; \
- } \
- \
- FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition) \
- { \
- if (condition) \
- return PFX##_remove(_map_, key, value); \
- \
- return false; \
- } \
- \
- FMOD bool PFX##_max(SNAME *_map_, K *key, V *value) \
- { \
- if (PFX##_empty(_map_)) \
- return false; \
- \
- SNAME##_iter iter; \
- \
- for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
- { \
- K result_key = PFX##_iter_key(&iter); \
- V result_value = PFX##_iter_value(&iter); \
- size_t index = PFX##_iter_index(&iter); \
- \
- if (index == 0) \
- { \
- *key = result_key; \
- *value = result_value; \
- } \
- else if (_map_->cmp(result_key, *key) > 0) \
- { \
- *key = result_key; \
- *value = result_value; \
- } \
- } \
- \
- return true; \
- } \
- \
- FMOD bool PFX##_min(SNAME *_map_, K *key, V *value) \
- { \
- if (PFX##_empty(_map_)) \
- return false; \
- \
- SNAME##_iter iter; \
- \
- for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
- { \
- K result_key = PFX##_iter_key(&iter); \
- V result_value = PFX##_iter_value(&iter); \
- size_t index = PFX##_iter_index(&iter); \
- \
- if (index == 0) \
- { \
- *key = result_key; \
- *value = result_value; \
- } \
- else if (_map_->cmp(result_key, *key) < 0) \
- { \
- *key = result_key; \
- *value = result_value; \
- } \
- } \
- \
- return true; \
- } \
- \
- FMOD V PFX##_get(SNAME *_map_, K key) \
- { \
- SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \
- \
- if (!entry) \
- PFX##_impl_default_value(); \
- \
- return entry->value; \
- } \
- \
- FMOD V *PFX##_get_ref(SNAME *_map_, K key) \
- { \
- SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \
- \
- if (!entry) \
- return NULL; \
- \
- return &(entry->value); \
- } \
- \
- FMOD bool PFX##_contains(SNAME *_map_, K key) \
- { \
- return PFX##_impl_get_entry(_map_, key) != NULL; \
- } \
- \
- FMOD bool PFX##_empty(SNAME *_map_) \
- { \
- return _map_->count == 0; \
- } \
- \
- FMOD size_t PFX##_count(SNAME *_map_) \
- { \
- return _map_->count; \
- } \
- \
- FMOD size_t PFX##_capacity(SNAME *_map_) \
- { \
- return _map_->capacity; \
- } \
- \
- 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; \
- iter->cursor = 0; \
- iter->index = 0; \
- iter->start = true; \
- iter->end = PFX##_empty(target); \
- \
- if (!PFX##_empty(target)) \
- { \
- for (size_t i = 0; i < target->capacity; i++) \
- { \
- if (target->buffer[i].state == ES_FILLED) \
- { \
- iter->first = i; \
- break; \
- } \
- } \
- \
- iter->cursor = iter->first; \
- \
- for (size_t i = target->capacity; i > 0; i--) \
- { \
- if (target->buffer[i - 1].state == ES_FILLED) \
- { \
- iter->last = i - 1; \
- break; \
- } \
- } \
- } \
- } \
- \
- 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->first; \
- iter->index = 0; \
- iter->start = true; \
- iter->end = PFX##_empty(iter->target); \
- } \
- \
- FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \
- { \
- iter->cursor = iter->last; \
- iter->index = iter->target->count - 1; \
- iter->start = PFX##_empty(iter->target); \
- iter->end = true; \
- } \
- \
- FMOD bool PFX##_iter_next(SNAME##_iter *iter) \
- { \
- if (iter->end) \
- return false; \
- \
- SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \
- \
- if (iter->cursor == iter->last) \
- { \
- iter->end = true; \
- \
- return false; \
- } \
- \
- iter->index++; \
- \
- while (1) \
- { \
- iter->cursor++; \
- scan = &(iter->target->buffer[iter->cursor]); \
- \
- if (scan->state == ES_FILLED) \
- break; \
- } \
- \
- iter->start = PFX##_empty(iter->target); \
- \
- return true; \
- } \
- \
- FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \
- { \
- if (iter->start) \
- return false; \
- \
- SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \
- \
- if (iter->cursor == iter->first) \
- { \
- iter->start = true; \
- \
- return false; \
- } \
- \
- iter->index--; \
- \
- while (1) \
- { \
- iter->cursor--; \
- scan = &(iter->target->buffer[iter->cursor]); \
- \
- if (scan->state == ES_FILLED) \
- break; \
- } \
- \
- iter->end = PFX##_empty(iter->target); \
- \
- return true; \
- } \
- \
- FMOD K PFX##_iter_key(SNAME##_iter *iter) \
- { \
- if (PFX##_empty(iter->target)) \
- PFX##_impl_default_key(); \
- \
- return iter->target->buffer[iter->cursor].key; \
- } \
- \
- FMOD V PFX##_iter_value(SNAME##_iter *iter) \
- { \
- if (PFX##_empty(iter->target)) \
- PFX##_impl_default_value(); \
- \
- return iter->target->buffer[iter->cursor].value; \
- } \
- \
- FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \
- { \
- if (PFX##_empty(iter->target)) \
- return NULL; \
- \
- return &(iter->target->buffer[iter->cursor].value); \
- } \
- \
- FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \
- { \
- return iter->index; \
- } \
- \
- static bool PFX##_impl_grow(SNAME *_map_) \
- { \
- size_t new_size = PFX##_impl_calculate_size(_map_->capacity + _map_->capacity / 2); \
- \
- SNAME *_new_map_ = PFX##_new(new_size, _map_->load, _map_->cmp, _map_->hash); \
- \
- if (!_new_map_) \
- return false; \
- \
- SNAME##_iter iter; \
- \
- for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
- { \
- K key = PFX##_iter_key(&iter); \
- V value = PFX##_iter_value(&iter); \
- \
- PFX##_insert(_new_map_, key, value); \
- } \
- \
- if (_map_->count != _new_map_->count) \
- { \
- PFX##_free(_new_map_); \
- return false; \
- } \
- \
- SNAME##_entry *tmp = _map_->buffer; \
- _map_->buffer = _new_map_->buffer; \
- _new_map_->buffer = tmp; \
- \
- _map_->capacity = _new_map_->capacity; \
- \
- PFX##_free(_new_map_); \
- \
- return true; \
- } \
- \
- static SNAME##_entry *PFX##_impl_get_entry(SNAME *_map_, K key) \
- { \
- size_t hash = _map_->hash(key); \
- size_t pos = hash % _map_->capacity; \
- \
- SNAME##_entry *target = &(_map_->buffer[pos]); \
- \
- while (target->state == ES_FILLED || target->state == ES_DELETED) \
- { \
- if (_map_->cmp(target->key, key) == 0) \
- return target; \
- \
- pos++; \
- target = &(_map_->buffer[pos % _map_->capacity]); \
- } \
- \
- return NULL; \
- } \
- \
- static size_t PFX##_impl_calculate_size(size_t required) \
- { \
- const size_t count = sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]); \
- \
- if (cmc_hashtable_primes[count - 1] < required) \
- return required; \
- \
- size_t i = 0; \
- while (cmc_hashtable_primes[i] < required) \
- i++; \
- \
- return cmc_hashtable_primes[i]; \
- } \
- \
- static SNAME##_iter PFX##_impl_it_start(SNAME *_map_) \
- { \
- SNAME##_iter iter; \
- \
- PFX##_iter_init(&iter, _map_); \
- \
- return iter; \
- } \
- \
- static SNAME##_iter PFX##_impl_it_end(SNAME *_map_) \
- { \
- SNAME##_iter iter; \
- \
- PFX##_iter_init(&iter, _map_); \
- PFX##_iter_to_end(&iter); \
- \
- return iter; \
+#define HASHMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) \
+ \
+ /* Implementation Detail Functions */ \
+ static bool PFX##_impl_grow(SNAME *_map_); \
+ static SNAME##_entry *PFX##_impl_get_entry(SNAME *_map_, K key); \
+ static size_t PFX##_impl_calculate_size(size_t required); \
+ static SNAME##_iter PFX##_impl_it_start(SNAME *_map_); \
+ static SNAME##_iter PFX##_impl_it_end(SNAME *_map_); \
+ \
+ FMOD SNAME *PFX##_new(size_t capacity, double load, int (*compare)(K, K), size_t (*hash)(K)) \
+ { \
+ if (capacity == 0 || load <= 0 || load >= 1) \
+ return NULL; \
+ \
+ size_t real_capacity = PFX##_impl_calculate_size(capacity / load); \
+ \
+ SNAME *_map_ = malloc(sizeof(SNAME)); \
+ \
+ if (!_map_) \
+ return NULL; \
+ \
+ _map_->buffer = malloc(sizeof(SNAME##_entry) * real_capacity); \
+ \
+ if (!_map_->buffer) \
+ { \
+ free(_map_); \
+ return NULL; \
+ } \
+ \
+ memset(_map_->buffer, 0, sizeof(SNAME##_entry) * real_capacity); \
+ \
+ _map_->count = 0; \
+ _map_->capacity = real_capacity; \
+ _map_->load = load; \
+ _map_->cmp = compare; \
+ _map_->hash = hash; \
+ \
+ _map_->it_start = PFX##_impl_it_start; \
+ _map_->it_end = PFX##_impl_it_end; \
+ \
+ return _map_; \
+ } \
+ \
+ FMOD void PFX##_clear(SNAME *_map_) \
+ { \
+ memset(_map_->buffer, 0, sizeof(SNAME##_entry) * _map_->capacity); \
+ \
+ _map_->count = 0; \
+ } \
+ \
+ FMOD void PFX##_free(SNAME *_map_) \
+ { \
+ free(_map_->buffer); \
+ free(_map_); \
+ } \
+ \
+ FMOD bool PFX##_insert(SNAME *_map_, K key, V value) \
+ { \
+ if ((double)_map_->capacity * _map_->load <= (double)_map_->count) \
+ { \
+ if (!PFX##_impl_grow(_map_)) \
+ return false; \
+ } \
+ \
+ size_t hash = _map_->hash(key); \
+ size_t original_pos = hash % _map_->capacity; \
+ size_t pos = original_pos; \
+ \
+ SNAME##_entry *target = &(_map_->buffer[pos]); \
+ \
+ if (PFX##_impl_get_entry(_map_, key) != NULL) \
+ return false; \
+ \
+ if (target->state == ES_EMPTY || target->state == ES_DELETED) \
+ { \
+ target->key = key; \
+ target->value = value; \
+ target->dist = original_pos - pos; \
+ target->state = ES_FILLED; \
+ } \
+ else \
+ { \
+ while (true) \
+ { \
+ pos++; \
+ target = &(_map_->buffer[pos % _map_->capacity]); \
+ \
+ if (target->state == ES_EMPTY || target->state == ES_DELETED) \
+ { \
+ target->key = key; \
+ target->value = value; \
+ target->dist = pos - original_pos; \
+ target->state = ES_FILLED; \
+ \
+ break; \
+ } \
+ else if (target->dist < original_pos - pos) \
+ { \
+ K tmp_k = target->key; \
+ V tmp_v = target->value; \
+ size_t tmp_dist = target->dist; \
+ \
+ target->key = key; \
+ target->value = value; \
+ target->dist = pos - original_pos; \
+ \
+ key = tmp_k; \
+ value = tmp_v; \
+ original_pos = pos - tmp_dist; \
+ } \
+ } \
+ } \
+ \
+ _map_->count++; \
+ \
+ return true; \
+ } \
+ \
+ FMOD bool PFX##_remove(SNAME *_map_, K key, V *value) \
+ { \
+ SNAME##_entry *result = PFX##_impl_get_entry(_map_, key); \
+ \
+ if (result == NULL) \
+ return false; \
+ \
+ *value = result->value; \
+ \
+ result->key = PFX##_impl_default_key(); \
+ result->value = PFX##_impl_default_value(); \
+ result->dist = 0; \
+ result->state = ES_DELETED; \
+ \
+ _map_->count--; \
+ \
+ return true; \
+ } \
+ \
+ FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition) \
+ { \
+ if (condition) \
+ return PFX##_insert(_map_, key, value); \
+ \
+ return false; \
+ } \
+ \
+ FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition) \
+ { \
+ if (condition) \
+ return PFX##_remove(_map_, key, value); \
+ \
+ return false; \
+ } \
+ \
+ FMOD bool PFX##_max(SNAME *_map_, K *key, V *value) \
+ { \
+ if (PFX##_empty(_map_)) \
+ return false; \
+ \
+ SNAME##_iter iter; \
+ \
+ for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
+ { \
+ K result_key = PFX##_iter_key(&iter); \
+ V result_value = PFX##_iter_value(&iter); \
+ size_t index = PFX##_iter_index(&iter); \
+ \
+ if (index == 0) \
+ { \
+ *key = result_key; \
+ *value = result_value; \
+ } \
+ else if (_map_->cmp(result_key, *key) > 0) \
+ { \
+ *key = result_key; \
+ *value = result_value; \
+ } \
+ } \
+ \
+ return true; \
+ } \
+ \
+ FMOD bool PFX##_min(SNAME *_map_, K *key, V *value) \
+ { \
+ if (PFX##_empty(_map_)) \
+ return false; \
+ \
+ SNAME##_iter iter; \
+ \
+ for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
+ { \
+ K result_key = PFX##_iter_key(&iter); \
+ V result_value = PFX##_iter_value(&iter); \
+ size_t index = PFX##_iter_index(&iter); \
+ \
+ if (index == 0) \
+ { \
+ *key = result_key; \
+ *value = result_value; \
+ } \
+ else if (_map_->cmp(result_key, *key) < 0) \
+ { \
+ *key = result_key; \
+ *value = result_value; \
+ } \
+ } \
+ \
+ return true; \
+ } \
+ \
+ FMOD V PFX##_get(SNAME *_map_, K key) \
+ { \
+ SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \
+ \
+ if (!entry) \
+ PFX##_impl_default_value(); \
+ \
+ return entry->value; \
+ } \
+ \
+ FMOD V *PFX##_get_ref(SNAME *_map_, K key) \
+ { \
+ SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \
+ \
+ if (!entry) \
+ return NULL; \
+ \
+ return &(entry->value); \
+ } \
+ \
+ FMOD bool PFX##_contains(SNAME *_map_, K key) \
+ { \
+ return PFX##_impl_get_entry(_map_, key) != NULL; \
+ } \
+ \
+ FMOD bool PFX##_empty(SNAME *_map_) \
+ { \
+ return _map_->count == 0; \
+ } \
+ \
+ FMOD size_t PFX##_count(SNAME *_map_) \
+ { \
+ return _map_->count; \
+ } \
+ \
+ FMOD size_t PFX##_capacity(SNAME *_map_) \
+ { \
+ return _map_->capacity; \
+ } \
+ \
+ 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; \
+ iter->cursor = 0; \
+ iter->index = 0; \
+ iter->start = true; \
+ iter->end = PFX##_empty(target); \
+ \
+ if (!PFX##_empty(target)) \
+ { \
+ for (size_t i = 0; i < target->capacity; i++) \
+ { \
+ if (target->buffer[i].state == ES_FILLED) \
+ { \
+ iter->first = i; \
+ break; \
+ } \
+ } \
+ \
+ iter->cursor = iter->first; \
+ \
+ for (size_t i = target->capacity; i > 0; i--) \
+ { \
+ if (target->buffer[i - 1].state == ES_FILLED) \
+ { \
+ iter->last = i - 1; \
+ break; \
+ } \
+ } \
+ } \
+ } \
+ \
+ 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->first; \
+ iter->index = 0; \
+ iter->start = true; \
+ iter->end = PFX##_empty(iter->target); \
+ } \
+ \
+ FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \
+ { \
+ iter->cursor = iter->last; \
+ iter->index = iter->target->count - 1; \
+ iter->start = PFX##_empty(iter->target); \
+ iter->end = true; \
+ } \
+ \
+ FMOD bool PFX##_iter_next(SNAME##_iter *iter) \
+ { \
+ if (iter->end) \
+ return false; \
+ \
+ SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \
+ \
+ if (iter->cursor == iter->last) \
+ { \
+ iter->end = true; \
+ \
+ return false; \
+ } \
+ \
+ iter->index++; \
+ \
+ while (1) \
+ { \
+ iter->cursor++; \
+ scan = &(iter->target->buffer[iter->cursor]); \
+ \
+ if (scan->state == ES_FILLED) \
+ break; \
+ } \
+ \
+ iter->start = PFX##_empty(iter->target); \
+ \
+ return true; \
+ } \
+ \
+ FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \
+ { \
+ if (iter->start) \
+ return false; \
+ \
+ SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \
+ \
+ if (iter->cursor == iter->first) \
+ { \
+ iter->start = true; \
+ \
+ return false; \
+ } \
+ \
+ iter->index--; \
+ \
+ while (1) \
+ { \
+ iter->cursor--; \
+ scan = &(iter->target->buffer[iter->cursor]); \
+ \
+ if (scan->state == ES_FILLED) \
+ break; \
+ } \
+ \
+ iter->end = PFX##_empty(iter->target); \
+ \
+ return true; \
+ } \
+ \
+ FMOD K PFX##_iter_key(SNAME##_iter *iter) \
+ { \
+ if (PFX##_empty(iter->target)) \
+ PFX##_impl_default_key(); \
+ \
+ return iter->target->buffer[iter->cursor].key; \
+ } \
+ \
+ FMOD V PFX##_iter_value(SNAME##_iter *iter) \
+ { \
+ if (PFX##_empty(iter->target)) \
+ PFX##_impl_default_value(); \
+ \
+ return iter->target->buffer[iter->cursor].value; \
+ } \
+ \
+ FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \
+ { \
+ if (PFX##_empty(iter->target)) \
+ return NULL; \
+ \
+ return &(iter->target->buffer[iter->cursor].value); \
+ } \
+ \
+ FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \
+ { \
+ return iter->index; \
+ } \
+ \
+ static bool PFX##_impl_grow(SNAME *_map_) \
+ { \
+ size_t new_size = PFX##_impl_calculate_size(_map_->capacity + _map_->capacity / 2); \
+ \
+ SNAME *_new_map_ = PFX##_new(new_size, _map_->load, _map_->cmp, _map_->hash); \
+ \
+ if (!_new_map_) \
+ return false; \
+ \
+ SNAME##_iter iter; \
+ \
+ for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
+ { \
+ K key = PFX##_iter_key(&iter); \
+ V value = PFX##_iter_value(&iter); \
+ \
+ PFX##_insert(_new_map_, key, value); \
+ } \
+ \
+ if (_map_->count != _new_map_->count) \
+ { \
+ PFX##_free(_new_map_); \
+ return false; \
+ } \
+ \
+ SNAME##_entry *tmp = _map_->buffer; \
+ _map_->buffer = _new_map_->buffer; \
+ _new_map_->buffer = tmp; \
+ \
+ _map_->capacity = _new_map_->capacity; \
+ \
+ PFX##_free(_new_map_); \
+ \
+ return true; \
+ } \
+ \
+ static SNAME##_entry *PFX##_impl_get_entry(SNAME *_map_, K key) \
+ { \
+ size_t hash = _map_->hash(key); \
+ size_t pos = hash % _map_->capacity; \
+ \
+ SNAME##_entry *target = &(_map_->buffer[pos]); \
+ \
+ while (target->state == ES_FILLED || target->state == ES_DELETED) \
+ { \
+ if (_map_->cmp(target->key, key) == 0) \
+ return target; \
+ \
+ pos++; \
+ target = &(_map_->buffer[pos % _map_->capacity]); \
+ } \
+ \
+ return NULL; \
+ } \
+ \
+ static size_t PFX##_impl_calculate_size(size_t required) \
+ { \
+ const size_t count = sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]); \
+ \
+ if (cmc_hashtable_primes[count - 1] < required) \
+ return required; \
+ \
+ size_t i = 0; \
+ while (cmc_hashtable_primes[i] < required) \
+ i++; \
+ \
+ return cmc_hashtable_primes[i]; \
+ } \
+ \
+ static SNAME##_iter PFX##_impl_it_start(SNAME *_map_) \
+ { \
+ SNAME##_iter iter; \
+ \
+ PFX##_iter_init(&iter, _map_); \
+ \
+ return iter; \
+ } \
+ \
+ static SNAME##_iter PFX##_impl_it_end(SNAME *_map_) \
+ { \
+ SNAME##_iter iter; \
+ \
+ PFX##_iter_init(&iter, _map_); \
+ PFX##_iter_to_end(&iter); \
+ \
+ return iter; \
}
#endif /* CMC_HASHMAP_H */
diff --git a/src/hashset.h b/src/hashset.h
index 7c17358..569a677 100644
--- a/src/hashset.h
+++ b/src/hashset.h
@@ -74,775 +74,775 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
HASHSET_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* HEADER ********************************************************************/
-#define HASHSET_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
- \
- /* Hashset Structure */ \
- typedef struct SNAME##_s \
- { \
- /* Array of Entries */ \
- struct SNAME##_entry_s *buffer; \
- \
- /* Current Array Capcity */ \
- size_t capacity; \
- \
- /* Current amount of elements */ \
- size_t count; \
- \
- /* Load factor in range (0.0, 1.0) */ \
- double load; \
- \
- /* Element comparison function */ \
- int (*cmp)(V, V); \
- \
- /* Element hash function */ \
- size_t (*hash)(V); \
- \
- /* Function that returns an iterator to the start of the hashset */ \
- struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
- \
- /* Function that returns an iterator to the end of the hashset */ \
- struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
- \
- } SNAME, *SNAME##_ptr; \
- \
- typedef struct SNAME##_entry_s \
- { \
- /* Entry element */ \
- V value; \
- \
- /* The distance of this node to its original position, used by robin-hood hashing */ \
- size_t dist; \
- \
- /* The sate of this node (DELETED, EMPTY, FILLED) */ \
- enum EntryState_e state; \
- \
- } SNAME##_entry, *SNAME##_entry_ptr; \
- \
- /* Hashset Iterator */ \
- typedef struct SNAME##_iter_s \
- { \
- /* Target Hashset */ \
- struct SNAME##_s *target; \
- \
- /* Cursor's position (index) */ \
- size_t cursor; \
- \
- /* Keeps track of relative index to the iteration of elements */ \
- size_t index; \
- \
- /* The index of the first element */ \
- size_t first; \
- \
- /* The index of the last element */ \
- size_t last; \
- \
- /* If the iterator has reached the start of the iteration */ \
- bool start; \
- \
- /* If the iterator has reached the end of the iteration */ \
- bool end; \
- \
- } SNAME##_iter, *SNAME##_iter_ptr; \
- \
- /* Collection Functions */ \
- /* Collection Allocation and Deallocation */ \
- FMOD SNAME *PFX##_new(size_t size, double load, int (*compare)(V, V), size_t (*hash)(V)); \
- FMOD void PFX##_clear(SNAME *_set_); \
- FMOD void PFX##_free(SNAME *_set_); \
- /* Collection Input and Output */ \
- FMOD bool PFX##_insert(SNAME *_set_, V element); \
- FMOD bool PFX##_remove(SNAME *_set_, V element); \
- /* Conditional Input and Output */ \
- FMOD bool PFX##_insert_if(SNAME *_set_, V element, bool condition); \
- FMOD bool PFX##_remove_if(SNAME *_set_, V element, bool condition); \
- /* Element Access */ \
- FMOD bool PFX##_max(SNAME *_set_, V *value); \
- FMOD bool PFX##_min(SNAME *_set_, V *value); \
- /* Collection State */ \
- FMOD bool PFX##_contains(SNAME *_set_, V element); \
- FMOD bool PFX##_empty(SNAME *_set_); \
- FMOD size_t PFX##_count(SNAME *_set_); \
- FMOD size_t PFX##_capacity(SNAME *_set_); \
- \
- /* Set Operations */ \
- FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_); \
- FMOD SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_); \
- FMOD SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_); \
- FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_); \
- FMOD bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_); \
- FMOD bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_); \
- FMOD bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_); \
- FMOD bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_); \
- FMOD bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_); \
- \
- /* 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 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 HASHSET_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
+ \
+ /* Hashset Structure */ \
+ typedef struct SNAME##_s \
+ { \
+ /* Array of Entries */ \
+ struct SNAME##_entry_s *buffer; \
+ \
+ /* Current Array Capcity */ \
+ size_t capacity; \
+ \
+ /* Current amount of elements */ \
+ size_t count; \
+ \
+ /* Load factor in range (0.0, 1.0) */ \
+ double load; \
+ \
+ /* Element comparison function */ \
+ int (*cmp)(V, V); \
+ \
+ /* Element hash function */ \
+ size_t (*hash)(V); \
+ \
+ /* Function that returns an iterator to the start of the hashset */ \
+ struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
+ \
+ /* Function that returns an iterator to the end of the hashset */ \
+ struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
+ \
+ } SNAME, *SNAME##_ptr; \
+ \
+ typedef struct SNAME##_entry_s \
+ { \
+ /* Entry element */ \
+ V value; \
+ \
+ /* The distance of this node to its original position, used by robin-hood hashing */ \
+ size_t dist; \
+ \
+ /* The sate of this node (DELETED, EMPTY, FILLED) */ \
+ enum EntryState_e state; \
+ \
+ } SNAME##_entry, *SNAME##_entry_ptr; \
+ \
+ /* Hashset Iterator */ \
+ typedef struct SNAME##_iter_s \
+ { \
+ /* Target Hashset */ \
+ struct SNAME##_s *target; \
+ \
+ /* Cursor's position (index) */ \
+ size_t cursor; \
+ \
+ /* Keeps track of relative index to the iteration of elements */ \
+ size_t index; \
+ \
+ /* The index of the first element */ \
+ size_t first; \
+ \
+ /* The index of the last element */ \
+ size_t last; \
+ \
+ /* If the iterator has reached the start of the iteration */ \
+ bool start; \
+ \
+ /* If the iterator has reached the end of the iteration */ \
+ bool end; \
+ \
+ } SNAME##_iter, *SNAME##_iter_ptr; \
+ \
+ /* Collection Functions */ \
+ /* Collection Allocation and Deallocation */ \
+ FMOD SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), size_t (*hash)(V)); \
+ FMOD void PFX##_clear(SNAME *_set_); \
+ FMOD void PFX##_free(SNAME *_set_); \
+ /* Collection Input and Output */ \
+ FMOD bool PFX##_insert(SNAME *_set_, V element); \
+ FMOD bool PFX##_remove(SNAME *_set_, V element); \
+ /* Conditional Input and Output */ \
+ FMOD bool PFX##_insert_if(SNAME *_set_, V element, bool condition); \
+ FMOD bool PFX##_remove_if(SNAME *_set_, V element, bool condition); \
+ /* Element Access */ \
+ FMOD bool PFX##_max(SNAME *_set_, V *value); \
+ FMOD bool PFX##_min(SNAME *_set_, V *value); \
+ /* Collection State */ \
+ FMOD bool PFX##_contains(SNAME *_set_, V element); \
+ FMOD bool PFX##_empty(SNAME *_set_); \
+ FMOD size_t PFX##_count(SNAME *_set_); \
+ FMOD size_t PFX##_capacity(SNAME *_set_); \
+ \
+ /* Set Operations */ \
+ FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_); \
+ FMOD SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_); \
+ FMOD SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_); \
+ FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_); \
+ FMOD bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_); \
+ FMOD bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_); \
+ FMOD bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_); \
+ FMOD bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_); \
+ FMOD bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_); \
+ \
+ /* 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 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 HASHSET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \
- \
- /* Implementation Detail Functions */ \
- static bool PFX##_impl_grow(SNAME *_set_); \
- static SNAME##_entry *PFX##_impl_get_entry(SNAME *_set_, V element); \
- static size_t PFX##_impl_calculate_size(size_t required); \
- static SNAME##_iter PFX##_impl_it_start(SNAME *_set_); \
- static SNAME##_iter PFX##_impl_it_end(SNAME *_set_); \
- \
- FMOD SNAME *PFX##_new(size_t size, double load, int (*compare)(V, V), size_t (*hash)(V)) \
- { \
- if (size == 0 || load <= 0 || load >= 1) \
- return NULL; \
- \
- size_t real_size = PFX##_impl_calculate_size(size); \
- \
- SNAME *_set_ = malloc(sizeof(SNAME)); \
- \
- if (!_set_) \
- return NULL; \
- \
- _set_->buffer = malloc(sizeof(SNAME##_entry) * real_size); \
- \
- if (!_set_->buffer) \
- { \
- free(_set_); \
- return NULL; \
- } \
- \
- memset(_set_->buffer, 0, sizeof(SNAME##_entry) * real_size); \
- \
- _set_->count = 0; \
- _set_->capacity = real_size; \
- _set_->load = load; \
- _set_->cmp = compare; \
- _set_->hash = hash; \
- \
- _set_->it_start = PFX##_impl_it_start; \
- _set_->it_end = PFX##_impl_it_end; \
- \
- return _set_; \
- } \
- \
- FMOD void PFX##_clear(SNAME *_set_) \
- { \
- memset(_set_->buffer, 0, sizeof(SNAME##_entry) * _set_->capacity); \
- \
- _set_->count = 0; \
- } \
- \
- FMOD void PFX##_free(SNAME *_set_) \
- { \
- free(_set_->buffer); \
- free(_set_); \
- } \
- \
- FMOD bool PFX##_insert(SNAME *_set_, V element) \
- { \
- if ((double)_set_->capacity * _set_->load <= (double)_set_->count) \
- { \
- if (!PFX##_impl_grow(_set_)) \
- return false; \
- } \
- \
- size_t hash = _set_->hash(element); \
- size_t original_pos = hash % _set_->capacity; \
- size_t pos = original_pos; \
- \
- SNAME##_entry *target = &(_set_->buffer[pos]); \
- \
- if (PFX##_impl_get_entry(_set_, element) != NULL) \
- return false; \
- \
- if (target->state == ES_EMPTY || target->state == ES_DELETED) \
- { \
- target->value = element; \
- target->dist = pos - original_pos; \
- target->state = ES_FILLED; \
- } \
- else \
- { \
- while (true) \
- { \
- pos++; \
- target = &(_set_->buffer[pos % _set_->capacity]); \
- \
- if (target->state == ES_EMPTY || target->state == ES_DELETED) \
- { \
- target->value = element; \
- target->dist = pos - original_pos; \
- target->state = ES_FILLED; \
- \
- break; \
- } \
- else if (target->dist < pos - original_pos) \
- { \
- V tmp = target->value; \
- size_t tmp_dist = target->dist; \
- \
- target->value = element; \
- target->dist = pos - original_pos; \
- \
- element = tmp; \
- original_pos = pos - tmp_dist; \
- } \
- } \
- } \
- \
- _set_->count++; \
- \
- return true; \
- } \
- \
- FMOD bool PFX##_remove(SNAME *_set_, V element) \
- { \
- SNAME##_entry *result = PFX##_impl_get_entry(_set_, element); \
- \
- if (result == NULL) \
- return false; \
- \
- result->value = PFX##_impl_default_value(); \
- result->dist = 0; \
- result->state = ES_DELETED; \
- \
- _set_->count--; \
- \
- return true; \
- } \
- \
- FMOD bool PFX##_insert_if(SNAME *_set_, V element, bool condition) \
- { \
- if (condition) \
- return PFX##_insert(_set_, element); \
- \
- return false; \
- } \
- \
- FMOD bool PFX##_remove_if(SNAME *_set_, V element, bool condition) \
- { \
- if (condition) \
- return PFX##_remove(_set_, element); \
- \
- return false; \
- } \
- \
- FMOD bool PFX##_max(SNAME *_set_, V *value) \
- { \
- if (PFX##_empty(_set_)) \
- return false; \
- \
- SNAME##_iter iter; \
- \
- for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
- { \
- V result = PFX##_iter_value(&iter); \
- size_t index = PFX##_iter_index(&iter); \
- \
- if (index == 0) \
- *value = result; \
- else if (_set_->cmp(result, *value) > 0) \
- *value = result; \
- } \
- \
- return true; \
- } \
- \
- FMOD bool PFX##_min(SNAME *_set_, V *value) \
- { \
- if (PFX##_empty(_set_)) \
- return false; \
- \
- SNAME##_iter iter; \
- \
- for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
- { \
- V result = PFX##_iter_value(&iter); \
- size_t index = PFX##_iter_index(&iter); \
- \
- if (index == 0) \
- *value = result; \
- else if (_set_->cmp(result, *value) < 0) \
- *value = result; \
- } \
- \
- return true; \
- } \
- \
- FMOD bool PFX##_contains(SNAME *_set_, V element) \
- { \
- return PFX##_impl_get_entry(_set_, element) != NULL; \
- } \
- \
- FMOD bool PFX##_empty(SNAME *_set_) \
- { \
- return _set_->count == 0; \
- } \
- \
- FMOD size_t PFX##_count(SNAME *_set_) \
- { \
- return _set_->count; \
- } \
- \
- FMOD size_t PFX##_capacity(SNAME *_set_) \
- { \
- return _set_->capacity; \
- } \
- \
- FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_) \
- { \
- SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \
- \
- if (!_set_r_) \
- return false; \
- \
- SNAME##_iter iter1, iter2; \
- PFX##_iter_init(&iter1, _set1_); \
- PFX##_iter_init(&iter2, _set2_); \
- \
- for (PFX##_iter_to_start(&iter1); !PFX##_iter_end(&iter1); PFX##_iter_next(&iter1)) \
- { \
- PFX##_insert(_set_r_, PFX##_iter_value(&iter1)); \
- } \
- \
- for (PFX##_iter_to_start(&iter2); !PFX##_iter_end(&iter2); PFX##_iter_next(&iter2)) \
- { \
- PFX##_insert(_set_r_, PFX##_iter_value(&iter2)); \
- } \
- \
- return _set_r_; \
- } \
- \
- FMOD SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_) \
- { \
- SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \
- \
- if (!_set_r_) \
- return false; \
- \
- SNAME *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; \
- SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \
- \
- SNAME##_iter iter; \
- PFX##_iter_init(&iter, _set_A_); \
- \
- for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
- { \
- V value = PFX##_iter_value(&iter); \
- \
- if (PFX##_impl_get_entry(_set_B_, value) != NULL) \
- PFX##_insert(_set_r_, value); \
- } \
- \
- return _set_r_; \
- } \
- \
- FMOD SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_) \
- { \
- SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \
- \
- if (!_set_r_) \
- return false; \
- \
- SNAME##_iter iter; \
- PFX##_iter_init(&iter, _set1_); \
- \
- for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
- { \
- V value = PFX##_iter_value(&iter); \
- \
- if (PFX##_impl_get_entry(_set2_, value) == NULL) \
- PFX##_insert(_set_r_, value); \
- } \
- \
- return _set_r_; \
- } \
- \
- FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_) \
- { \
- SNAME##_iter iter1, iter2; \
- \
- SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \
- \
- if (!_set_r_) \
- return false; \
- \
- PFX##_iter_init(&iter1, _set1_); \
- PFX##_iter_init(&iter2, _set2_); \
- \
- for (PFX##_iter_to_start(&iter1); !PFX##_iter_end(&iter1); PFX##_iter_next(&iter1)) \
- { \
- V value = PFX##_iter_value(&iter1); \
- \
- if (PFX##_impl_get_entry(_set2_, value) == NULL) \
- PFX##_insert(_set_r_, value); \
- } \
- \
- for (PFX##_iter_to_start(&iter2); !PFX##_iter_end(&iter2); PFX##_iter_next(&iter2)) \
- { \
- V value = PFX##_iter_value(&iter2); \
- \
- if (PFX##_impl_get_entry(_set1_, value) == NULL) \
- PFX##_insert(_set_r_, value); \
- } \
- \
- return _set_r_; \
- } \
- \
- /* Is _set1_ a subset of _set2_ ? */ \
- /* A set X is a subset of a set Y when: X <= Y */ \
- /* If X is a subset of Y, then Y is a superset of X */ \
- FMOD bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_) \
- { \
- /* If the cardinality of _set1_ is greater than that of _set2_, then it is safe to */ \
- /* say that _set1_ can't be a subset of _set2_ */ \
- if (PFX##_count(_set1_) > PFX##_count(_set2_)) \
- return false; \
- \
- /* The empty set is a subset of all sets */ \
- if (PFX##_empty(_set1_)) \
- return true; \
- \
- SNAME##_iter iter; \
- \
- PFX##_iter_init(&iter, _set1_); \
- \
- for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
- { \
- V value = PFX##_iter_value(&iter); \
- \
- if (!PFX##_contains(_set2_, value)) \
- return false; \
- } \
- \
- return true; \
- } \
- \
- /* Is _set1_ a superset of _set2_ ? */ \
- /* A set X is a superset of a set Y when: X >= Y */ \
- /* If X is a superset of Y, then Y is a subset of X */ \
- FMOD bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_) \
- { \
- return PFX##_is_subset(_set2_, _set1_); \
- } \
- \
- /* Is _set1_ a proper subset of _set2_ ? */ \
- /* A set X is a proper subset of a set Y when: X < Y */ \
- /* If X is a proper subset of Y, then Y is a proper superset of X */ \
- FMOD bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_) \
- { \
- /* If the cardinality of _set1_ is greater than or equal to that of _set2_, then it */ \
- /* is safe to say that _set1_ can't be a proper subset of _set2_ */ \
- if (PFX##_count(_set1_) >= PFX##_count(_set2_)) \
- return false; \
- \
- if (PFX##_empty(_set1_)) \
- { \
- /* The empty set is a proper subset of all non-empty sets */ \
- if (!PFX##_empty(_set2_)) \
- return true; \
- /* The empty set is not a proper subset of itself (this is true for any set) */ \
- else \
- return false; \
- } \
- \
- SNAME##_iter iter; \
- \
- PFX##_iter_init(&iter, _set1_); \
- \
- for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
- { \
- V value = PFX##_iter_value(&iter); \
- \
- if (!PFX##_contains(_set2_, value)) \
- return false; \
- } \
- \
- return true; \
- } \
- \
- /* Is _set1_ a proper superset of _set2_ ? */ \
- /* A set X is a proper superset of a set Y when: X > Y */ \
- /* If X is a proper superset of Y, then Y is a proper subset of X */ \
- FMOD bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_) \
- { \
- return PFX##_is_proper_subset(_set2_, _set1_); \
- } \
- \
- /* Is _set1_ a disjointset of _set2_ ? */ \
- /* A set X is a disjointset of a set Y if their intersection is empty, that is, if */ \
- /* there are no elements in common between the two */ \
- FMOD bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_) \
- { \
- /* The intersection of an empty set with any other set will result in an empty set */ \
- if (PFX##_empty(_set1_)) \
- return true; \
- \
- SNAME##_iter iter; \
- \
- PFX##_iter_init(&iter, _set1_); \
- \
- for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
- { \
- V value = PFX##_iter_value(&iter); \
- \
- if (PFX##_contains(_set2_, value)) \
- return false; \
- } \
- \
- return true; \
- } \
- \
- 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; \
- iter->cursor = 0; \
- iter->index = 0; \
- iter->start = true; \
- iter->end = PFX##_empty(target); \
- \
- if (!PFX##_empty(target)) \
- { \
- for (size_t i = 0; i < target->capacity; i++) \
- { \
- if (target->buffer[i].state == ES_FILLED) \
- { \
- iter->first = i; \
- break; \
- } \
- } \
- \
- iter->cursor = iter->first; \
- \
- for (size_t i = target->capacity; i > 0; i--) \
- { \
- if (target->buffer[i - 1].state == ES_FILLED) \
- { \
- iter->last = i - 1; \
- break; \
- } \
- } \
- } \
- } \
- \
- 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->first; \
- iter->index = 0; \
- iter->start = true; \
- iter->end = PFX##_empty(iter->target); \
- } \
- \
- FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \
- { \
- iter->cursor = iter->last; \
- iter->index = iter->target->count - 1; \
- iter->start = PFX##_empty(iter->target); \
- iter->end = true; \
- } \
- \
- FMOD bool PFX##_iter_next(SNAME##_iter *iter) \
- { \
- if (iter->end) \
- return false; \
- \
- SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \
- \
- if (iter->cursor == iter->last) \
- iter->end = true; \
- else \
- { \
- iter->index++; \
- \
- while (1) \
- { \
- iter->cursor++; \
- scan = &(iter->target->buffer[iter->cursor]); \
- \
- if (scan->state == ES_FILLED) \
- break; \
- } \
- } \
- \
- iter->start = PFX##_empty(iter->target); \
- \
- return true; \
- } \
- \
- FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \
- { \
- if (iter->start) \
- return false; \
- \
- SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \
- \
- if (iter->cursor == iter->first) \
- iter->start = true; \
- else \
- { \
- iter->index--; \
- \
- while (1) \
- { \
- iter->cursor--; \
- scan = &(iter->target->buffer[iter->cursor]); \
- \
- if (scan->state == ES_FILLED) \
- break; \
- } \
- } \
- \
- iter->end = PFX##_empty(iter->target); \
- \
- 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].value; \
- } \
- \
- FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \
- { \
- return iter->index; \
- } \
- \
- static bool PFX##_impl_grow(SNAME *_set_) \
- { \
- size_t new_size = PFX##_impl_calculate_size(_set_->capacity + _set_->capacity / 2); \
- \
- SNAME *_new_set_ = PFX##_new(new_size, _set_->load, _set_->cmp, _set_->hash); \
- \
- if (!_new_set_) \
- return false; \
- \
- SNAME##_iter iter; \
- \
- for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
- { \
- PFX##_insert(_new_set_, PFX##_iter_value(&iter)); \
- } \
- \
- if (_set_->count != _new_set_->count) \
- { \
- PFX##_free(_new_set_); \
- \
- return false; \
- } \
- \
- SNAME##_entry *tmp = _set_->buffer; \
- _set_->buffer = _new_set_->buffer; \
- _new_set_->buffer = tmp; \
- \
- _set_->capacity = _new_set_->capacity; \
- \
- PFX##_free(_new_set_); \
- \
- return true; \
- } \
- \
- static SNAME##_entry *PFX##_impl_get_entry(SNAME *_set_, V element) \
- { \
- size_t hash = _set_->hash(element); \
- size_t pos = hash % _set_->capacity; \
- \
- SNAME##_entry *target = &(_set_->buffer[pos]); \
- \
- while (target->state == ES_FILLED || target->state == ES_DELETED) \
- { \
- if (_set_->cmp(target->value, element) == 0) \
- return target; \
- \
- pos++; \
- target = &(_set_->buffer[pos % _set_->capacity]); \
- } \
- \
- return NULL; \
- } \
- \
- static size_t PFX##_impl_calculate_size(size_t required) \
- { \
- const size_t count = sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]); \
- \
- if (cmc_hashtable_primes[count - 1] < required) \
- return required; \
- \
- size_t i = 0; \
- while (cmc_hashtable_primes[i] < required) \
- i++; \
- \
- return cmc_hashtable_primes[i]; \
- } \
- \
- static SNAME##_iter PFX##_impl_it_start(SNAME *_set_) \
- { \
- SNAME##_iter iter; \
- \
- PFX##_iter_init(&iter, _set_); \
- \
- return iter; \
- } \
- \
- static SNAME##_iter PFX##_impl_it_end(SNAME *_set_) \
- { \
- SNAME##_iter iter; \
- \
- PFX##_iter_init(&iter, _set_); \
- PFX##_iter_to_end(&iter); \
- \
- return iter; \
+#define HASHSET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \
+ \
+ /* Implementation Detail Functions */ \
+ static bool PFX##_impl_grow(SNAME *_set_); \
+ static SNAME##_entry *PFX##_impl_get_entry(SNAME *_set_, V element); \
+ static size_t PFX##_impl_calculate_size(size_t required); \
+ static SNAME##_iter PFX##_impl_it_start(SNAME *_set_); \
+ static SNAME##_iter PFX##_impl_it_end(SNAME *_set_); \
+ \
+ FMOD SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), size_t (*hash)(V)) \
+ { \
+ if (capacity == 0 || load <= 0 || load >= 1) \
+ return NULL; \
+ \
+ size_t real_capacity = PFX##_impl_calculate_size(capacity / load); \
+ \
+ SNAME *_set_ = malloc(sizeof(SNAME)); \
+ \
+ if (!_set_) \
+ return NULL; \
+ \
+ _set_->buffer = malloc(sizeof(SNAME##_entry) * real_capacity); \
+ \
+ if (!_set_->buffer) \
+ { \
+ free(_set_); \
+ return NULL; \
+ } \
+ \
+ memset(_set_->buffer, 0, sizeof(SNAME##_entry) * real_capacity); \
+ \
+ _set_->count = 0; \
+ _set_->capacity = real_capacity; \
+ _set_->load = load; \
+ _set_->cmp = compare; \
+ _set_->hash = hash; \
+ \
+ _set_->it_start = PFX##_impl_it_start; \
+ _set_->it_end = PFX##_impl_it_end; \
+ \
+ return _set_; \
+ } \
+ \
+ FMOD void PFX##_clear(SNAME *_set_) \
+ { \
+ memset(_set_->buffer, 0, sizeof(SNAME##_entry) * _set_->capacity); \
+ \
+ _set_->count = 0; \
+ } \
+ \
+ FMOD void PFX##_free(SNAME *_set_) \
+ { \
+ free(_set_->buffer); \
+ free(_set_); \
+ } \
+ \
+ FMOD bool PFX##_insert(SNAME *_set_, V element) \
+ { \
+ if ((double)_set_->capacity * _set_->load <= (double)_set_->count) \
+ { \
+ if (!PFX##_impl_grow(_set_)) \
+ return false; \
+ } \
+ \
+ size_t hash = _set_->hash(element); \
+ size_t original_pos = hash % _set_->capacity; \
+ size_t pos = original_pos; \
+ \
+ SNAME##_entry *target = &(_set_->buffer[pos]); \
+ \
+ if (PFX##_impl_get_entry(_set_, element) != NULL) \
+ return false; \
+ \
+ if (target->state == ES_EMPTY || target->state == ES_DELETED) \
+ { \
+ target->value = element; \
+ target->dist = pos - original_pos; \
+ target->state = ES_FILLED; \
+ } \
+ else \
+ { \
+ while (true) \
+ { \
+ pos++; \
+ target = &(_set_->buffer[pos % _set_->capacity]); \
+ \
+ if (target->state == ES_EMPTY || target->state == ES_DELETED) \
+ { \
+ target->value = element; \
+ target->dist = pos - original_pos; \
+ target->state = ES_FILLED; \
+ \
+ break; \
+ } \
+ else if (target->dist < pos - original_pos) \
+ { \
+ V tmp = target->value; \
+ size_t tmp_dist = target->dist; \
+ \
+ target->value = element; \
+ target->dist = pos - original_pos; \
+ \
+ element = tmp; \
+ original_pos = pos - tmp_dist; \
+ } \
+ } \
+ } \
+ \
+ _set_->count++; \
+ \
+ return true; \
+ } \
+ \
+ FMOD bool PFX##_remove(SNAME *_set_, V element) \
+ { \
+ SNAME##_entry *result = PFX##_impl_get_entry(_set_, element); \
+ \
+ if (result == NULL) \
+ return false; \
+ \
+ result->value = PFX##_impl_default_value(); \
+ result->dist = 0; \
+ result->state = ES_DELETED; \
+ \
+ _set_->count--; \
+ \
+ return true; \
+ } \
+ \
+ FMOD bool PFX##_insert_if(SNAME *_set_, V element, bool condition) \
+ { \
+ if (condition) \
+ return PFX##_insert(_set_, element); \
+ \
+ return false; \
+ } \
+ \
+ FMOD bool PFX##_remove_if(SNAME *_set_, V element, bool condition) \
+ { \
+ if (condition) \
+ return PFX##_remove(_set_, element); \
+ \
+ return false; \
+ } \
+ \
+ FMOD bool PFX##_max(SNAME *_set_, V *value) \
+ { \
+ if (PFX##_empty(_set_)) \
+ return false; \
+ \
+ SNAME##_iter iter; \
+ \
+ for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
+ { \
+ V result = PFX##_iter_value(&iter); \
+ size_t index = PFX##_iter_index(&iter); \
+ \
+ if (index == 0) \
+ *value = result; \
+ else if (_set_->cmp(result, *value) > 0) \
+ *value = result; \
+ } \
+ \
+ return true; \
+ } \
+ \
+ FMOD bool PFX##_min(SNAME *_set_, V *value) \
+ { \
+ if (PFX##_empty(_set_)) \
+ return false; \
+ \
+ SNAME##_iter iter; \
+ \
+ for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
+ { \
+ V result = PFX##_iter_value(&iter); \
+ size_t index = PFX##_iter_index(&iter); \
+ \
+ if (index == 0) \
+ *value = result; \
+ else if (_set_->cmp(result, *value) < 0) \
+ *value = result; \
+ } \
+ \
+ return true; \
+ } \
+ \
+ FMOD bool PFX##_contains(SNAME *_set_, V element) \
+ { \
+ return PFX##_impl_get_entry(_set_, element) != NULL; \
+ } \
+ \
+ FMOD bool PFX##_empty(SNAME *_set_) \
+ { \
+ return _set_->count == 0; \
+ } \
+ \
+ FMOD size_t PFX##_count(SNAME *_set_) \
+ { \
+ return _set_->count; \
+ } \
+ \
+ FMOD size_t PFX##_capacity(SNAME *_set_) \
+ { \
+ return _set_->capacity; \
+ } \
+ \
+ FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_) \
+ { \
+ SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \
+ \
+ if (!_set_r_) \
+ return false; \
+ \
+ SNAME##_iter iter1, iter2; \
+ PFX##_iter_init(&iter1, _set1_); \
+ PFX##_iter_init(&iter2, _set2_); \
+ \
+ for (PFX##_iter_to_start(&iter1); !PFX##_iter_end(&iter1); PFX##_iter_next(&iter1)) \
+ { \
+ PFX##_insert(_set_r_, PFX##_iter_value(&iter1)); \
+ } \
+ \
+ for (PFX##_iter_to_start(&iter2); !PFX##_iter_end(&iter2); PFX##_iter_next(&iter2)) \
+ { \
+ PFX##_insert(_set_r_, PFX##_iter_value(&iter2)); \
+ } \
+ \
+ return _set_r_; \
+ } \
+ \
+ FMOD SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_) \
+ { \
+ SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \
+ \
+ if (!_set_r_) \
+ return false; \
+ \
+ SNAME *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; \
+ SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \
+ \
+ SNAME##_iter iter; \
+ PFX##_iter_init(&iter, _set_A_); \
+ \
+ for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
+ { \
+ V value = PFX##_iter_value(&iter); \
+ \
+ if (PFX##_impl_get_entry(_set_B_, value) != NULL) \
+ PFX##_insert(_set_r_, value); \
+ } \
+ \
+ return _set_r_; \
+ } \
+ \
+ FMOD SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_) \
+ { \
+ SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \
+ \
+ if (!_set_r_) \
+ return false; \
+ \
+ SNAME##_iter iter; \
+ PFX##_iter_init(&iter, _set1_); \
+ \
+ for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
+ { \
+ V value = PFX##_iter_value(&iter); \
+ \
+ if (PFX##_impl_get_entry(_set2_, value) == NULL) \
+ PFX##_insert(_set_r_, value); \
+ } \
+ \
+ return _set_r_; \
+ } \
+ \
+ FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_) \
+ { \
+ SNAME##_iter iter1, iter2; \
+ \
+ SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \
+ \
+ if (!_set_r_) \
+ return false; \
+ \
+ PFX##_iter_init(&iter1, _set1_); \
+ PFX##_iter_init(&iter2, _set2_); \
+ \
+ for (PFX##_iter_to_start(&iter1); !PFX##_iter_end(&iter1); PFX##_iter_next(&iter1)) \
+ { \
+ V value = PFX##_iter_value(&iter1); \
+ \
+ if (PFX##_impl_get_entry(_set2_, value) == NULL) \
+ PFX##_insert(_set_r_, value); \
+ } \
+ \
+ for (PFX##_iter_to_start(&iter2); !PFX##_iter_end(&iter2); PFX##_iter_next(&iter2)) \
+ { \
+ V value = PFX##_iter_value(&iter2); \
+ \
+ if (PFX##_impl_get_entry(_set1_, value) == NULL) \
+ PFX##_insert(_set_r_, value); \
+ } \
+ \
+ return _set_r_; \
+ } \
+ \
+ /* Is _set1_ a subset of _set2_ ? */ \
+ /* A set X is a subset of a set Y when: X <= Y */ \
+ /* If X is a subset of Y, then Y is a superset of X */ \
+ FMOD bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_) \
+ { \
+ /* If the cardinality of _set1_ is greater than that of _set2_, then it is safe to */ \
+ /* say that _set1_ can't be a subset of _set2_ */ \
+ if (PFX##_count(_set1_) > PFX##_count(_set2_)) \
+ return false; \
+ \
+ /* The empty set is a subset of all sets */ \
+ if (PFX##_empty(_set1_)) \
+ return true; \
+ \
+ SNAME##_iter iter; \
+ \
+ PFX##_iter_init(&iter, _set1_); \
+ \
+ for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
+ { \
+ V value = PFX##_iter_value(&iter); \
+ \
+ if (!PFX##_contains(_set2_, value)) \
+ return false; \
+ } \
+ \
+ return true; \
+ } \
+ \
+ /* Is _set1_ a superset of _set2_ ? */ \
+ /* A set X is a superset of a set Y when: X >= Y */ \
+ /* If X is a superset of Y, then Y is a subset of X */ \
+ FMOD bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_) \
+ { \
+ return PFX##_is_subset(_set2_, _set1_); \
+ } \
+ \
+ /* Is _set1_ a proper subset of _set2_ ? */ \
+ /* A set X is a proper subset of a set Y when: X < Y */ \
+ /* If X is a proper subset of Y, then Y is a proper superset of X */ \
+ FMOD bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_) \
+ { \
+ /* If the cardinality of _set1_ is greater than or equal to that of _set2_, then it */ \
+ /* is safe to say that _set1_ can't be a proper subset of _set2_ */ \
+ if (PFX##_count(_set1_) >= PFX##_count(_set2_)) \
+ return false; \
+ \
+ if (PFX##_empty(_set1_)) \
+ { \
+ /* The empty set is a proper subset of all non-empty sets */ \
+ if (!PFX##_empty(_set2_)) \
+ return true; \
+ /* The empty set is not a proper subset of itself (this is true for any set) */ \
+ else \
+ return false; \
+ } \
+ \
+ SNAME##_iter iter; \
+ \
+ PFX##_iter_init(&iter, _set1_); \
+ \
+ for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
+ { \
+ V value = PFX##_iter_value(&iter); \
+ \
+ if (!PFX##_contains(_set2_, value)) \
+ return false; \
+ } \
+ \
+ return true; \
+ } \
+ \
+ /* Is _set1_ a proper superset of _set2_ ? */ \
+ /* A set X is a proper superset of a set Y when: X > Y */ \
+ /* If X is a proper superset of Y, then Y is a proper subset of X */ \
+ FMOD bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_) \
+ { \
+ return PFX##_is_proper_subset(_set2_, _set1_); \
+ } \
+ \
+ /* Is _set1_ a disjointset of _set2_ ? */ \
+ /* A set X is a disjointset of a set Y if their intersection is empty, that is, if */ \
+ /* there are no elements in common between the two */ \
+ FMOD bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_) \
+ { \
+ /* The intersection of an empty set with any other set will result in an empty set */ \
+ if (PFX##_empty(_set1_)) \
+ return true; \
+ \
+ SNAME##_iter iter; \
+ \
+ PFX##_iter_init(&iter, _set1_); \
+ \
+ for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
+ { \
+ V value = PFX##_iter_value(&iter); \
+ \
+ if (PFX##_contains(_set2_, value)) \
+ return false; \
+ } \
+ \
+ return true; \
+ } \
+ \
+ 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; \
+ iter->cursor = 0; \
+ iter->index = 0; \
+ iter->start = true; \
+ iter->end = PFX##_empty(target); \
+ \
+ if (!PFX##_empty(target)) \
+ { \
+ for (size_t i = 0; i < target->capacity; i++) \
+ { \
+ if (target->buffer[i].state == ES_FILLED) \
+ { \
+ iter->first = i; \
+ break; \
+ } \
+ } \
+ \
+ iter->cursor = iter->first; \
+ \
+ for (size_t i = target->capacity; i > 0; i--) \
+ { \
+ if (target->buffer[i - 1].state == ES_FILLED) \
+ { \
+ iter->last = i - 1; \
+ break; \
+ } \
+ } \
+ } \
+ } \
+ \
+ 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->first; \
+ iter->index = 0; \
+ iter->start = true; \
+ iter->end = PFX##_empty(iter->target); \
+ } \
+ \
+ FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \
+ { \
+ iter->cursor = iter->last; \
+ iter->index = iter->target->count - 1; \
+ iter->start = PFX##_empty(iter->target); \
+ iter->end = true; \
+ } \
+ \
+ FMOD bool PFX##_iter_next(SNAME##_iter *iter) \
+ { \
+ if (iter->end) \
+ return false; \
+ \
+ SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \
+ \
+ if (iter->cursor == iter->last) \
+ iter->end = true; \
+ else \
+ { \
+ iter->index++; \
+ \
+ while (1) \
+ { \
+ iter->cursor++; \
+ scan = &(iter->target->buffer[iter->cursor]); \
+ \
+ if (scan->state == ES_FILLED) \
+ break; \
+ } \
+ } \
+ \
+ iter->start = PFX##_empty(iter->target); \
+ \
+ return true; \
+ } \
+ \
+ FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \
+ { \
+ if (iter->start) \
+ return false; \
+ \
+ SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \
+ \
+ if (iter->cursor == iter->first) \
+ iter->start = true; \
+ else \
+ { \
+ iter->index--; \
+ \
+ while (1) \
+ { \
+ iter->cursor--; \
+ scan = &(iter->target->buffer[iter->cursor]); \
+ \
+ if (scan->state == ES_FILLED) \
+ break; \
+ } \
+ } \
+ \
+ iter->end = PFX##_empty(iter->target); \
+ \
+ 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].value; \
+ } \
+ \
+ FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \
+ { \
+ return iter->index; \
+ } \
+ \
+ static bool PFX##_impl_grow(SNAME *_set_) \
+ { \
+ size_t new_size = PFX##_impl_calculate_size(_set_->capacity + _set_->capacity / 2); \
+ \
+ SNAME *_new_set_ = PFX##_new(new_size, _set_->load, _set_->cmp, _set_->hash); \
+ \
+ if (!_new_set_) \
+ return false; \
+ \
+ SNAME##_iter iter; \
+ \
+ for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
+ { \
+ PFX##_insert(_new_set_, PFX##_iter_value(&iter)); \
+ } \
+ \
+ if (_set_->count != _new_set_->count) \
+ { \
+ PFX##_free(_new_set_); \
+ \
+ return false; \
+ } \
+ \
+ SNAME##_entry *tmp = _set_->buffer; \
+ _set_->buffer = _new_set_->buffer; \
+ _new_set_->buffer = tmp; \
+ \
+ _set_->capacity = _new_set_->capacity; \
+ \
+ PFX##_free(_new_set_); \
+ \
+ return true; \
+ } \
+ \
+ static SNAME##_entry *PFX##_impl_get_entry(SNAME *_set_, V element) \
+ { \
+ size_t hash = _set_->hash(element); \
+ size_t pos = hash % _set_->capacity; \
+ \
+ SNAME##_entry *target = &(_set_->buffer[pos]); \
+ \
+ while (target->state == ES_FILLED || target->state == ES_DELETED) \
+ { \
+ if (_set_->cmp(target->value, element) == 0) \
+ return target; \
+ \
+ pos++; \
+ target = &(_set_->buffer[pos % _set_->capacity]); \
+ } \
+ \
+ return NULL; \
+ } \
+ \
+ static size_t PFX##_impl_calculate_size(size_t required) \
+ { \
+ const size_t count = sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]); \
+ \
+ if (cmc_hashtable_primes[count - 1] < required) \
+ return required; \
+ \
+ size_t i = 0; \
+ while (cmc_hashtable_primes[i] < required) \
+ i++; \
+ \
+ return cmc_hashtable_primes[i]; \
+ } \
+ \
+ static SNAME##_iter PFX##_impl_it_start(SNAME *_set_) \
+ { \
+ SNAME##_iter iter; \
+ \
+ PFX##_iter_init(&iter, _set_); \
+ \
+ return iter; \
+ } \
+ \
+ static SNAME##_iter PFX##_impl_it_end(SNAME *_set_) \
+ { \
+ SNAME##_iter iter; \
+ \
+ PFX##_iter_init(&iter, _set_); \
+ PFX##_iter_to_end(&iter); \
+ \
+ return iter; \
}
#endif /* CMC_HASHSET_H */
diff --git a/src/heap.h b/src/heap.h
index 16c7bbf..bd995cf 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -36,100 +36,100 @@ typedef enum HeapOrder
HEAP_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* HEADER ********************************************************************/
-#define HEAP_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
- \
- /* Heap Structure */ \
- typedef struct SNAME##_s \
- { \
- /* Dynamic array of elements */ \
- V *buffer; \
- \
- /* Current array capacity */ \
- size_t capacity; \
- \
- /* Current amount of elements in the heap */ \
- size_t count; \
- \
- /* Heap order (MaxHeap or MinHeap) */ \
- enum HeapOrder HO; \
- \
- /* Element comparison function */ \
- int (*cmp)(V, V); \
- \
- /* Function that returns an iterator to the start of the heap */ \
- struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
- \
- /* Function that returns an iterator to the end of the heap */ \
- struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
- \
- } SNAME, *SNAME##_ptr; \
- \
- /* Heap Iterator */ \
- typedef struct SNAME##_iter_s \
- { \
- /* Target heap */ \
- struct SNAME##_s *target; \
- \
- /* Cursor's position (index) */ \
- size_t cursor; \
- \
- /* If the iterator has reached the start of the iteration */ \
- bool start; \
- \
- /* If the iterator has reached the end of the iteration */ \
- bool end; \
- \
- } SNAME##_iter, *SNAME##_iter_ptr; \
- \
- /* Collection Functions */ \
- /* Collection Allocation and Deallocation */ \
- FMOD SNAME *PFX##_new(size_t size, HeapOrder HO, int (*compare)(V, V)); \
- FMOD void PFX##_clear(SNAME *_heap_); \
- FMOD void PFX##_free(SNAME *_heap_); \
- /* Collection Input and Output */ \
- FMOD bool PFX##_insert(SNAME *_heap_, V element); \
- FMOD bool PFX##_remove(SNAME *_heap_, V *result); \
- /* Conditional Input and Output */ \
- FMOD bool PFX##_insert_if(SNAME *_heap_, V element, bool condition); \
- FMOD bool PFX##_remove_if(SNAME *_heap_, V *result, bool condition); \
- /* Element Access */ \
- FMOD V PFX##_peek(SNAME *_heap_); \
- FMOD V *PFX##_peek_ref(SNAME *_heap_); \
- /* Collection State */ \
- FMOD bool PFX##_contains(SNAME *_heap_, V element); \
- FMOD bool PFX##_empty(SNAME *_heap_); \
- FMOD bool PFX##_full(SNAME *_heap_); \
- FMOD size_t PFX##_count(SNAME *_heap_); \
- FMOD size_t PFX##_capacity(SNAME *_heap_); \
- \
- /* 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 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 HEAP_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
+ \
+ /* Heap Structure */ \
+ typedef struct SNAME##_s \
+ { \
+ /* Dynamic array of elements */ \
+ V *buffer; \
+ \
+ /* Current array capacity */ \
+ size_t capacity; \
+ \
+ /* Current amount of elements in the heap */ \
+ size_t count; \
+ \
+ /* Heap order (MaxHeap or MinHeap) */ \
+ enum HeapOrder HO; \
+ \
+ /* Element comparison function */ \
+ int (*cmp)(V, V); \
+ \
+ /* Function that returns an iterator to the start of the heap */ \
+ struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
+ \
+ /* Function that returns an iterator to the end of the heap */ \
+ struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
+ \
+ } SNAME, *SNAME##_ptr; \
+ \
+ /* Heap Iterator */ \
+ typedef struct SNAME##_iter_s \
+ { \
+ /* Target heap */ \
+ struct SNAME##_s *target; \
+ \
+ /* Cursor's position (index) */ \
+ size_t cursor; \
+ \
+ /* If the iterator has reached the start of the iteration */ \
+ bool start; \
+ \
+ /* If the iterator has reached the end of the iteration */ \
+ bool end; \
+ \
+ } SNAME##_iter, *SNAME##_iter_ptr; \
+ \
+ /* Collection Functions */ \
+ /* Collection Allocation and Deallocation */ \
+ FMOD SNAME *PFX##_new(size_t capacity, HeapOrder HO, int (*compare)(V, V)); \
+ FMOD void PFX##_clear(SNAME *_heap_); \
+ FMOD void PFX##_free(SNAME *_heap_); \
+ /* Collection Input and Output */ \
+ FMOD bool PFX##_insert(SNAME *_heap_, V element); \
+ FMOD bool PFX##_remove(SNAME *_heap_, V *result); \
+ /* Conditional Input and Output */ \
+ FMOD bool PFX##_insert_if(SNAME *_heap_, V element, bool condition); \
+ FMOD bool PFX##_remove_if(SNAME *_heap_, V *result, bool condition); \
+ /* Element Access */ \
+ FMOD V PFX##_peek(SNAME *_heap_); \
+ FMOD V *PFX##_peek_ref(SNAME *_heap_); \
+ /* Collection State */ \
+ FMOD bool PFX##_contains(SNAME *_heap_, V element); \
+ FMOD bool PFX##_empty(SNAME *_heap_); \
+ FMOD bool PFX##_full(SNAME *_heap_); \
+ FMOD size_t PFX##_count(SNAME *_heap_); \
+ FMOD size_t PFX##_capacity(SNAME *_heap_); \
+ \
+ /* 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 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 HEAP_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \
\
@@ -143,9 +143,9 @@ typedef enum HeapOrder
static SNAME##_iter PFX##_impl_it_start(SNAME *_heap_); \
static SNAME##_iter PFX##_impl_it_end(SNAME *_heap_); \
\
- FMOD SNAME *PFX##_new(size_t size, HeapOrder HO, int (*compare)(V, V)) \
+ FMOD SNAME *PFX##_new(size_t capacity, HeapOrder HO, int (*compare)(V, V)) \
{ \
- if (size < 1) \
+ if (capacity < 1) \
return NULL; \
\
if (HO != MinHeap && HO != MaxHeap) \
@@ -156,7 +156,7 @@ typedef enum HeapOrder
if (!_heap_) \
return NULL; \
\
- _heap_->buffer = malloc(sizeof(V) * size); \
+ _heap_->buffer = malloc(sizeof(V) * capacity); \
\
if (!_heap_->buffer) \
{ \
@@ -164,9 +164,9 @@ typedef enum HeapOrder
return NULL; \
} \
\
- memset(_heap_->buffer, 0, sizeof(V) * size); \
+ memset(_heap_->buffer, 0, sizeof(V) * capacity); \
\
- _heap_->capacity = size; \
+ _heap_->capacity = capacity; \
_heap_->count = 0; \
_heap_->HO = HO; \
_heap_->cmp = compare; \
diff --git a/src/queue.h b/src/queue.h
index 0dc1dfb..a45980e 100644
--- a/src/queue.h
+++ b/src/queue.h
@@ -80,7 +80,7 @@
\
/* Collection Functions */ \
/* Collection Allocation and Deallocation */ \
- FMOD SNAME *PFX##_new(size_t size); \
+ FMOD SNAME *PFX##_new(size_t capacity); \
FMOD void PFX##_clear(SNAME *_queue_); \
FMOD void PFX##_free(SNAME *_queue_); \
/* Collection Input and Output */ \
@@ -135,9 +135,9 @@
static SNAME##_iter PFX##_impl_it_start(SNAME *_queue_); \
static SNAME##_iter PFX##_impl_it_end(SNAME *_queue_); \
\
- FMOD SNAME *PFX##_new(size_t size) \
+ FMOD SNAME *PFX##_new(size_t capacity) \
{ \
- if (size < 1) \
+ if (capacity < 1) \
return NULL; \
\
SNAME *_queue_ = malloc(sizeof(SNAME)); \
@@ -145,7 +145,7 @@
if (!_queue_) \
return NULL; \
\
- _queue_->buffer = malloc(sizeof(V) * size); \
+ _queue_->buffer = malloc(sizeof(V) * capacity); \
\
if (!_queue_->buffer) \
{ \
@@ -153,9 +153,9 @@
return NULL; \
} \
\
- memset(_queue_->buffer, 0, sizeof(V) * size); \
+ memset(_queue_->buffer, 0, sizeof(V) * capacity); \
\
- _queue_->capacity = size; \
+ _queue_->capacity = capacity; \
_queue_->count = 0; \
_queue_->front = 0; \
_queue_->rear = 0; \
diff --git a/src/stack.h b/src/stack.h
index f59933b..e3879d2 100644
--- a/src/stack.h
+++ b/src/stack.h
@@ -71,7 +71,7 @@
\
/* Collection Functions */ \
/* Collection Allocation and Deallocation */ \
- FMOD SNAME *PFX##_new(size_t size); \
+ FMOD SNAME *PFX##_new(size_t capacity); \
FMOD void PFX##_clear(SNAME *_stack_); \
FMOD void PFX##_free(SNAME *_stack_); \
/* Collection Input and Output */ \
@@ -126,9 +126,9 @@
static SNAME##_iter PFX##_impl_it_start(SNAME *_stack_); \
static SNAME##_iter PFX##_impl_it_end(SNAME *_stack_); \
\
- FMOD SNAME *PFX##_new(size_t size) \
+ FMOD SNAME *PFX##_new(size_t capacity) \
{ \
- if (size < 1) \
+ if (capacity < 1) \
return NULL; \
\
SNAME *_stack_ = malloc(sizeof(SNAME)); \
@@ -136,7 +136,7 @@
if (!_stack_) \
return NULL; \
\
- _stack_->buffer = malloc(sizeof(V) * size); \
+ _stack_->buffer = malloc(sizeof(V) * capacity); \
\
if (!_stack_->buffer) \
{ \
@@ -146,7 +146,7 @@
\
memset(_stack_->buffer, 0, sizeof(V) * size); \
\
- _stack_->capacity = size; \
+ _stack_->capacity = capacity; \
_stack_->count = 0; \
\
_stack_->it_start = PFX##_impl_it_start; \