diff --git a/src/cmc/hashset.h b/src/cmc/hashset.h index 1cbf3c0..7e6ae1d 100644 --- a/src/cmc/hashset.h +++ b/src/cmc/hashset.h @@ -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) \ { \ diff --git a/src/cor/core.h b/src/cor/core.h index 375c597..2a6979f 100644 --- a/src/cor/core.h +++ b/src/cor/core.h @@ -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 diff --git a/src/ext/cmc/hashmap.h b/src/ext/cmc/hashmap.h index 8ae193c..46f0149 100644 --- a/src/ext/cmc/hashmap.h +++ b/src/ext/cmc/hashmap.h @@ -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) \ diff --git a/src/ext/cmc/hashmultiset.h b/src/ext/cmc/hashmultiset.h index a55617b..975b868 100644 --- a/src/ext/cmc/hashmultiset.h +++ b/src/ext/cmc/hashmultiset.h @@ -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) \ diff --git a/src/ext/cmc/hashset.h b/src/ext/cmc/hashset.h index fab2d76..d53d06a 100644 --- a/src/ext/cmc/hashset.h +++ b/src/ext/cmc/hashset.h @@ -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 */ diff --git a/src/macro_collections.h b/src/macro_collections.h index 31ec322..237b580 100644 --- a/src/macro_collections.h +++ b/src/macro_collections.h @@ -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__) diff --git a/tests/main/src/hashset.c b/tests/main/src/hashset.c index 4f39d25..94fb021 100644 --- a/tests/main/src/hashset.c +++ b/tests/main/src/hashset.c @@ -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_ = diff --git a/tests/to_string.c b/tests/to_string.c index 2b59500..531bfb6 100644 --- a/tests/to_string.c +++ b/tests/to_string.c @@ -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