diff --git a/src/cmc/hashbidimap.h b/src/cmc/hashbidimap.h index 00006d6..00dd671 100644 --- a/src/cmc/hashbidimap.h +++ b/src/cmc/hashbidimap.h @@ -1049,9 +1049,9 @@ static const char *cmc_cmc_string_fmt_hashbidimap = "struct %s<%s, %s> " { \ for (size_t i = 0; i < target->capacity; i++) \ { \ - struct CMC_DEF_ENTRY(SNAME) *tmp = target->buffer[i][0]; \ + struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i][0]; \ \ - if (tmp != NULL && tmp != CMC_ENTRY_DELETED) \ + if (entry && entry != CMC_ENTRY_DELETED) \ { \ iter->first = i; \ break; \ @@ -1062,9 +1062,9 @@ static const char *cmc_cmc_string_fmt_hashbidimap = "struct %s<%s, %s> " \ for (size_t i = target->capacity; i > 0; i--) \ { \ - struct CMC_DEF_ENTRY(SNAME) *tmp = target->buffer[i - 1][0]; \ + struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i - 1][0]; \ \ - if (tmp != NULL && tmp != CMC_ENTRY_DELETED) \ + if (entry && entry != CMC_ENTRY_DELETED) \ { \ iter->last = i - 1; \ break; \ diff --git a/src/cmc/hashmultiset.h b/src/cmc/hashmultiset.h index b2c5613..e816b57 100644 --- a/src/cmc/hashmultiset.h +++ b/src/cmc/hashmultiset.h @@ -36,23 +36,6 @@ * ------------------------------------------------------------------------- */ #include "../cor/hashtable.h" -/* ------------------------------------------------------------------------- - * HashMultiSet specific - * ------------------------------------------------------------------------- */ -/* to_string format */ -static const char *cmc_cmc_string_fmt_hashmultiset = - "struct %s<%s> " - "at %p { " - "buffer:%p, " - "capacity:%" PRIuMAX ", " - "count:%" PRIuMAX ", " - "cardinality:%" PRIuMAX ", " - "load:%lf, " - "flag:%d, " - "f_val:%p, " - "alloc:%p, " - "callbacks:%p }"; - /** * Core HashMultiSet implementation */ @@ -142,31 +125,6 @@ static const char *cmc_cmc_string_fmt_hashmultiset = int (*pri)(V, V); \ }; \ \ - /* HashMultiset Iterator */ \ - struct CMC_DEF_ITER(SNAME) \ - { \ - /* Target HashMultiset */ \ - 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; \ - }; \ - \ /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ struct SNAME *CMC_(PFX, _new)(size_t capacity, double load, \ @@ -204,8 +162,6 @@ static const char *cmc_cmc_string_fmt_hashmultiset = 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_, \ @@ -226,30 +182,7 @@ static const char *cmc_cmc_string_fmt_hashmultiset = 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_multiplicity)(struct CMC_DEF_ITER(SNAME) * iter); \ - size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter); + struct SNAME * _set2_); /* ------------------------------------------------------------------------- * Source @@ -877,35 +810,6 @@ static const char *cmc_cmc_string_fmt_hashmultiset = 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_hashmultiset, #SNAME, \ - #V, s_, s_->buffer, s_->capacity, s_->count, s_->cardinality, \ - 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_) \ { \ @@ -1182,264 +1086,6 @@ static const char *cmc_cmc_string_fmt_hashmultiset = 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_multiplicity)(struct CMC_DEF_ITER(SNAME) * iter) \ - { \ - if (CMC_(PFX, _empty)(iter->target)) \ - return 0; \ - \ - return iter->target->buffer[iter->cursor].multiplicity; \ - } \ - \ - size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \ - { \ - return iter->index; \ - } \ - \ static size_t CMC_(PFX, _impl_multiplicity_of)(struct SNAME * _set_, \ V value) \ { \ diff --git a/src/ext/cmc/hashmap.h b/src/ext/cmc/hashmap.h index c21658a..8ae193c 100644 --- a/src/ext/cmc/hashmap.h +++ b/src/ext/cmc/hashmap.h @@ -131,7 +131,7 @@ static const char *cmc_cmc_string_fmt_hashmap = "struct %s<%s, %s> " #define CMC_EXT_CMC_HASHMAP_ITER_HEADER_(PFX, SNAME, K, V) \ \ - /* Hashmap Iterator */ \ + /* HashMap Iterator */ \ struct CMC_DEF_ITER(SNAME) \ { \ /* Target hashmap */ \ diff --git a/src/ext/cmc/hashmultimap.h b/src/ext/cmc/hashmultimap.h index 9a38aab..fdaa9e3 100644 --- a/src/ext/cmc/hashmultimap.h +++ b/src/ext/cmc/hashmultimap.h @@ -50,6 +50,7 @@ static const char *cmc_cmc_string_fmt_hashmultimap = "struct %s<%s, %s> " #define CMC_EXT_CMC_HASHMULTIMAP_ITER_HEADER_(PFX, SNAME, K, V) \ \ + /* HashMultiMap Iterator */ \ struct CMC_DEF_ITER(SNAME) \ { \ /* Target hashmultimap */ \ diff --git a/src/ext/cmc/hashmultiset.h b/src/ext/cmc/hashmultiset.h new file mode 100644 index 0000000..a55617b --- /dev/null +++ b/src/ext/cmc/hashmultiset.h @@ -0,0 +1,437 @@ +/** + * hashmultiset.h + * + * Creation Date: 30/05/2020 + * + * Authors: + * Leonardo Vencovsky (https://github.com/LeoVen) + * + */ + +#ifndef CMC_EXT_CMC_HASHMULTISET_H +#define CMC_EXT_CMC_HASHMULTISET_H + +#include "../../cor/core.h" + +/** + * All the EXT parts of CMC HashMultiSet. + */ +#define CMC_EXT_CMC_HASHMULTISET_PARTS ITER, STR + +/* Used by STR */ +static const char *cmc_cmc_string_fmt_hashmultiset = + "struct %s<%s> " + "at %p { " + "buffer:%p, " + "capacity:%" PRIuMAX ", " + "count:%" PRIuMAX ", " + "cardinality:%" PRIuMAX ", " + "load:%lf, " + "flag:%d, " + "f_val:%p, " + "alloc:%p, " + "callbacks:%p }"; + +/** + * ITER + */ +#define CMC_EXT_CMC_HASHMULTISET_ITER(BODY) \ + CMC_EXT_CMC_HASHMULTISET_ITER_HEADER(BODY) \ + CMC_EXT_CMC_HASHMULTISET_ITER_SOURCE(BODY) + +#define CMC_EXT_CMC_HASHMULTISET_ITER_HEADER(BODY) \ + CMC_EXT_CMC_HASHMULTISET_ITER_HEADER_( \ + CMC_PARAM_PFX(BODY), CMC_PARAM_SNAME(BODY), CMC_PARAM_V(BODY)) + +#define CMC_EXT_CMC_HASHMULTISET_ITER_SOURCE(BODY) \ + CMC_EXT_CMC_HASHMULTISET_ITER_SOURCE_( \ + CMC_PARAM_PFX(BODY), CMC_PARAM_SNAME(BODY), CMC_PARAM_V(BODY)) + +#define CMC_EXT_CMC_HASHMULTISET_ITER_HEADER_(PFX, SNAME, V) \ + \ + /* HashMultiSet Iterator */ \ + struct CMC_DEF_ITER(SNAME) \ + { \ + /* Target HashMultiset */ \ + 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_multiplicity)(struct CMC_DEF_ITER(SNAME) * iter); \ + size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter); + +#define CMC_EXT_CMC_HASHMULTISET_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_multiplicity)(struct CMC_DEF_ITER(SNAME) * iter) \ + { \ + if (CMC_(PFX, _empty)(iter->target)) \ + return 0; \ + \ + return iter->target->buffer[iter->cursor].multiplicity; \ + } \ + \ + size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \ + { \ + return iter->index; \ + } + +/** + * 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) \ + CMC_EXT_CMC_HASHMULTISET_STR_SOURCE(BODY) + +#define CMC_EXT_CMC_HASHMULTISET_STR_HEADER(BODY) \ + CMC_EXT_CMC_HASHMULTISET_STR_HEADER_( \ + CMC_PARAM_PFX(BODY), CMC_PARAM_SNAME(BODY), CMC_PARAM_V(BODY)) + +#define CMC_EXT_CMC_HASHMULTISET_STR_SOURCE(BODY) \ + CMC_EXT_CMC_HASHMULTISET_STR_SOURCE_( \ + CMC_PARAM_PFX(BODY), CMC_PARAM_SNAME(BODY), CMC_PARAM_V(BODY)) + +#define CMC_EXT_CMC_HASHMULTISET_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, const char *key_val_sep); + +#define CMC_EXT_CMC_HASHMULTISET_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_hashmultiset, \ + CMC_TO_STRING(SNAME), CMC_TO_STRING(V), s_, \ + s_->buffer, s_->capacity, s_->count, \ + s_->cardinality, 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, const char *val_mul_sep) \ + { \ + 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; \ + \ + fprintf(fptr, "%s", val_mul_sep); \ + \ + if (fprintf(fptr, "%" PRIuMAX "", entry->multiplicity) < 0) \ + return false; \ + \ + if (i + 1 < last) \ + fprintf(fptr, "%s", separator); \ + } \ + } \ + \ + fprintf(fptr, "%s", end); \ + \ + return true; \ + } + +#endif /* CMC_EXT_CMC_HASHMULTISET_H */ diff --git a/src/ext/cmc/hashset.h b/src/ext/cmc/hashset.h new file mode 100644 index 0000000..fab2d76 --- /dev/null +++ b/src/ext/cmc/hashset.h @@ -0,0 +1,21 @@ +/** + * hashset.h + * + * Creation Date: 29/05/2020 + * + * Authors: + * Leonardo Vencovsky (https://github.com/LeoVen) + * + */ + +#ifndef CMC_EXT_CMC_HASHSET_H +#define CMC_EXT_CMC_HASHSET_H + +#include "../../cor/core.h" + +/** + * All the EXT parts of CMC HashSet. + */ +#define CMC_EXT_CMC_HASHSET_PARTS + +#endif /* CMC_EXT_CMC_HASHSET_H */ diff --git a/src/macro_collections.h b/src/macro_collections.h index 06fc4bd..31ec322 100644 --- a/src/macro_collections.h +++ b/src/macro_collections.h @@ -40,6 +40,7 @@ #include "ext/cmc/deque.h" /* Added in 25/05/2020 */ #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 "utl/assert.h" /* Added in 27/06/2019 */ #include "utl/foreach.h" /* Added in 25/02/2019 */ diff --git a/tests/main/src/hashmultiset.c b/tests/main/src/hashmultiset.c index 1da5571..579799a 100644 --- a/tests/main/src/hashmultiset.c +++ b/tests/main/src/hashmultiset.c @@ -553,30 +553,6 @@ _Bool hms_equals(struct hashmultiset *_set1_, struct hashmultiset *_set2_) } return 1; } -struct cmc_string hms_to_string(struct hashmultiset *_set_) -{ - struct cmc_string str; - struct hashmultiset *s_ = _set_; - int n = snprintf(str.s, cmc_string_len, cmc_cmc_string_fmt_hashmultiset, - "CMC_PARAM_SNAME((hms, hashmultiset, , , size_t))", - "CMC_PARAM_V((hms, hashmultiset, , , size_t))", s_, - s_->buffer, s_->capacity, s_->count, s_->cardinality, - s_->load, s_->flag, s_->f_val, s_->alloc, s_->callbacks); - return n >= 0 ? str : (struct cmc_string){ 0 }; -} -_Bool hms_print(struct hashmultiset *_set_, FILE *fptr) -{ - for (size_t i = 0; i < _set_->capacity; i++) - { - struct hashmultiset_entry *entry = &(_set_->buffer[i]); - if (entry->state == CMC_ES_FILLED) - { - if (!_set_->f_val->str(fptr, entry->value)) - return 0; - } - } - return 1; -} struct hashmultiset *hms_union(struct hashmultiset *_set1_, struct hashmultiset *_set2_) { diff --git a/tests/to_string.c b/tests/to_string.c index 18acdde..2b59500 100644 --- a/tests/to_string.c +++ b/tests/to_string.c @@ -3,9 +3,10 @@ #include "macro_collections.h" // clang-format off -C_MACRO_COLLECTIONS_ALL(CMC, DEQUE, ( d, deque, , , int)) -C_MACRO_COLLECTIONS_ALL(CMC, HASHMAP, ( hm, hashmap, , int, int)) +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)) struct { @@ -22,9 +23,10 @@ int main(void) struct deque *d = d_new(100, (struct deque_fval *)&int_ftab); struct hashmap *hm = hm_new(100, 0.6, (struct hashmap_fkey *)&int_ftab, (struct hashmap_fval *)&int_ftab); - struct hashmultimap *hmm = hmm_new(100, 0.6, + 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); d_to_string(d, stdout); d_print(d, stdout, "\n[ ", ", ", " ]\n"); @@ -32,12 +34,15 @@ int main(void) hm_print(hm, stdout, "\n[ {", "}, {", "} ]\n", " : "); hmm_to_string(hmm, stdout); hmm_print(hmm, stdout, "\n[ {", "}, {", "} ]\n", " : "); + hms_to_string(hms, stdout); + hms_print(hms, stdout, "\n[ {", "}, {", "} ]\n", " : "); for (int i = 0; i < 20; i++) { d_push_back(d, i); hm_insert(hm, i, i); hmm_insert(hmm, i, i); + hms_insert(hms, i); } fprintf(stdout, "\n"); @@ -48,10 +53,13 @@ int main(void) hm_print(hm, stdout, "\n[ {", "}, {", "} ]\n", " : "); hmm_to_string(hmm, stdout); hmm_print(hmm, stdout, "\n[ {", "}, {", "} ]\n", " : "); + hms_to_string(hms, stdout); + hms_print(hms, stdout, "\n[ {", "}, {", "} ]\n", " : "); d_free(d); hm_free(hm); hmm_free(hmm); + hms_free(hms); } // clang-format on