Adding and fixing things, documenting code and moving more stuff to EXT
This commit is contained in:
1 parent
b85f3d1f81
commit
624d1613f0
8 files changed
+514
-355
No files matched your search
+1
-319
@@ -29,21 +29,6 @@
|
||||
* ------------------------------------------------------------------------- */
|
||||
#include "../cor/hashtable.h"
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* HashSet specific
|
||||
* ------------------------------------------------------------------------- */
|
||||
/* to_string format */
|
||||
static const char *cmc_cmc_string_fmt_hashset = "struct %s<%s> "
|
||||
"at %p { "
|
||||
"buffer:%p, "
|
||||
"capacity:%" PRIuMAX ", "
|
||||
"count:%" PRIuMAX ", "
|
||||
"load:%lf, "
|
||||
"flag:%d, "
|
||||
"f_val:%p, "
|
||||
"alloc:%p, "
|
||||
"callbacks: %p }";
|
||||
|
||||
/**
|
||||
* Core HashSet implementation
|
||||
*/
|
||||
@@ -183,8 +168,6 @@ static const char *cmc_cmc_string_fmt_hashset = "struct %s<%s> "
|
||||
bool CMC_(PFX, _resize)(struct SNAME * _set_, size_t capacity); \
|
||||
struct SNAME *CMC_(PFX, _copy_of)(struct SNAME * _set_); \
|
||||
bool CMC_(PFX, _equals)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
struct cmc_string CMC_(PFX, _to_string)(struct SNAME * _set_); \
|
||||
bool CMC_(PFX, _print)(struct SNAME * _set_, FILE * fptr); \
|
||||
\
|
||||
/* Set Operations */ \
|
||||
struct SNAME *CMC_(PFX, _union)(struct SNAME * _set1_, \
|
||||
@@ -203,29 +186,7 @@ static const char *cmc_cmc_string_fmt_hashset = "struct %s<%s> "
|
||||
bool CMC_(PFX, _is_proper_superset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_disjointset)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_); \
|
||||
\
|
||||
/* Iterator Functions */ \
|
||||
/* Iterator Initialization */ \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target); \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target); \
|
||||
/* Iterator State */ \
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
/* Iterator Movement */ \
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t steps); \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t steps); \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t index); \
|
||||
/* Iterator Access */ \
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
struct SNAME * _set2_);
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* Source
|
||||
@@ -737,35 +698,6 @@ static const char *cmc_cmc_string_fmt_hashset = "struct %s<%s> "
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
struct cmc_string CMC_(PFX, _to_string)(struct SNAME * _set_) \
|
||||
{ \
|
||||
struct cmc_string str; \
|
||||
struct SNAME *s_ = _set_; \
|
||||
\
|
||||
int n = \
|
||||
snprintf(str.s, cmc_string_len, cmc_cmc_string_fmt_hashset, \
|
||||
#SNAME, #V, s_, s_->buffer, s_->capacity, s_->count, \
|
||||
s_->load, s_->flag, s_->f_val, s_->alloc, s_->callbacks); \
|
||||
\
|
||||
return n >= 0 ? str : (struct cmc_string){ 0 }; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _print)(struct SNAME * _set_, FILE * fptr) \
|
||||
{ \
|
||||
for (size_t i = 0; i < _set_->capacity; i++) \
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *entry = &(_set_->buffer[i]); \
|
||||
\
|
||||
if (entry->state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
if (!_set_->f_val->str(fptr, entry->value)) \
|
||||
return false; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _union)(struct SNAME * _set1_, \
|
||||
struct SNAME * _set2_) \
|
||||
{ \
|
||||
@@ -1020,256 +952,6 @@ static const char *cmc_cmc_string_fmt_hashset = "struct %s<%s> "
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = 0; \
|
||||
iter.index = 0; \
|
||||
iter.first = 0; \
|
||||
iter.last = 0; \
|
||||
iter.start = true; \
|
||||
iter.end = CMC_(PFX, _empty)(target); \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
for (size_t i = 0; i < target->capacity; i++) \
|
||||
{ \
|
||||
if (target->buffer[i].state == CMC_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 == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = 0; \
|
||||
iter.index = 0; \
|
||||
iter.first = 0; \
|
||||
iter.last = 0; \
|
||||
iter.start = CMC_(PFX, _empty)(target); \
|
||||
iter.end = true; \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
for (size_t i = 0; i < target->capacity; i++) \
|
||||
{ \
|
||||
if (target->buffer[i].state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.first = i; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
for (size_t i = target->capacity; i > 0; i--) \
|
||||
{ \
|
||||
if (target->buffer[i - 1].state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
iter.cursor = iter.last; \
|
||||
iter.index = target->count - 1; \
|
||||
} \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->first; \
|
||||
iter->index = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->last; \
|
||||
iter->index = iter->target->count - 1; \
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
iter->end = true; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
struct CMC_DEF_ENTRY(SNAME) *scan = \
|
||||
&(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
iter->index++; \
|
||||
\
|
||||
while (1) \
|
||||
{ \
|
||||
iter->cursor++; \
|
||||
scan = &(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
if (scan->state == CMC_ES_FILLED) \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
struct CMC_DEF_ENTRY(SNAME) *scan = \
|
||||
&(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
iter->index--; \
|
||||
\
|
||||
while (1) \
|
||||
{ \
|
||||
iter->cursor--; \
|
||||
scan = &(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
if (scan->state == CMC_ES_FILLED) \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t steps) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index + steps >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
CMC_(PFX, _iter_next)(iter); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t steps) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index < steps) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
CMC_(PFX, _iter_prev)(iter); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator was able to be positioned at the */ \
|
||||
/* given index */ \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t index) \
|
||||
{ \
|
||||
if (index >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index > index) \
|
||||
return CMC_(PFX, _iter_rewind)(iter, iter->index - index); \
|
||||
else if (iter->index < index) \
|
||||
return CMC_(PFX, _iter_advance)(iter, index - iter->index); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (V){ 0 }; \
|
||||
\
|
||||
return iter->target->buffer[iter->cursor].value; \
|
||||
} \
|
||||
\
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return iter->index; \
|
||||
} \
|
||||
\
|
||||
static struct CMC_DEF_ENTRY(SNAME) * \
|
||||
CMC_(PFX, _impl_get_entry)(struct SNAME * _set_, V value) \
|
||||
{ \
|
||||
|
||||
+1
-1
@@ -84,7 +84,7 @@
|
||||
* K - Key type
|
||||
* V - Value type
|
||||
*
|
||||
* PARAM := (PFX, SNAME, SIZE, K, V)
|
||||
* PARAMS := (PFX, SNAME, SIZE, K, V)
|
||||
*/
|
||||
#define CMC_PARAM_PFX CMC_TUP_0
|
||||
#define CMC_PARAM_SNAME CMC_TUP_1
|
||||
|
||||
@@ -449,9 +449,6 @@ static const char *cmc_cmc_string_fmt_hashmap = "struct %s<%s, %s> "
|
||||
|
||||
/**
|
||||
* STR
|
||||
*
|
||||
* The part 'STR' gives a new way of initializing a collection. The collection
|
||||
* struct is not heap allocated, only its internal structure (nodes, buffers).
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHMAP_STR(BODY) \
|
||||
CMC_EXT_CMC_HASHMAP_STR_HEADER(BODY) \
|
||||
|
||||
@@ -358,9 +358,6 @@ static const char *cmc_cmc_string_fmt_hashmultiset =
|
||||
|
||||
/**
|
||||
* STR
|
||||
*
|
||||
* The part 'STR' gives a new way of initializing a collection. The collection
|
||||
* struct is not heap allocated, only its internal structure (nodes, buffers).
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHMULTISET_STR(BODY) \
|
||||
CMC_EXT_CMC_HASHMULTISET_STR_HEADER(BODY) \
|
||||
|
||||
+397
-1
@@ -16,6 +16,402 @@
|
||||
/**
|
||||
* All the EXT parts of CMC HashSet.
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHSET_PARTS
|
||||
#define CMC_EXT_CMC_HASHSET_PARTS ITER, STR
|
||||
|
||||
/* Used by STR */
|
||||
static const char *cmc_cmc_string_fmt_hashset = "struct %s<%s> "
|
||||
"at %p { "
|
||||
"buffer:%p, "
|
||||
"capacity:%" PRIuMAX ", "
|
||||
"count:%" PRIuMAX ", "
|
||||
"load:%lf, "
|
||||
"flag:%d, "
|
||||
"f_val:%p, "
|
||||
"alloc:%p, "
|
||||
"callbacks: %p }";
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHSET_ITER(BODY) \
|
||||
CMC_EXT_CMC_HASHSET_ITER_HEADER(BODY) \
|
||||
CMC_EXT_CMC_HASHSET_ITER_SOURCE(BODY)
|
||||
|
||||
#define CMC_EXT_CMC_HASHSET_ITER_HEADER(BODY) \
|
||||
CMC_EXT_CMC_HASHSET_ITER_HEADER_(CMC_PARAM_PFX(BODY), \
|
||||
CMC_PARAM_SNAME(BODY), CMC_PARAM_V(BODY))
|
||||
|
||||
#define CMC_EXT_CMC_HASHSET_ITER_SOURCE(BODY) \
|
||||
CMC_EXT_CMC_HASHSET_ITER_SOURCE_(CMC_PARAM_PFX(BODY), \
|
||||
CMC_PARAM_SNAME(BODY), CMC_PARAM_V(BODY))
|
||||
|
||||
#define CMC_EXT_CMC_HASHSET_ITER_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
/* HashSet Iterator */ \
|
||||
struct CMC_DEF_ITER(SNAME) \
|
||||
{ \
|
||||
/* Target HashSet */ \
|
||||
struct SNAME *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; \
|
||||
}; \
|
||||
\
|
||||
/* Iterator Initialization */ \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target); \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target); \
|
||||
/* Iterator State */ \
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
/* Iterator Movement */ \
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t steps); \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t steps); \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t index); \
|
||||
/* Iterator Access */ \
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
|
||||
#define CMC_EXT_CMC_HASHSET_ITER_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = 0; \
|
||||
iter.index = 0; \
|
||||
iter.first = 0; \
|
||||
iter.last = 0; \
|
||||
iter.start = true; \
|
||||
iter.end = CMC_(PFX, _empty)(target); \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
for (size_t i = 0; i < target->capacity; i++) \
|
||||
{ \
|
||||
if (target->buffer[i].state == CMC_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 == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = 0; \
|
||||
iter.index = 0; \
|
||||
iter.first = 0; \
|
||||
iter.last = 0; \
|
||||
iter.start = CMC_(PFX, _empty)(target); \
|
||||
iter.end = true; \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
for (size_t i = 0; i < target->capacity; i++) \
|
||||
{ \
|
||||
if (target->buffer[i].state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.first = i; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
for (size_t i = target->capacity; i > 0; i--) \
|
||||
{ \
|
||||
if (target->buffer[i - 1].state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
iter.cursor = iter.last; \
|
||||
iter.index = target->count - 1; \
|
||||
} \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->first; \
|
||||
iter->index = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->last; \
|
||||
iter->index = iter->target->count - 1; \
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
iter->end = true; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
struct CMC_DEF_ENTRY(SNAME) *scan = \
|
||||
&(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
iter->index++; \
|
||||
\
|
||||
while (1) \
|
||||
{ \
|
||||
iter->cursor++; \
|
||||
scan = &(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
if (scan->state == CMC_ES_FILLED) \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
struct CMC_DEF_ENTRY(SNAME) *scan = \
|
||||
&(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
iter->index--; \
|
||||
\
|
||||
while (1) \
|
||||
{ \
|
||||
iter->cursor--; \
|
||||
scan = &(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
if (scan->state == CMC_ES_FILLED) \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t steps) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index + steps >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
CMC_(PFX, _iter_next)(iter); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t steps) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index < steps) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
CMC_(PFX, _iter_prev)(iter); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator was able to be positioned at the */ \
|
||||
/* given index */ \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, \
|
||||
size_t index) \
|
||||
{ \
|
||||
if (index >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index > index) \
|
||||
return CMC_(PFX, _iter_rewind)(iter, iter->index - index); \
|
||||
else if (iter->index < index) \
|
||||
return CMC_(PFX, _iter_advance)(iter, index - iter->index); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (V){ 0 }; \
|
||||
\
|
||||
return iter->target->buffer[iter->cursor].value; \
|
||||
} \
|
||||
\
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return iter->index; \
|
||||
}
|
||||
|
||||
/**
|
||||
* STR
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHSET_STR(BODY) \
|
||||
CMC_EXT_CMC_HASHSET_STR_HEADER(BODY) \
|
||||
CMC_EXT_CMC_HASHSET_STR_SOURCE(BODY)
|
||||
|
||||
#define CMC_EXT_CMC_HASHSET_STR_HEADER(BODY) \
|
||||
CMC_EXT_CMC_HASHSET_STR_HEADER_(CMC_PARAM_PFX(BODY), \
|
||||
CMC_PARAM_SNAME(BODY), CMC_PARAM_V(BODY))
|
||||
|
||||
#define CMC_EXT_CMC_HASHSET_STR_SOURCE(BODY) \
|
||||
CMC_EXT_CMC_HASHSET_STR_SOURCE_(CMC_PARAM_PFX(BODY), \
|
||||
CMC_PARAM_SNAME(BODY), CMC_PARAM_V(BODY))
|
||||
|
||||
#define CMC_EXT_CMC_HASHSET_STR_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _set_, FILE * fptr); \
|
||||
bool CMC_(PFX, _print)(struct SNAME * _set_, FILE * fptr, \
|
||||
const char *start, const char *separator, \
|
||||
const char *end);
|
||||
|
||||
#define CMC_EXT_CMC_HASHSET_STR_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _set_, FILE * fptr) \
|
||||
{ \
|
||||
struct SNAME *s_ = _set_; \
|
||||
\
|
||||
return 0 <= fprintf(fptr, cmc_cmc_string_fmt_hashset, \
|
||||
CMC_TO_STRING(SNAME), CMC_TO_STRING(V), s_, \
|
||||
s_->buffer, s_->capacity, s_->count, s_->load, \
|
||||
s_->flag, s_->f_val, s_->alloc, s_->callbacks); \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _print)(struct SNAME * _set_, FILE * fptr, \
|
||||
const char *start, const char *separator, \
|
||||
const char *end) \
|
||||
{ \
|
||||
fprintf(fptr, "%s", start); \
|
||||
\
|
||||
size_t last = 0; \
|
||||
for (size_t i = _set_->capacity; i > 0; i--) \
|
||||
{ \
|
||||
if ((_set_->buffer[i - 1]).state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
for (size_t i = 0; i < _set_->capacity; i++) \
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *entry = &(_set_->buffer[i]); \
|
||||
\
|
||||
if (entry->state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
if (!_set_->f_val->str(fptr, entry->value)) \
|
||||
return false; \
|
||||
\
|
||||
if (i + 1 < last) \
|
||||
fprintf(fptr, "%s", separator); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
fprintf(fptr, "%s", end); \
|
||||
\
|
||||
return true; \
|
||||
}
|
||||
|
||||
#endif /* CMC_EXT_CMC_HASHSET_H */
|
||||
+104
-3
@@ -8,6 +8,21 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file provides everything from the C Macro Collections library.
|
||||
*
|
||||
* Every data structure and features are available through this header. There is
|
||||
* also three macros that can help you generate whichever Collection you need
|
||||
* from any given sub-library. They are:
|
||||
*
|
||||
* - C_MACRO_COLLECTIONS
|
||||
* - C_MACRO_COLLECTIONS_GEN
|
||||
* - C_MACRO_COLLECTIONS_GEN_HEADER
|
||||
* - C_MACRO_COLLECTIONS_GEN_SOURCE
|
||||
* - C_MACRO_COLLECTIONS_ALL
|
||||
* - C_MACRO_COLLECTIONS_ALL_HEADER
|
||||
* - C_MACRO_COLLECTIONS_ALL_SOURCE
|
||||
*/
|
||||
#ifndef CMC_MACRO_COLLECTIONS_H
|
||||
#define CMC_MACRO_COLLECTIONS_H
|
||||
|
||||
@@ -41,6 +56,7 @@
|
||||
#include "ext/cmc/hashmap.h" /* Added in 25/05/2020 */
|
||||
#include "ext/cmc/hashmultimap.h" /* Added in 29/05/2020 */
|
||||
#include "ext/cmc/hashmultiset.h" /* Added in 30/05/2020 */
|
||||
#include "ext/cmc/hashset.h" /* Added in 31/05/2020 */
|
||||
|
||||
#include "utl/assert.h" /* Added in 27/06/2019 */
|
||||
#include "utl/foreach.h" /* Added in 25/02/2019 */
|
||||
@@ -53,7 +69,15 @@
|
||||
// clang-format on
|
||||
|
||||
/**
|
||||
* Generate a specific part of a collection
|
||||
* C_MACRO_COLLECTIONS
|
||||
*
|
||||
* Generate a specific part of a specific collection from a specific library.
|
||||
*
|
||||
* \param LIB The collection's sub-library
|
||||
* \param COLLECTION The name of the collection in all uppercase
|
||||
* \param PART The part of the collection (either CORE or one available at EXT)
|
||||
* \param FILE Either HEADER or SOURCE
|
||||
* \param PARAMS A tuple of form (PFX, SNAME, SIZE, K, V)
|
||||
*/
|
||||
#define C_MACRO_COLLECTIONS(LIB, COLLECTION, PART, FILE, PARAMS) \
|
||||
C_MACRO_COLLECTIONS_(LIB, COLLECTION, PART, FILE)(PARAMS)
|
||||
@@ -61,26 +85,102 @@
|
||||
CMC_##LIB##_##COLLECTION##_##PART##_##FILE
|
||||
|
||||
/**
|
||||
* Generate everything provided by a collection included in ext
|
||||
* C_MACRO_COLLECTIONS_GEN
|
||||
*
|
||||
* Generate the CORE of a collection along with one or more part from EXT. The
|
||||
* headers are generated first, then the source code.
|
||||
*
|
||||
* \param LIB The collection's sub-library
|
||||
* \param COLLECTION The name of the collection in all uppercase
|
||||
* \param PARAMS A tuple of form (PFX, SNAME, SIZE, K, V)
|
||||
* \param PARTS A non-empty tuple of all desired EXT parts
|
||||
*/
|
||||
#define C_MACRO_COLLECTIONS_GEN(LIB, COLLECTION, PARAMS, PARTS) \
|
||||
C_MACRO_COLLECTIONS_GEN_HEADER(LIB, COLLECTION, PARAMS, PARTS) \
|
||||
C_MACRO_COLLECTIONS_GEN_SOURCE(LIB, COLLECTION, PARAMS, PARTS)
|
||||
|
||||
/**
|
||||
* C_MACRO_COLLECTIONS_GEN_HEADER
|
||||
*
|
||||
* Generate all headers of CORE and the specified header parts of a collection.
|
||||
*
|
||||
* \param LIB The collection's sub-library
|
||||
* \param COLLECTION The name of the collection in all uppercase
|
||||
* \param PARAMS A tuple of form (PFX, SNAME, SIZE, K, V)
|
||||
* \param PARTS A non-empty tuple of all desired EXT parts
|
||||
*/
|
||||
#define C_MACRO_COLLECTIONS_GEN_HEADER(LIB, COLLECTION, PARAMS, PARTS) \
|
||||
C_MACRO_COLLECTIONS(LIB, COLLECTION, CORE, HEADER, PARAMS) \
|
||||
CMC_MAP(CMC_(EXT_, LIB), COLLECTION, HEADER, PARAMS, CMC_EVAL PARTS)
|
||||
|
||||
/**
|
||||
* C_MACRO_COLLECTIONS_GEN_SOURCE
|
||||
*
|
||||
* Generate all sources of CORE and the specified source parts of a collection.
|
||||
*
|
||||
* \param LIB The collection's sub-library
|
||||
* \param COLLECTION The name of the collection in all uppercase
|
||||
* \param PARAMS A tuple of form (PFX, SNAME, SIZE, K, V)
|
||||
* \param PARTS A non-empty tuple of all desired EXT parts
|
||||
*/
|
||||
#define C_MACRO_COLLECTIONS_GEN_SOURCE(LIB, COLLECTION, PARAMS, PARTS) \
|
||||
C_MACRO_COLLECTIONS(LIB, COLLECTION, CORE, SOURCE, PARAMS) \
|
||||
CMC_MAP(CMC_(EXT_, LIB), COLLECTION, SOURCE, PARAMS, CMC_EVAL PARTS)
|
||||
|
||||
/**
|
||||
* C_MACRO_COLLECTIONS_ALL
|
||||
*
|
||||
* Generate everything provided by a collection included in the EXT library. The
|
||||
* headers are generated first, then the source code.
|
||||
*
|
||||
* \param LIB The collection's library
|
||||
* \param COLLECTION The name of the collection in all uppercase
|
||||
* \param PARAMS A tuple of form (PFX, SNAME, SIZE, K, V
|
||||
*/
|
||||
#define C_MACRO_COLLECTIONS_ALL(LIB, COLLECTION, PARAMS) \
|
||||
C_MACRO_COLLECTIONS_ALL_HEADER(LIB, COLLECTION, PARAMS) \
|
||||
C_MACRO_COLLECTIONS_ALL_SOURCE(LIB, COLLECTION, PARAMS)
|
||||
|
||||
/**
|
||||
* C_MACRO_COLLECTIONS_ALL_HEADER
|
||||
*
|
||||
* Generates all headers (CORE and those at EXT) from a given collection.
|
||||
*
|
||||
* \param LIB The collection's library
|
||||
* \param COLLECTION The name of the collection in all uppercase
|
||||
* \param PARAMS A tuple of form (PFX, SNAME, SIZE, K, V
|
||||
*/
|
||||
#define C_MACRO_COLLECTIONS_ALL_HEADER(LIB, COLLECTION, PARAMS) \
|
||||
C_MACRO_COLLECTIONS(LIB, COLLECTION, CORE, HEADER, PARAMS) \
|
||||
CMC_MAP(CMC_(EXT_, LIB), COLLECTION, HEADER, PARAMS, \
|
||||
C_MACRO_COLLECTIONS_PARTS(LIB, COLLECTION))
|
||||
|
||||
/**
|
||||
* C_MACRO_COLLECTIONS_ALL_SOURCE
|
||||
*
|
||||
* Generates all sources (CORE and those at EXT) from a given collection.
|
||||
*
|
||||
* \param LIB The collection's library
|
||||
* \param COLLECTION The name of the collection in all uppercase
|
||||
* \param PARAMS A tuple of form (PFX, SNAME, SIZE, K, V
|
||||
*/
|
||||
#define C_MACRO_COLLECTIONS_ALL_SOURCE(LIB, COLLECTION, PARAMS) \
|
||||
C_MACRO_COLLECTIONS(LIB, COLLECTION, CORE, SOURCE, PARAMS) \
|
||||
CMC_MAP(CMC_(EXT_, LIB), COLLECTION, SOURCE, PARAMS, \
|
||||
C_MACRO_COLLECTIONS_PARTS(LIB, COLLECTION))
|
||||
|
||||
/* Gets the macro with all EXT parts of a collection */
|
||||
/**
|
||||
* C_MACRO_COLLECTIONS_PARTS
|
||||
*
|
||||
* Gets the macro with all EXT parts of a collection. Every collection has this
|
||||
* macro defined in the EXT libraries.
|
||||
*/
|
||||
#define C_MACRO_COLLECTIONS_PARTS(LIB, COLLECTION) \
|
||||
CMC_EXT_##LIB##_##COLLECTION##_PARTS,
|
||||
|
||||
/* Evaluates a tuple so that (A, B) -> A, B, */
|
||||
#define CMC_EVAL(...) __VA_ARGS__,
|
||||
|
||||
/**
|
||||
* A __VA_ARGS__ argument counter. This argument counter is slightly shifted:
|
||||
*
|
||||
@@ -103,6 +203,7 @@
|
||||
28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, \
|
||||
11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
|
||||
|
||||
/* Generates the FILE for each part (__VA_ARGS__) of a collection */
|
||||
#define CMC_MAP(LIB, COLLECTION, FILE, PARAMS, ...) \
|
||||
CMC_(CMC_MAP_, CMC_NARG(__VA_ARGS__)) \
|
||||
(LIB, COLLECTION, FILE, PARAMS, __VA_ARGS__)
|
||||
|
||||
@@ -455,30 +455,6 @@ _Bool hs_equals(struct hashset *_set1_, struct hashset *_set2_)
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
struct cmc_string hs_to_string(struct hashset *_set_)
|
||||
{
|
||||
struct cmc_string str;
|
||||
struct hashset *s_ = _set_;
|
||||
int n = snprintf(str.s, cmc_string_len, cmc_cmc_string_fmt_hashset,
|
||||
"CMC_PARAM_SNAME((hs, hashset, , , size_t))",
|
||||
"CMC_PARAM_V((hs, hashset, , , size_t))", s_, s_->buffer,
|
||||
s_->capacity, s_->count, s_->load, s_->flag, s_->f_val,
|
||||
s_->alloc, s_->callbacks);
|
||||
return n >= 0 ? str : (struct cmc_string){ 0 };
|
||||
}
|
||||
_Bool hs_print(struct hashset *_set_, FILE *fptr)
|
||||
{
|
||||
for (size_t i = 0; i < _set_->capacity; i++)
|
||||
{
|
||||
struct hashset_entry *entry = &(_set_->buffer[i]);
|
||||
if (entry->state == CMC_ES_FILLED)
|
||||
{
|
||||
if (!_set_->f_val->str(fptr, entry->value))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
struct hashset *hs_union(struct hashset *_set1_, struct hashset *_set2_)
|
||||
{
|
||||
struct hashset *_set_r_ =
|
||||
|
||||
+11
-1
@@ -7,6 +7,7 @@ C_MACRO_COLLECTIONS_ALL(CMC, DEQUE, ( d, deque, , , int))
|
||||
C_MACRO_COLLECTIONS_ALL(CMC, HASHMAP, ( hm, hashmap, , int, int))
|
||||
C_MACRO_COLLECTIONS_ALL(CMC, HASHMULTIMAP, (hmm, hashmultimap, , int, int))
|
||||
C_MACRO_COLLECTIONS_ALL(CMC, HASHMULTISET, (hms, hashmultiset, , , int))
|
||||
C_MACRO_COLLECTIONS_ALL(CMC, HASHSET, ( hs, hashset, , , int))
|
||||
|
||||
struct
|
||||
{
|
||||
@@ -26,7 +27,10 @@ int main(void)
|
||||
struct hashmultimap *hmm = hmm_new(100, 0.8,
|
||||
(struct hashmultimap_fkey *)&int_ftab,
|
||||
(struct hashmultimap_fval *)&int_ftab);
|
||||
struct hashmultiset *hms = hms_new(100, 0.6, (struct hashmultiset_fval *)&int_ftab);
|
||||
struct hashmultiset *hms = hms_new(100, 0.6,
|
||||
(struct hashmultiset_fval *)&int_ftab);
|
||||
struct hashset *hs = hs_new(100, 0.6,
|
||||
(struct hashset_fval *)&int_ftab);
|
||||
|
||||
d_to_string(d, stdout);
|
||||
d_print(d, stdout, "\n[ ", ", ", " ]\n");
|
||||
@@ -36,6 +40,8 @@ int main(void)
|
||||
hmm_print(hmm, stdout, "\n[ {", "}, {", "} ]\n", " : ");
|
||||
hms_to_string(hms, stdout);
|
||||
hms_print(hms, stdout, "\n[ {", "}, {", "} ]\n", " : ");
|
||||
hs_to_string(hs, stdout);
|
||||
hs_print(hs, stdout, "\n[ ", ", ", " ]\n");
|
||||
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
@@ -43,6 +49,7 @@ int main(void)
|
||||
hm_insert(hm, i, i);
|
||||
hmm_insert(hmm, i, i);
|
||||
hms_insert(hms, i);
|
||||
hs_insert(hs, i);
|
||||
}
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
@@ -55,11 +62,14 @@ int main(void)
|
||||
hmm_print(hmm, stdout, "\n[ {", "}, {", "} ]\n", " : ");
|
||||
hms_to_string(hms, stdout);
|
||||
hms_print(hms, stdout, "\n[ {", "}, {", "} ]\n", " : ");
|
||||
hs_to_string(hs, stdout);
|
||||
hs_print(hs, stdout, "\n[ ", ", ", " ]\n");
|
||||
|
||||
d_free(d);
|
||||
hm_free(hm);
|
||||
hmm_free(hmm);
|
||||
hms_free(hms);
|
||||
hs_free(hs);
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
Reference in new issue
Block a user