diff --git a/cmc/bitset.h b/cmc/bitset.h index 4cc5e0f..3d72699 100644 --- a/cmc/bitset.h +++ b/cmc/bitset.h @@ -65,28 +65,22 @@ * PFX - functions prefix */ -/* Structs definition */ -#include "cmc/bitset/struct.h" +#if !defined(CMC_STRUCT) && !defined(CMC_HEADER) && !defined(CMC_CODE) +#include "bitset/struct.h" +#include "bitset/header.h" +#include "bitset/code.h" +#endif -/* Function declaration */ -#include "cmc/bitset/header.h" +#ifdef CMC_STRUCT +#include "bitset/struct.h" +#endif /* CMC_STRUCT */ -/* Function implementation */ -#include "cmc/bitset/code.h" +#ifdef CMC_HEADER +#include "bitset/header.h" +#endif /* CMC_HEADER */ -/** - * Extensions - * - * INIT - Initializes the struct on the stack - * ITER - bitset iterator - * STR - Print helper functions - */ -#define CMC_EXT_BITSET_PARTS INIT, ITER, STR -/**/ -#include "cmc/bitset/ext/struct.h" -/**/ -#include "cmc/bitset/ext/header.h" -/**/ -#include "cmc/bitset/ext/code.h" +#ifdef CMC_CODE +#include "bitset/code.h" +#endif /* CMC_CODE */ #include "cor/undef.h" diff --git a/cmc/bitset/ext/code.h b/cmc/bitset/ext/code.h deleted file mode 100644 index ae62677..0000000 --- a/cmc/bitset/ext/code.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright (c) 2019 Leonardo Vencovsky - * - * This file is part of the C Macro Collections Library. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * INIT - * - * The part 'INIT' gives a new way of initializing a collection. The collection - * struct is not heap allocated, only its internal structure (nodes, buffers). - */ -#ifdef CMC_EXT_INIT - -#endif /* CMC_EXT_INIT */ - -/** - * ITER - * - * Bitset bi-directional iterator. - */ -#ifdef CMC_EXT_ITER - -/* Iterator Functions */ -/* Iterator Initialization */ -/* Iterator State */ -/* Iterator Movement */ -/* Iterator Access */ - -#endif /* CMC_EXT_ITER */ - -/** - * STR - * - * Print helper functions. - */ -#ifdef CMC_EXT_STR - -#endif /* CMC_EXT_STR */ diff --git a/cmc/bitset/ext/header.h b/cmc/bitset/ext/header.h deleted file mode 100644 index ae62677..0000000 --- a/cmc/bitset/ext/header.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright (c) 2019 Leonardo Vencovsky - * - * This file is part of the C Macro Collections Library. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * INIT - * - * The part 'INIT' gives a new way of initializing a collection. The collection - * struct is not heap allocated, only its internal structure (nodes, buffers). - */ -#ifdef CMC_EXT_INIT - -#endif /* CMC_EXT_INIT */ - -/** - * ITER - * - * Bitset bi-directional iterator. - */ -#ifdef CMC_EXT_ITER - -/* Iterator Functions */ -/* Iterator Initialization */ -/* Iterator State */ -/* Iterator Movement */ -/* Iterator Access */ - -#endif /* CMC_EXT_ITER */ - -/** - * STR - * - * Print helper functions. - */ -#ifdef CMC_EXT_STR - -#endif /* CMC_EXT_STR */ diff --git a/cmc/bitset/ext/struct.h b/cmc/bitset/ext/struct.h deleted file mode 100644 index 6848bb7..0000000 --- a/cmc/bitset/ext/struct.h +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) 2019 Leonardo Vencovsky - * - * This file is part of the C Macro Collections Library. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * ITER - * - * Bitset bi-directional iterator. - */ -#ifdef CMC_EXT_ITER - -/* BitSet Iterator */ -struct CMC_DEF_ITER(SNAME) -{ - /* Target bitset */ - struct SNAME *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; -}; - -#endif /* CMC_EXT_ITER */ diff --git a/cmc/deque.h b/cmc/deque.h index 1e246ec..51163fe 100644 --- a/cmc/deque.h +++ b/cmc/deque.h @@ -65,28 +65,22 @@ * PFX - functions prefix */ -/* Structs definition */ -#include "cmc/deque/struct.h" +#if !defined(CMC_STRUCT) && !defined(CMC_HEADER) && !defined(CMC_CODE) +#include "deque/struct.h" +#include "deque/header.h" +#include "deque/code.h" +#endif -/* Function declaration */ -#include "cmc/deque/header.h" +#ifdef CMC_STRUCT +#include "deque/struct.h" +#endif /* CMC_STRUCT */ -/* Function implementation */ -#include "cmc/deque/code.h" +#ifdef CMC_HEADER +#include "deque/header.h" +#endif /* CMC_HEADER */ -/** - * Extensions - * - * INIT - Initializes the struct on the stack - * ITER - Deque iterator - * STR - Print helper functions - */ -#define CMC_EXT_DEQUE_PARTS INIT, ITER, STR -/**/ -#include "cmc/deque/ext/struct.h" -/**/ -#include "cmc/deque/ext/header.h" -/**/ -#include "cmc/deque/ext/code.h" +#ifdef CMC_CODE +#include "deque/code.h" +#endif /* CMC_CODE */ #include "cor/undef.h" diff --git a/cmc/deque/code.h b/cmc/deque/code.h index 5b3b45b..a8b103d 100644 --- a/cmc/deque/code.h +++ b/cmc/deque/code.h @@ -122,6 +122,71 @@ void CMC_(PFX, _free)(struct SNAME *_deque_) _deque_->alloc->free(_deque_); } +struct SNAME CMC_(PFX, _init)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + return CMC_(PFX, _init_custom)(capacity, f_val, NULL, NULL); +} + +struct SNAME CMC_(PFX, _init_custom)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val, CMC_ALLOC_TYPE alloc, + CMC_CALLBACK_TYPE callbacks) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + CMC_CALLBACKS_MAYBE_UNUSED(callbacks); + + struct SNAME _deque_ = { 0 }; + + if (capacity < 1) + return _deque_; + + if (!f_val) + return _deque_; + + if (!alloc) + alloc = &cmc_alloc_node_default; + + _deque_.buffer = alloc->calloc(capacity, sizeof(V)); + + if (!_deque_.buffer) + return _deque_; + + _deque_.capacity = capacity; + _deque_.count = 0; + _deque_.front = 0; + _deque_.back = 0; + _deque_.flag = CMC_FLAG_OK; + _deque_.f_val = f_val; + _deque_.alloc = alloc; + CMC_CALLBACKS_ASSIGN(&_deque_, callbacks); + + return _deque_; +} + +void CMC_(PFX, _release)(struct SNAME _deque_) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + if (_deque_.f_val->free) + { + for (size_t i = _deque_.front, j = 0; j < _deque_.count; j++) + { + _deque_.f_val->free(_deque_.buffer[i]); + + i = (i + 1) % _deque_.capacity; + } + } + + _deque_.alloc->free(_deque_.buffer); +} + void CMC_(PFX, _customize)(struct SNAME *_deque_, CMC_ALLOC_TYPE alloc, CMC_CALLBACK_TYPE callbacks) { #ifdef CMC_DEV @@ -459,3 +524,335 @@ bool CMC_(PFX, _equals)(struct SNAME *_deque1_, struct SNAME *_deque2_) return true; } + +/** + * ITER + * + * Deque bi-directional iterator. + */ +#ifdef CMC_EXT_ITER + +struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + struct CMC_DEF_ITER(SNAME) iter; + + iter.target = target; + iter.cursor = target->front; + iter.index = 0; + iter.start = true; + iter.end = CMC_(PFX, _empty)(target); + + return iter; +} + +struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME *target) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + struct CMC_DEF_ITER(SNAME) iter; + + iter.target = target; + + if (!CMC_(PFX, _empty)(target)) + { + if (iter.target->back == 0) + iter.cursor = iter.target->capacity - 1; + else + iter.cursor = iter.target->back - 1; + + iter.index = iter.target->count - 1; + } + else + { + iter.cursor = 0; + iter.index = 0; + } + + iter.start = CMC_(PFX, _empty)(target); + iter.end = true; + + return iter; +} + +bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + return CMC_(PFX, _empty)(iter->target) || iter->start; +} + +bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + return CMC_(PFX, _empty)(iter->target) || iter->end; +} + +bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + if (!CMC_(PFX, _empty)(iter->target)) + { + iter->cursor = iter->target->front; + iter->index = 0; + iter->start = true; + iter->end = false; + + return true; + } + + return false; +} + +bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + if (!CMC_(PFX, _empty)(iter->target)) + { + if (iter->target->back == 0) + iter->cursor = iter->target->capacity - 1; + else + iter->cursor = iter->target->back - 1; + + iter->index = iter->target->count - 1; + + iter->start = false; + iter->end = true; + + return true; + } + + return false; +} + +bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + if (iter->end) + return false; + + if (iter->index + 1 == iter->target->count) + { + iter->end = true; + return false; + } + + iter->start = CMC_(PFX, _empty)(iter->target); + + iter->cursor = (iter->cursor + 1) % (iter->target->capacity); + iter->index++; + + return true; +} + +bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + if (iter->start) + return false; + + if (iter->index == 0) + { + iter->start = true; + return false; + } + + iter->end = CMC_(PFX, _empty)(iter->target); + + iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; + iter->index--; + + return true; +} + +/* Returns true only if the iterator moved */ +bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + 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; + + iter->start = CMC_(PFX, _empty)(iter->target); + + iter->index += steps; + iter->cursor = (iter->cursor + steps) % iter->target->capacity; + + return true; +} + +/* Returns true only if the iterator moved */ +bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + if (iter->start) + return false; + + if (iter->index == 0) + { + iter->start = true; + return false; + } + + if (steps == 0 || iter->index < steps) + return false; + + iter->end = CMC_(PFX, _empty)(iter->target); + + iter->index -= steps; + + /* Prevent underflow */ + if (iter->cursor < steps) + iter->cursor += iter->target->capacity; + + iter->cursor -= steps; + + 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) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + 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) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + if (CMC_(PFX, _empty)(iter->target)) + return (V){ 0 }; + + return iter->target->buffer[iter->cursor]; +} + +V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + if (CMC_(PFX, _empty)(iter->target)) + return NULL; + + return &(iter->target->buffer[iter->cursor]); +} + +size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + return iter->index; +} + +#endif /* CMC_EXT_ITER */ + +/** + * STR + * + * Print helper functions. + */ +#ifdef CMC_EXT_STR + +bool CMC_(PFX, _to_string)(struct SNAME *_deque_, FILE *fptr) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + struct SNAME *d_ = _deque_; + + return 0 <= fprintf(fptr, + "struct %s<%s> " + "at %p { " + "buffer:%p, " + "capacity:%" PRIuMAX ", " + "count:%" PRIuMAX ", " + "front:%" PRIuMAX ", " + "back:%" PRIuMAX ", " + "flag:%d, " + "f_val:%p, " + "alloc:%p, " + "callbacks:%p }", + CMC_TO_STRING(SNAME), CMC_TO_STRING(V), d_, d_->buffer, d_->capacity, d_->count, d_->front, + d_->back, d_->flag, d_->f_val, d_->alloc, CMC_CALLBACKS_GET(d_)); +} + +bool CMC_(PFX, _print)(struct SNAME *_deque_, FILE *fptr, const char *start, const char *separator, const char *end) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + fprintf(fptr, "%s", start); + + for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) + { + if (!_deque_->f_val->str(fptr, _deque_->buffer[i])) + return false; + + i = (i + 1) % _deque_->capacity; + + if (j + 1 < _deque_->count) + fprintf(fptr, "%s", separator); + } + + fprintf(fptr, "%s", end); + + return true; +} + +#endif /* CMC_EXT_STR */ diff --git a/cmc/deque/ext/code.h b/cmc/deque/ext/code.h deleted file mode 100644 index 6946293..0000000 --- a/cmc/deque/ext/code.h +++ /dev/null @@ -1,430 +0,0 @@ -/** - * Copyright (c) 2019 Leonardo Vencovsky - * - * This file is part of the C Macro Collections Library. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * INIT - * - * The part 'INIT' gives a new way of initializing a collection. The collection - * struct is not heap allocated, only its internal structure (nodes, buffers). - */ -#ifdef CMC_EXT_INIT - -struct SNAME CMC_(PFX, _init)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - return CMC_(PFX, _init_custom)(capacity, f_val, NULL, NULL); -} - -struct SNAME CMC_(PFX, _init_custom)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val, CMC_ALLOC_TYPE alloc, - CMC_CALLBACK_TYPE callbacks) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - CMC_CALLBACKS_MAYBE_UNUSED(callbacks); - - struct SNAME _deque_ = { 0 }; - - if (capacity < 1) - return _deque_; - - if (!f_val) - return _deque_; - - if (!alloc) - alloc = &cmc_alloc_node_default; - - _deque_.buffer = alloc->calloc(capacity, sizeof(V)); - - if (!_deque_.buffer) - return _deque_; - - _deque_.capacity = capacity; - _deque_.count = 0; - _deque_.front = 0; - _deque_.back = 0; - _deque_.flag = CMC_FLAG_OK; - _deque_.f_val = f_val; - _deque_.alloc = alloc; - CMC_CALLBACKS_ASSIGN(&_deque_, callbacks); - - return _deque_; -} - -void CMC_(PFX, _release)(struct SNAME _deque_) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - if (_deque_.f_val->free) - { - for (size_t i = _deque_.front, j = 0; j < _deque_.count; j++) - { - _deque_.f_val->free(_deque_.buffer[i]); - - i = (i + 1) % _deque_.capacity; - } - } - - _deque_.alloc->free(_deque_.buffer); -} - -#endif /* CMC_EXT_INIT */ - -/** - * ITER - * - * Deque bi-directional iterator. - */ -#ifdef CMC_EXT_ITER - -struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - struct CMC_DEF_ITER(SNAME) iter; - - iter.target = target; - iter.cursor = target->front; - iter.index = 0; - iter.start = true; - iter.end = CMC_(PFX, _empty)(target); - - return iter; -} - -struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME *target) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - struct CMC_DEF_ITER(SNAME) iter; - - iter.target = target; - - if (!CMC_(PFX, _empty)(target)) - { - if (iter.target->back == 0) - iter.cursor = iter.target->capacity - 1; - else - iter.cursor = iter.target->back - 1; - - iter.index = iter.target->count - 1; - } - else - { - iter.cursor = 0; - iter.index = 0; - } - - iter.start = CMC_(PFX, _empty)(target); - iter.end = true; - - return iter; -} - -bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - return CMC_(PFX, _empty)(iter->target) || iter->start; -} - -bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - return CMC_(PFX, _empty)(iter->target) || iter->end; -} - -bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - if (!CMC_(PFX, _empty)(iter->target)) - { - iter->cursor = iter->target->front; - iter->index = 0; - iter->start = true; - iter->end = false; - - return true; - } - - return false; -} - -bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - if (!CMC_(PFX, _empty)(iter->target)) - { - if (iter->target->back == 0) - iter->cursor = iter->target->capacity - 1; - else - iter->cursor = iter->target->back - 1; - - iter->index = iter->target->count - 1; - - iter->start = false; - iter->end = true; - - return true; - } - - return false; -} - -bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - if (iter->end) - return false; - - if (iter->index + 1 == iter->target->count) - { - iter->end = true; - return false; - } - - iter->start = CMC_(PFX, _empty)(iter->target); - - iter->cursor = (iter->cursor + 1) % (iter->target->capacity); - iter->index++; - - return true; -} - -bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - if (iter->start) - return false; - - if (iter->index == 0) - { - iter->start = true; - return false; - } - - iter->end = CMC_(PFX, _empty)(iter->target); - - iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; - iter->index--; - - return true; -} - -/* Returns true only if the iterator moved */ -bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - 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; - - iter->start = CMC_(PFX, _empty)(iter->target); - - iter->index += steps; - iter->cursor = (iter->cursor + steps) % iter->target->capacity; - - return true; -} - -/* Returns true only if the iterator moved */ -bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - if (iter->start) - return false; - - if (iter->index == 0) - { - iter->start = true; - return false; - } - - if (steps == 0 || iter->index < steps) - return false; - - iter->end = CMC_(PFX, _empty)(iter->target); - - iter->index -= steps; - - /* Prevent underflow */ - if (iter->cursor < steps) - iter->cursor += iter->target->capacity; - - iter->cursor -= steps; - - 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) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - 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) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - if (CMC_(PFX, _empty)(iter->target)) - return (V){ 0 }; - - return iter->target->buffer[iter->cursor]; -} - -V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - if (CMC_(PFX, _empty)(iter->target)) - return NULL; - - return &(iter->target->buffer[iter->cursor]); -} - -size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - return iter->index; -} - -#endif /* CMC_EXT_ITER */ - -/** - * STR - * - * Print helper functions. - */ -#ifdef CMC_EXT_STR - -bool CMC_(PFX, _to_string)(struct SNAME *_deque_, FILE *fptr) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - struct SNAME *d_ = _deque_; - - return 0 <= fprintf(fptr, - "struct %s<%s> " - "at %p { " - "buffer:%p, " - "capacity:%" PRIuMAX ", " - "count:%" PRIuMAX ", " - "front:%" PRIuMAX ", " - "back:%" PRIuMAX ", " - "flag:%d, " - "f_val:%p, " - "alloc:%p, " - "callbacks:%p }", - CMC_TO_STRING(SNAME), CMC_TO_STRING(V), d_, d_->buffer, d_->capacity, d_->count, d_->front, - d_->back, d_->flag, d_->f_val, d_->alloc, CMC_CALLBACKS_GET(d_)); -} - -bool CMC_(PFX, _print)(struct SNAME *_deque_, FILE *fptr, const char *start, const char *separator, const char *end) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - fprintf(fptr, "%s", start); - - for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) - { - if (!_deque_->f_val->str(fptr, _deque_->buffer[i])) - return false; - - i = (i + 1) % _deque_->capacity; - - if (j + 1 < _deque_->count) - fprintf(fptr, "%s", separator); - } - - fprintf(fptr, "%s", end); - - return true; -} - -#endif /* CMC_EXT_STR */ diff --git a/cmc/deque/ext/header.h b/cmc/deque/ext/header.h deleted file mode 100644 index 23696d6..0000000 --- a/cmc/deque/ext/header.h +++ /dev/null @@ -1,80 +0,0 @@ -/** - * Copyright (c) 2019 Leonardo Vencovsky - * - * This file is part of the C Macro Collections Library. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * INIT - * - * The part 'INIT' gives a new way of initializing a collection. The collection - * struct is not heap allocated, only its internal structure (nodes, buffers). - */ -#ifdef CMC_EXT_INIT - -struct SNAME CMC_(PFX, _init)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val); -struct SNAME CMC_(PFX, _init_custom)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val, CMC_ALLOC_TYPE alloc, - CMC_CALLBACK_TYPE callbacks); -void CMC_(PFX, _release)(struct SNAME _deque_); - -#endif /* CMC_EXT_INIT */ - -/** - * ITER - * - * Deque bi-directional iterator. - */ -#ifdef CMC_EXT_ITER - -/* 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); -V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter); -size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter); - -#endif /* CMC_EXT_ITER */ - -/** - * STR - * - * Print helper functions. - */ -#ifdef CMC_EXT_STR - -/* Debug prints the struct to fptr */ -bool CMC_(PFX, _to_string)(struct SNAME *_deque_, FILE *fptr); -/* Prints each item in the deque as an array */ -bool CMC_(PFX, _print)(struct SNAME *_deque_, FILE *fptr, const char *start, const char *separator, const char *end); - -#endif /* CMC_EXT_STR */ diff --git a/cmc/deque/ext/struct.h b/cmc/deque/ext/struct.h deleted file mode 100644 index f65d75a..0000000 --- a/cmc/deque/ext/struct.h +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright (c) 2019 Leonardo Vencovsky - * - * This file is part of the C Macro Collections Library. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * ITER - * - * Deque bi-directional iterator. - */ -#ifdef CMC_EXT_ITER - -/* Deque Iterator */ -struct CMC_DEF_ITER(SNAME) -{ - /* Target deque */ - struct SNAME *target; - /* Cursor's position (index) */ - size_t cursor; - /* Keeps track of relative index to the iteration of elements */ - size_t index; - /* If the iterator has reached the start of the iteration */ - bool start; - /* If the iterator has reached the end of the iteration */ - bool end; -}; - -#endif /* CMC_EXT_ITER */ diff --git a/cmc/deque/header.h b/cmc/deque/header.h index e313665..69aa517 100644 --- a/cmc/deque/header.h +++ b/cmc/deque/header.h @@ -45,6 +45,11 @@ struct SNAME *CMC_(PFX, _new_custom)(size_t capacity, struct CMC_DEF_FVAL(SNAME) CMC_CALLBACK_TYPE callbacks); void CMC_(PFX, _clear)(struct SNAME *_deque_); void CMC_(PFX, _free)(struct SNAME *_deque_); +/* Collection Allocation and Deallocation */ +struct SNAME CMC_(PFX, _init)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val); +struct SNAME CMC_(PFX, _init_custom)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val, CMC_ALLOC_TYPE alloc, + CMC_CALLBACK_TYPE callbacks); +void CMC_(PFX, _release)(struct SNAME _deque_); /* Customization of Allocation and Callbacks */ void CMC_(PFX, _customize)(struct SNAME *_deque_, CMC_ALLOC_TYPE alloc, CMC_CALLBACK_TYPE callbacks); /* Collection Input and Output */ @@ -66,3 +71,45 @@ int CMC_(PFX, _flag)(struct SNAME *_deque_); bool CMC_(PFX, _resize)(struct SNAME *_deque_, size_t capacity); struct SNAME *CMC_(PFX, _copy_of)(struct SNAME *_deque_); bool CMC_(PFX, _equals)(struct SNAME *_deque1_, struct SNAME *_deque2_); + +/** + * ITER + * + * Deque bi-directional iterator. + */ +#ifdef CMC_EXT_ITER + +/* 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); +V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter); +size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter); + +#endif /* CMC_EXT_ITER */ + +/** + * STR + * + * Print helper functions. + */ +#ifdef CMC_EXT_STR + +/* Debug prints the struct to fptr */ +bool CMC_(PFX, _to_string)(struct SNAME *_deque_, FILE *fptr); +/* Prints each item in the deque as an array */ +bool CMC_(PFX, _print)(struct SNAME *_deque_, FILE *fptr, const char *start, const char *separator, const char *end); + +#endif /* CMC_EXT_STR */ diff --git a/cmc/deque/struct.h b/cmc/deque/struct.h index cb85e11..2bd2458 100644 --- a/cmc/deque/struct.h +++ b/cmc/deque/struct.h @@ -43,3 +43,27 @@ struct SNAME /* Custom callback functions */ CMC_CALLBACKS_DECL; }; + +/** + * ITER + * + * Deque bi-directional iterator. + */ +#ifdef CMC_EXT_ITER + +/* Deque Iterator */ +struct CMC_DEF_ITER(SNAME) +{ + /* Target deque */ + struct SNAME *target; + /* Cursor's position (index) */ + size_t cursor; + /* Keeps track of relative index to the iteration of elements */ + size_t index; + /* If the iterator has reached the start of the iteration */ + bool start; + /* If the iterator has reached the end of the iteration */ + bool end; +}; + +#endif /* CMC_EXT_ITER */ diff --git a/cmc/hashbidimap.h b/cmc/hashbidimap.h index 7ea9f6e..e61dd05 100644 --- a/cmc/hashbidimap.h +++ b/cmc/hashbidimap.h @@ -62,28 +62,22 @@ * PFX - functions prefix */ -/* Structs definition */ -#include "cmc/hashbidimap/struct.h" +#if !defined(CMC_STRUCT) && !defined(CMC_HEADER) && !defined(CMC_CODE) +#include "hashbidimap/struct.h" +#include "hashbidimap/header.h" +#include "hashbidimap/code.h" +#endif -/* Function declaration */ -#include "cmc/hashbidimap/header.h" +#ifdef CMC_STRUCT +#include "hashbidimap/struct.h" +#endif /* CMC_STRUCT */ -/* Function implementation */ -#include "cmc/hashbidimap/code.h" +#ifdef CMC_HEADER +#include "hashbidimap/header.h" +#endif /* CMC_HEADER */ -/** - * Extensions - * - * INIT - Initializes the struct on the stack - * ITER - Hashbidimap iterator - * STR - Print helper functions - */ -#define CMC_EXT_HASHBIDIMAP_PARTS INIT, ITER, STR -/**/ -#include "cmc/hashbidimap/ext/struct.h" -/**/ -#include "cmc/hashbidimap/ext/header.h" -/**/ -#include "cmc/hashbidimap/ext/code.h" +#ifdef CMC_CODE +#include "hashbidimap/code.h" +#endif /* CMC_CODE */ #include "cor/undef.h" diff --git a/cmc/hashbidimap/code.h b/cmc/hashbidimap/code.h index b1e2e2e..a90bf8c 100644 --- a/cmc/hashbidimap/code.h +++ b/cmc/hashbidimap/code.h @@ -134,6 +134,72 @@ void CMC_(PFX, _free)(struct SNAME *_map_) _map_->alloc->free(_map_); } +struct SNAME CMC_(PFX, _init)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, + struct CMC_DEF_FVAL(SNAME) * f_val) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + return CMC_(PFX, _init_custom)(capacity, load, f_key, f_val, NULL, NULL); +} + +struct SNAME CMC_(PFX, _init_custom)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, + struct CMC_DEF_FVAL(SNAME) * f_val, CMC_ALLOC_TYPE alloc, + CMC_CALLBACK_TYPE callbacks) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + CMC_CALLBACKS_MAYBE_UNUSED(callbacks); + + struct SNAME _map_ = { 0 }; + + if (capacity == 0 || load <= 0 || load >= 1) + return _map_; + + /* Prevent integer overflow */ + if (capacity >= (double)UINTMAX_MAX * load) + return _map_; + + if (!f_key || !f_val) + return _map_; + + size_t real_capacity = CMC_(PFX, _impl_calculate_size)(capacity / load); + + if (!alloc) + alloc = &cmc_alloc_node_default; + + _map_.buffer = alloc->calloc(real_capacity, sizeof(struct CMC_DEF_ENTRY(SNAME) *[2])); + + if (!_map_.buffer) + return _map_; + + _map_.count = 0; + _map_.capacity = real_capacity; + _map_.load = load; + _map_.flag = CMC_FLAG_OK; + _map_.f_key = f_key; + _map_.f_val = f_val; + _map_.flag = CMC_FLAG_OK; + _map_.alloc = alloc; + CMC_CALLBACKS_ASSIGN(&_map_, callbacks); + + return _map_; +} + +void CMC_(PFX, _release)(struct SNAME _map_) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + CMC_(PFX, _clear)(&_map_); + + _map_.alloc->free(_map_.buffer); +} + void CMC_(PFX, _customize)(struct SNAME *_map_, CMC_ALLOC_TYPE alloc, CMC_CALLBACK_TYPE callbacks) { #ifdef CMC_DEV @@ -959,3 +1025,377 @@ static size_t CMC_(PFX, _impl_calculate_size)(size_t required) return cmc_hashtable_primes[i]; } + +/** + * ITER + * + * Hashbidimap bi-directional iterator. + */ +#ifdef CMC_EXT_ITER + +struct CMC_DEF_ITER(SNAME) * CMC_(PFX, _iter_new)(struct SNAME *target) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + struct CMC_DEF_ITER(SNAME) *iter = target->alloc->malloc(sizeof(struct CMC_DEF_ITER(SNAME))); + + if (!iter) + return NULL; + + CMC_(PFX, _iter_init)(iter, target); + + return iter; +} + +void CMC_(PFX, _iter_free)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + iter->target->alloc->free(iter); +} + +void CMC_(PFX, _iter_init)(struct CMC_DEF_ITER(SNAME) * iter, struct SNAME *target) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + memset(iter, 0, sizeof(struct CMC_DEF_ITER(SNAME))); + + iter->target = target; + iter->start = true; + iter->end = CMC_(PFX, _empty)(target); + + if (!CMC_(PFX, _empty)(target)) + { + for (size_t i = 0; i < target->capacity; i++) + { + struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i][0]; + + if (entry && entry != CMC_ENTRY_DELETED) + { + iter->first = i; + break; + } + } + + iter->cursor = iter->first; + + for (size_t i = target->capacity; i > 0; i--) + { + struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i - 1][0]; + + if (entry && entry != CMC_ENTRY_DELETED) + { + iter->last = i - 1; + break; + } + } + } +} + +bool CMC_(PFX, _iter_start)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + return CMC_(PFX, _empty)(iter->target) || iter->start; +} + +bool CMC_(PFX, _iter_end)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + return CMC_(PFX, _empty)(iter->target) || iter->end; +} + +void CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + if (!CMC_(PFX, _empty)(iter->target)) + { + iter->cursor = iter->first; + iter->index = 0; + iter->start = true; + iter->end = false; + } +} + +void CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + if (!CMC_(PFX, _empty)(iter->target)) + { + iter->cursor = iter->last; + iter->index = iter->target->count - 1; + iter->start = false; + iter->end = true; + } +} + +bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + 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][0]; + + iter->index++; + + while (1) + { + iter->cursor++; + scan = iter->target->buffer[iter->cursor][0]; + + if (scan != NULL && scan != CMC_ENTRY_DELETED) + break; + } + + return true; +} + +bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + 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][0]; + + iter->index--; + + while (1) + { + iter->cursor--; + scan = iter->target->buffer[iter->cursor][0]; + + if (scan != NULL && scan != CMC_ENTRY_DELETED) + break; + } + + return true; +} + +/* Returns true only if the iterator moved */ +bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + 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) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + 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) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + 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; +} + +K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + if (CMC_(PFX, _empty)(iter->target)) + { + iter->target->flag = CMC_FLAG_EMPTY; + return (K){ 0 }; + } + + return iter->target->buffer[iter->cursor][0]->key; +} + +V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + if (CMC_(PFX, _empty)(iter->target)) + { + iter->target->flag = CMC_FLAG_EMPTY; + return (V){ 0 }; + } + + return iter->target->buffer[iter->cursor][0]->value; +} + +size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + return iter->index; +} + +#endif /* CMC_EXT_ITER */ + +/** + * STR + * + * Print helper functions. + */ +#ifdef CMC_EXT_STR + +bool CMC_(PFX, _to_string)(struct SNAME *_map_, FILE *fptr) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + struct SNAME *m_ = _map_; + + return 0 <= fprintf(fptr, + "struct %s<%s, %s> " + "at %p { " + "buffer:%p, " + "capacity:%" PRIuMAX ", " + "count:%" PRIuMAX ", " + "load:%lf, " + "flag:%d, " + "f_key:%p, " + "f_val:%p, " + "alloc:%p, " + "callbacks:%p }", + CMC_TO_STRING(SNAME), CMC_TO_STRING(K), CMC_TO_STRING(V), m_, m_->buffer, m_->capacity, + m_->count, m_->load, m_->flag, m_->f_key, m_->f_val, m_->alloc, CMC_CALLBACKS_GET(m_)); +} + +bool CMC_(PFX, _print)(struct SNAME *_map_, FILE *fptr, const char *start, const char *separator, const char *end, + const char *key_val_sep) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + fprintf(fptr, "%s", start); + + size_t last = 0; + for (size_t i = _map_->capacity; i > 0; i--) + { + struct CMC_DEF_ENTRY(SNAME) *entry = _map_->buffer[i - 1][0]; + + if (entry && entry != CMC_ENTRY_DELETED) + { + last = i - 1; + break; + } + } + + for (size_t i = 0; i < _map_->capacity; i++) + { + struct CMC_DEF_ENTRY(SNAME) *entry = _map_->buffer[i][0]; + + if (entry && entry != CMC_ENTRY_DELETED) + { + if (!_map_->f_key->str(fptr, entry->key)) + return false; + + fprintf(fptr, "%s", key_val_sep); + + if (!_map_->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_STR */ diff --git a/cmc/hashbidimap/ext/code.h b/cmc/hashbidimap/ext/code.h deleted file mode 100644 index 678fa07..0000000 --- a/cmc/hashbidimap/ext/code.h +++ /dev/null @@ -1,473 +0,0 @@ -/** - * Copyright (c) 2019 Leonardo Vencovsky - * - * This file is part of the C Macro Collections Library. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * INIT - * - * The part 'INIT' gives a new way of initializing a collection. The collection - * struct is not heap allocated, only its internal structure (nodes, buffers). - */ -#ifdef CMC_EXT_INIT - -struct SNAME CMC_(PFX, _init)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, - struct CMC_DEF_FVAL(SNAME) * f_val) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - return CMC_(PFX, _init_custom)(capacity, load, f_key, f_val, NULL, NULL); -} - -struct SNAME CMC_(PFX, _init_custom)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, - struct CMC_DEF_FVAL(SNAME) * f_val, CMC_ALLOC_TYPE alloc, - CMC_CALLBACK_TYPE callbacks) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - CMC_CALLBACKS_MAYBE_UNUSED(callbacks); - - struct SNAME _map_ = { 0 }; - - if (capacity == 0 || load <= 0 || load >= 1) - return _map_; - - /* Prevent integer overflow */ - if (capacity >= (double)UINTMAX_MAX * load) - return _map_; - - if (!f_key || !f_val) - return _map_; - - size_t real_capacity = CMC_(PFX, _impl_calculate_size)(capacity / load); - - if (!alloc) - alloc = &cmc_alloc_node_default; - - _map_.buffer = alloc->calloc(real_capacity, sizeof(struct CMC_DEF_ENTRY(SNAME) *[2])); - - if (!_map_.buffer) - return _map_; - - _map_.count = 0; - _map_.capacity = real_capacity; - _map_.load = load; - _map_.flag = CMC_FLAG_OK; - _map_.f_key = f_key; - _map_.f_val = f_val; - _map_.flag = CMC_FLAG_OK; - _map_.alloc = alloc; - CMC_CALLBACKS_ASSIGN(&_map_, callbacks); - - return _map_; -} - -void CMC_(PFX, _release)(struct SNAME _map_) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - CMC_(PFX, _clear)(&_map_); - - _map_.alloc->free(_map_.buffer); -} - -#endif /* CMC_EXT_INIT */ - -/** - * ITER - * - * Hashbidimap bi-directional iterator. - */ -#ifdef CMC_EXT_ITER - -struct CMC_DEF_ITER(SNAME) * CMC_(PFX, _iter_new)(struct SNAME *target) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - struct CMC_DEF_ITER(SNAME) *iter = target->alloc->malloc(sizeof(struct CMC_DEF_ITER(SNAME))); - - if (!iter) - return NULL; - - CMC_(PFX, _iter_init)(iter, target); - - return iter; -} - -void CMC_(PFX, _iter_free)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - iter->target->alloc->free(iter); -} - -void CMC_(PFX, _iter_init)(struct CMC_DEF_ITER(SNAME) * iter, struct SNAME *target) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - memset(iter, 0, sizeof(struct CMC_DEF_ITER(SNAME))); - - iter->target = target; - iter->start = true; - iter->end = CMC_(PFX, _empty)(target); - - if (!CMC_(PFX, _empty)(target)) - { - for (size_t i = 0; i < target->capacity; i++) - { - struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i][0]; - - if (entry && entry != CMC_ENTRY_DELETED) - { - iter->first = i; - break; - } - } - - iter->cursor = iter->first; - - for (size_t i = target->capacity; i > 0; i--) - { - struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i - 1][0]; - - if (entry && entry != CMC_ENTRY_DELETED) - { - iter->last = i - 1; - break; - } - } - } -} - -bool CMC_(PFX, _iter_start)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - return CMC_(PFX, _empty)(iter->target) || iter->start; -} - -bool CMC_(PFX, _iter_end)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - return CMC_(PFX, _empty)(iter->target) || iter->end; -} - -void CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - if (!CMC_(PFX, _empty)(iter->target)) - { - iter->cursor = iter->first; - iter->index = 0; - iter->start = true; - iter->end = false; - } -} - -void CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - if (!CMC_(PFX, _empty)(iter->target)) - { - iter->cursor = iter->last; - iter->index = iter->target->count - 1; - iter->start = false; - iter->end = true; - } -} - -bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - 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][0]; - - iter->index++; - - while (1) - { - iter->cursor++; - scan = iter->target->buffer[iter->cursor][0]; - - if (scan != NULL && scan != CMC_ENTRY_DELETED) - break; - } - - return true; -} - -bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - 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][0]; - - iter->index--; - - while (1) - { - iter->cursor--; - scan = iter->target->buffer[iter->cursor][0]; - - if (scan != NULL && scan != CMC_ENTRY_DELETED) - break; - } - - return true; -} - -/* Returns true only if the iterator moved */ -bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - 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) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - 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) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - 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; -} - -K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - if (CMC_(PFX, _empty)(iter->target)) - { - iter->target->flag = CMC_FLAG_EMPTY; - return (K){ 0 }; - } - - return iter->target->buffer[iter->cursor][0]->key; -} - -V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - if (CMC_(PFX, _empty)(iter->target)) - { - iter->target->flag = CMC_FLAG_EMPTY; - return (V){ 0 }; - } - - return iter->target->buffer[iter->cursor][0]->value; -} - -size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - return iter->index; -} - -#endif /* CMC_EXT_ITER */ - -/** - * STR - * - * Print helper functions. - */ -#ifdef CMC_EXT_STR - -bool CMC_(PFX, _to_string)(struct SNAME *_map_, FILE *fptr) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - struct SNAME *m_ = _map_; - - return 0 <= fprintf(fptr, - "struct %s<%s, %s> " - "at %p { " - "buffer:%p, " - "capacity:%" PRIuMAX ", " - "count:%" PRIuMAX ", " - "load:%lf, " - "flag:%d, " - "f_key:%p, " - "f_val:%p, " - "alloc:%p, " - "callbacks:%p }", - CMC_TO_STRING(SNAME), CMC_TO_STRING(K), CMC_TO_STRING(V), m_, m_->buffer, m_->capacity, - m_->count, m_->load, m_->flag, m_->f_key, m_->f_val, m_->alloc, CMC_CALLBACKS_GET(m_)); -} - -bool CMC_(PFX, _print)(struct SNAME *_map_, FILE *fptr, const char *start, const char *separator, const char *end, - const char *key_val_sep) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - fprintf(fptr, "%s", start); - - size_t last = 0; - for (size_t i = _map_->capacity; i > 0; i--) - { - struct CMC_DEF_ENTRY(SNAME) *entry = _map_->buffer[i - 1][0]; - - if (entry && entry != CMC_ENTRY_DELETED) - { - last = i - 1; - break; - } - } - - for (size_t i = 0; i < _map_->capacity; i++) - { - struct CMC_DEF_ENTRY(SNAME) *entry = _map_->buffer[i][0]; - - if (entry && entry != CMC_ENTRY_DELETED) - { - if (!_map_->f_key->str(fptr, entry->key)) - return false; - - fprintf(fptr, "%s", key_val_sep); - - if (!_map_->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_STR */ diff --git a/cmc/hashbidimap/ext/header.h b/cmc/hashbidimap/ext/header.h deleted file mode 100644 index 11fae3d..0000000 --- a/cmc/hashbidimap/ext/header.h +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Copyright (c) 2019 Leonardo Vencovsky - * - * This file is part of the C Macro Collections Library. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * INIT - * - * The part 'INIT' gives a new way of initializing a collection. The collection - * struct is not heap allocated, only its internal structure (nodes, buffers). - */ -#ifdef CMC_EXT_INIT - -struct SNAME CMC_(PFX, _init)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, - struct CMC_DEF_FVAL(SNAME) * f_val); -struct SNAME CMC_(PFX, _init_custom)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, - struct CMC_DEF_FVAL(SNAME) * f_val, CMC_ALLOC_TYPE alloc, - CMC_CALLBACK_TYPE callbacks); -void CMC_(PFX, _release)(struct SNAME _map_); - -#endif /* CMC_EXT_INIT */ - -/** - * ITER - * - * Hashbidimap bi-directional iterator. - */ -#ifdef CMC_EXT_ITER - -/* Iterator Functions */ -/* Iterator Allocation and Deallocation */ -struct CMC_DEF_ITER(SNAME) * CMC_(PFX, _iter_new)(struct SNAME *target); -void CMC_(PFX, _iter_free)(struct CMC_DEF_ITER(SNAME) * iter); -/* Iterator Initialization */ -void CMC_(PFX, _iter_init)(struct CMC_DEF_ITER(SNAME) * iter, struct SNAME *target); -/* Iterator State */ -bool CMC_(PFX, _iter_start)(struct CMC_DEF_ITER(SNAME) * iter); -bool CMC_(PFX, _iter_end)(struct CMC_DEF_ITER(SNAME) * iter); -/* Iterator Movement */ -void CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); -void 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 */ -K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter); -V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); -size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter); - -#endif /* CMC_EXT_ITER */ - -/** - * STR - * - * Print helper functions. - */ -#ifdef CMC_EXT_STR - -/* Debug prints the struct to fptr */ -bool CMC_(PFX, _to_string)(struct SNAME *_map_, FILE *fptr); -/* Prints each item in the hashbidimap as an array */ -bool CMC_(PFX, _print)(struct SNAME *_map_, FILE *fptr, const char *start, const char *separator, const char *end, - const char *key_val_sep); - -#endif /* CMC_EXT_STR */ diff --git a/cmc/hashbidimap/ext/struct.h b/cmc/hashbidimap/ext/struct.h deleted file mode 100644 index b887ea8..0000000 --- a/cmc/hashbidimap/ext/struct.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) 2019 Leonardo Vencovsky - * - * This file is part of the C Macro Collections Library. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * ITER - * - * Hashbidimap bi-directional iterator. - */ -#ifdef CMC_EXT_ITER - -/* HashBidiMap Iterator */ -struct CMC_DEF_ITER(SNAME) -{ - /* Target hashbidimap */ - 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; -}; - -#endif /* CMC_EXT_ITER */ diff --git a/cmc/hashbidimap/header.h b/cmc/hashbidimap/header.h index 1a3d235..f30b95a 100644 --- a/cmc/hashbidimap/header.h +++ b/cmc/hashbidimap/header.h @@ -64,6 +64,13 @@ struct SNAME *CMC_(PFX, _new_custom)(size_t capacity, double load, struct CMC_DE CMC_CALLBACK_TYPE callbacks); void CMC_(PFX, _clear)(struct SNAME *_map_); void CMC_(PFX, _free)(struct SNAME *_map_); +/* Collection Allocation and Deallocation */ +struct SNAME CMC_(PFX, _init)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, + struct CMC_DEF_FVAL(SNAME) * f_val); +struct SNAME CMC_(PFX, _init_custom)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, + struct CMC_DEF_FVAL(SNAME) * f_val, CMC_ALLOC_TYPE alloc, + CMC_CALLBACK_TYPE callbacks); +void CMC_(PFX, _release)(struct SNAME _map_); /* Customization of Allocation and Callbacks */ void CMC_(PFX, _customize)(struct SNAME *_map_, CMC_ALLOC_TYPE alloc, CMC_CALLBACK_TYPE callbacks); /* Collection Input and Output */ @@ -88,3 +95,49 @@ int CMC_(PFX, _flag)(struct SNAME *_map_); bool CMC_(PFX, _resize)(struct SNAME *_map_, size_t capacity); struct SNAME *CMC_(PFX, _copy_of)(struct SNAME *_map_); bool CMC_(PFX, _equals)(struct SNAME *_map1_, struct SNAME *_map2_); + +/** + * ITER + * + * Hashbidimap bi-directional iterator. + */ +#ifdef CMC_EXT_ITER + +/* Iterator Functions */ +/* Iterator Allocation and Deallocation */ +struct CMC_DEF_ITER(SNAME) * CMC_(PFX, _iter_new)(struct SNAME *target); +void CMC_(PFX, _iter_free)(struct CMC_DEF_ITER(SNAME) * iter); +/* Iterator Initialization */ +void CMC_(PFX, _iter_init)(struct CMC_DEF_ITER(SNAME) * iter, struct SNAME *target); +/* Iterator State */ +bool CMC_(PFX, _iter_start)(struct CMC_DEF_ITER(SNAME) * iter); +bool CMC_(PFX, _iter_end)(struct CMC_DEF_ITER(SNAME) * iter); +/* Iterator Movement */ +void CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); +void 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 */ +K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter); +V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); +size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter); + +#endif /* CMC_EXT_ITER */ + +/** + * STR + * + * Print helper functions. + */ +#ifdef CMC_EXT_STR + +/* Debug prints the struct to fptr */ +bool CMC_(PFX, _to_string)(struct SNAME *_map_, FILE *fptr); +/* Prints each item in the hashbidimap as an array */ +bool CMC_(PFX, _print)(struct SNAME *_map_, FILE *fptr, const char *start, const char *separator, const char *end, + const char *key_val_sep); + +#endif /* CMC_EXT_STR */ diff --git a/cmc/hashbidimap/struct.h b/cmc/hashbidimap/struct.h index 910f5f1..3e818c8 100644 --- a/cmc/hashbidimap/struct.h +++ b/cmc/hashbidimap/struct.h @@ -67,3 +67,31 @@ struct CMC_DEF_ENTRY(SNAME) /* ref[1] is relative to V -> K */ struct CMC_DEF_ENTRY(SNAME) * *ref[2]; }; + +/** + * ITER + * + * Hashbidimap bi-directional iterator. + */ +#ifdef CMC_EXT_ITER + +/* HashBidiMap Iterator */ +struct CMC_DEF_ITER(SNAME) +{ + /* Target hashbidimap */ + 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; +}; + +#endif /* CMC_EXT_ITER */ diff --git a/cmc/hashmap.h b/cmc/hashmap.h index 25919cc..1d5f93e 100644 --- a/cmc/hashmap.h +++ b/cmc/hashmap.h @@ -55,28 +55,22 @@ * PFX - functions prefix */ -/* Structs definition */ -#include "cmc/hashmap/struct.h" +#if !defined(CMC_STRUCT) && !defined(CMC_HEADER) && !defined(CMC_CODE) +#include "hashmap/struct.h" +#include "hashmap/header.h" +#include "hashmap/code.h" +#endif -/* Function declaration */ -#include "cmc/hashmap/header.h" +#ifdef CMC_STRUCT +#include "hashmap/struct.h" +#endif /* CMC_STRUCT */ -/* Function implementation */ -#include "cmc/hashmap/code.h" +#ifdef CMC_HEADER +#include "hashmap/header.h" +#endif /* CMC_HEADER */ -/** - * Extensions - * - * INIT - Initializes the struct on the stack - * ITER - hashmap iterator - * STR - Print helper functions - */ -#define CMC_EXT_HASHMAP_PARTS INIT, ITER, STR -/**/ -#include "cmc/hashmap/ext/struct.h" -/**/ -#include "cmc/hashmap/ext/header.h" -/**/ -#include "cmc/hashmap/ext/code.h" +#ifdef CMC_CODE +#include "hashmap/code.h" +#endif /* CMC_CODE */ #include "cor/undef.h" diff --git a/cmc/hashmap/code.h b/cmc/hashmap/code.h index f595415..407ecc7 100644 --- a/cmc/hashmap/code.h +++ b/cmc/hashmap/code.h @@ -136,6 +136,81 @@ void CMC_(PFX, _free)(struct SNAME *_map_) _map_->alloc->free(_map_); } +struct SNAME CMC_(PFX, _init)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, + struct CMC_DEF_FVAL(SNAME) * f_val) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + return CMC_(PFX, _init_custom)(capacity, load, f_key, f_val, NULL, NULL); +} + +struct SNAME CMC_(PFX, _init_custom)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, + struct CMC_DEF_FVAL(SNAME) * f_val, CMC_ALLOC_TYPE alloc, + CMC_CALLBACK_TYPE callbacks) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + CMC_CALLBACKS_MAYBE_UNUSED(callbacks); + + struct SNAME _map_ = { 0 }; + + if (capacity == 0 || load <= 0 || load >= 1) + return _map_; + + /* Prevent integer overflow */ + if (capacity >= (double)UINTMAX_MAX * load) + return _map_; + + if (!f_key || !f_val) + return _map_; + + size_t real_capacity = CMC_(PFX, _impl_calculate_size)(capacity / load); + + if (!alloc) + alloc = &cmc_alloc_node_default; + + _map_.buffer = alloc->calloc(real_capacity, sizeof(struct CMC_DEF_ENTRY(SNAME))); + + if (!_map_.buffer) + return _map_; + + _map_.count = 0; + _map_.capacity = real_capacity; + _map_.load = load; + _map_.flag = CMC_FLAG_OK; + _map_.f_key = f_key; + _map_.f_val = f_val; + _map_.alloc = alloc; + CMC_CALLBACKS_ASSIGN(&_map_, callbacks); + + return _map_; +} + +void CMC_(PFX, _release)(struct SNAME _map_) +{ + if (_map_.f_key->free || _map_.f_val->free) + { + for (size_t i = 0; i < _map_.capacity; i++) + { + struct CMC_DEF_ENTRY(SNAME) *entry = &(_map_.buffer[i]); + + if (entry->state == CMC_ES_FILLED) + { + if (_map_.f_key->free) + _map_.f_key->free(entry->key); + if (_map_.f_val->free) + _map_.f_val->free(entry->value); + } + } + } + + _map_.alloc->free(_map_.buffer); +} + void CMC_(PFX, _customize)(struct SNAME *_map_, CMC_ALLOC_TYPE alloc, CMC_CALLBACK_TYPE callbacks) { #ifdef CMC_DEV @@ -726,3 +801,409 @@ static size_t CMC_(PFX, _impl_calculate_size)(size_t required) return cmc_hashtable_primes[i]; } + +/** + * ITER + * + * Hashmap bi-directional iterator. + */ +#ifdef CMC_EXT_ITER + +struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + 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) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + 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) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + return CMC_(PFX, _empty)(iter->target) || iter->start; +} + +bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + return CMC_(PFX, _empty)(iter->target) || iter->end; +} + +bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + 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) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + 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) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + 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) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + 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) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + 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) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + 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) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + 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; +} + +K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + if (CMC_(PFX, _empty)(iter->target)) + return (K){ 0 }; + + return iter->target->buffer[iter->cursor].key; +} + +V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + if (CMC_(PFX, _empty)(iter->target)) + return (V){ 0 }; + + return iter->target->buffer[iter->cursor].value; +} + +V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + if (CMC_(PFX, _empty)(iter->target)) + return NULL; + + return &(iter->target->buffer[iter->cursor].value); +} + +size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + return iter->index; +} + +#endif /* CMC_EXT_ITER */ + +/** + * STR + * + * Print helper functions. + */ +#ifdef CMC_EXT_STR + +bool CMC_(PFX, _to_string)(struct SNAME *_map_, FILE *fptr) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + struct SNAME *m_ = _map_; + + return 0 <= fprintf(fptr, + "struct %s<%s, %s> " + "at %p { " + "buffer:%p, " + "capacity:%" PRIuMAX ", " + "count:%" PRIuMAX ", " + "load:%lf, " + "flag:%d, " + "f_key:%p, " + "f_val:%p, " + "alloc:%p, " + "callbacks:%p }", + CMC_TO_STRING(SNAME), CMC_TO_STRING(K), CMC_TO_STRING(V), m_, m_->buffer, m_->capacity, + m_->count, m_->load, m_->flag, m_->f_key, m_->f_val, m_->alloc, CMC_CALLBACKS_GET(m_)); +} + +bool CMC_(PFX, _print)(struct SNAME *_map_, FILE *fptr, const char *start, const char *separator, const char *end, + const char *key_val_sep) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + fprintf(fptr, "%s", start); + + size_t last = 0; + for (size_t i = _map_->capacity; i > 0; i--) + { + if ((_map_->buffer[i - 1]).state == CMC_ES_FILLED) + { + last = i - 1; + break; + } + } + + for (size_t i = 0; i < _map_->capacity; i++) + { + struct CMC_DEF_ENTRY(SNAME) *entry = &(_map_->buffer[i]); + + if (entry->state == CMC_ES_FILLED) + { + if (!_map_->f_key->str(fptr, entry->key)) + return false; + + fprintf(fptr, "%s", key_val_sep); + + if (!_map_->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_STR */ diff --git a/cmc/hashmap/ext/code.h b/cmc/hashmap/ext/code.h deleted file mode 100644 index 9844ada..0000000 --- a/cmc/hashmap/ext/code.h +++ /dev/null @@ -1,514 +0,0 @@ -/** - * Copyright (c) 2019 Leonardo Vencovsky - * - * This file is part of the C Macro Collections Library. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * INIT - * - * The part 'INIT' gives a new way of initializing a collection. The collection - * struct is not heap allocated, only its internal structure (nodes, buffers). - */ -#ifdef CMC_EXT_INIT - -struct SNAME CMC_(PFX, _init)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, - struct CMC_DEF_FVAL(SNAME) * f_val) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - return CMC_(PFX, _init_custom)(capacity, load, f_key, f_val, NULL, NULL); -} - -struct SNAME CMC_(PFX, _init_custom)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, - struct CMC_DEF_FVAL(SNAME) * f_val, CMC_ALLOC_TYPE alloc, - CMC_CALLBACK_TYPE callbacks) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - CMC_CALLBACKS_MAYBE_UNUSED(callbacks); - - struct SNAME _map_ = { 0 }; - - if (capacity == 0 || load <= 0 || load >= 1) - return _map_; - - /* Prevent integer overflow */ - if (capacity >= (double)UINTMAX_MAX * load) - return _map_; - - if (!f_key || !f_val) - return _map_; - - size_t real_capacity = CMC_(PFX, _impl_calculate_size)(capacity / load); - - if (!alloc) - alloc = &cmc_alloc_node_default; - - _map_.buffer = alloc->calloc(real_capacity, sizeof(struct CMC_DEF_ENTRY(SNAME))); - - if (!_map_.buffer) - return _map_; - - _map_.count = 0; - _map_.capacity = real_capacity; - _map_.load = load; - _map_.flag = CMC_FLAG_OK; - _map_.f_key = f_key; - _map_.f_val = f_val; - _map_.alloc = alloc; - CMC_CALLBACKS_ASSIGN(&_map_, callbacks); - - return _map_; -} - -void CMC_(PFX, _release)(struct SNAME _map_) -{ - if (_map_.f_key->free || _map_.f_val->free) - { - for (size_t i = 0; i < _map_.capacity; i++) - { - struct CMC_DEF_ENTRY(SNAME) *entry = &(_map_.buffer[i]); - - if (entry->state == CMC_ES_FILLED) - { - if (_map_.f_key->free) - _map_.f_key->free(entry->key); - if (_map_.f_val->free) - _map_.f_val->free(entry->value); - } - } - } - - _map_.alloc->free(_map_.buffer); -} - -#endif /* CMC_EXT_INIT */ - -/** - * ITER - * - * Hashmap bi-directional iterator. - */ -#ifdef CMC_EXT_ITER - -struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - 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) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - 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) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - return CMC_(PFX, _empty)(iter->target) || iter->start; -} - -bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - return CMC_(PFX, _empty)(iter->target) || iter->end; -} - -bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - 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) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - 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) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - 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) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - 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) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - 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) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - 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) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - 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; -} - -K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - if (CMC_(PFX, _empty)(iter->target)) - return (K){ 0 }; - - return iter->target->buffer[iter->cursor].key; -} - -V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - if (CMC_(PFX, _empty)(iter->target)) - return (V){ 0 }; - - return iter->target->buffer[iter->cursor].value; -} - -V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - if (CMC_(PFX, _empty)(iter->target)) - return NULL; - - return &(iter->target->buffer[iter->cursor].value); -} - -size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - return iter->index; -} - -#endif /* CMC_EXT_ITER */ - -/** - * STR - * - * Print helper functions. - */ -#ifdef CMC_EXT_STR - -bool CMC_(PFX, _to_string)(struct SNAME *_map_, FILE *fptr) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - struct SNAME *m_ = _map_; - - return 0 <= fprintf(fptr, - "struct %s<%s, %s> " - "at %p { " - "buffer:%p, " - "capacity:%" PRIuMAX ", " - "count:%" PRIuMAX ", " - "load:%lf, " - "flag:%d, " - "f_key:%p, " - "f_val:%p, " - "alloc:%p, " - "callbacks:%p }", - CMC_TO_STRING(SNAME), CMC_TO_STRING(K), CMC_TO_STRING(V), m_, m_->buffer, m_->capacity, - m_->count, m_->load, m_->flag, m_->f_key, m_->f_val, m_->alloc, CMC_CALLBACKS_GET(m_)); -} - -bool CMC_(PFX, _print)(struct SNAME *_map_, FILE *fptr, const char *start, const char *separator, const char *end, - const char *key_val_sep) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - fprintf(fptr, "%s", start); - - size_t last = 0; - for (size_t i = _map_->capacity; i > 0; i--) - { - if ((_map_->buffer[i - 1]).state == CMC_ES_FILLED) - { - last = i - 1; - break; - } - } - - for (size_t i = 0; i < _map_->capacity; i++) - { - struct CMC_DEF_ENTRY(SNAME) *entry = &(_map_->buffer[i]); - - if (entry->state == CMC_ES_FILLED) - { - if (!_map_->f_key->str(fptr, entry->key)) - return false; - - fprintf(fptr, "%s", key_val_sep); - - if (!_map_->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_STR */ diff --git a/cmc/hashmap/ext/header.h b/cmc/hashmap/ext/header.h deleted file mode 100644 index 4bd06a9..0000000 --- a/cmc/hashmap/ext/header.h +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Copyright (c) 2019 Leonardo Vencovsky - * - * This file is part of the C Macro Collections Library. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * INIT - * - * The part 'INIT' gives a new way of initializing a collection. The collection - * struct is not heap allocated, only its internal structure (nodes, buffers). - */ -#ifdef CMC_EXT_INIT - -struct SNAME CMC_(PFX, _init)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, - struct CMC_DEF_FVAL(SNAME) * f_val); -struct SNAME CMC_(PFX, _init_custom)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, - struct CMC_DEF_FVAL(SNAME) * f_val, CMC_ALLOC_TYPE alloc, - CMC_CALLBACK_TYPE callbacks); -void CMC_(PFX, _release)(struct SNAME _map_); - -#endif /* CMC_EXT_INIT */ - -/** - * ITER - * - * Hashmap bi-directional iterator. - */ -#ifdef CMC_EXT_ITER - -/* 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 */ -K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter); -V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); -V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter); -size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter); - -#endif /* CMC_EXT_ITER */ - -/** - * STR - * - * Print helper functions. - */ -#ifdef CMC_EXT_STR - -bool CMC_(PFX, _to_string)(struct SNAME *_map_, FILE *fptr); -bool CMC_(PFX, _print)(struct SNAME *_map_, FILE *fptr, const char *start, const char *separator, const char *end, - const char *key_val_sep); - -#endif /* CMC_EXT_STR */ diff --git a/cmc/hashmap/ext/struct.h b/cmc/hashmap/ext/struct.h deleted file mode 100644 index 6b997f5..0000000 --- a/cmc/hashmap/ext/struct.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) 2019 Leonardo Vencovsky - * - * This file is part of the C Macro Collections Library. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * ITER - * - * Hashmap bi-directional iterator. - */ -#ifdef CMC_EXT_ITER - -/* HashMap Iterator */ -struct CMC_DEF_ITER(SNAME) -{ - /* Target hashmap */ - 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; -}; - -#endif /* CMC_EXT_ITER */ diff --git a/cmc/hashmap/header.h b/cmc/hashmap/header.h index 81a4c54..7e254de 100644 --- a/cmc/hashmap/header.h +++ b/cmc/hashmap/header.h @@ -64,6 +64,13 @@ struct SNAME *CMC_(PFX, _new_custom)(size_t capacity, double load, struct CMC_DE CMC_CALLBACK_TYPE callbacks); void CMC_(PFX, _clear)(struct SNAME *_map_); void CMC_(PFX, _free)(struct SNAME *_map_); +/* Collection Allocation and Deallocation */ +struct SNAME CMC_(PFX, _init)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, + struct CMC_DEF_FVAL(SNAME) * f_val); +struct SNAME CMC_(PFX, _init_custom)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, + struct CMC_DEF_FVAL(SNAME) * f_val, CMC_ALLOC_TYPE alloc, + CMC_CALLBACK_TYPE callbacks); +void CMC_(PFX, _release)(struct SNAME _map_); /* Customization of Allocation and Callbacks */ void CMC_(PFX, _customize)(struct SNAME *_map_, CMC_ALLOC_TYPE alloc, CMC_CALLBACK_TYPE callbacks); /* Collection Input and Output */ @@ -87,3 +94,45 @@ int CMC_(PFX, _flag)(struct SNAME *_map_); bool CMC_(PFX, _resize)(struct SNAME *_map_, size_t capacity); struct SNAME *CMC_(PFX, _copy_of)(struct SNAME *_map_); bool CMC_(PFX, _equals)(struct SNAME *_map1_, struct SNAME *_map2_); + +/** + * ITER + * + * Hashmap bi-directional iterator. + */ +#ifdef CMC_EXT_ITER + +/* 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 */ +K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter); +V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); +V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter); +size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter); + +#endif /* CMC_EXT_ITER */ + +/** + * STR + * + * Print helper functions. + */ +#ifdef CMC_EXT_STR + +bool CMC_(PFX, _to_string)(struct SNAME *_map_, FILE *fptr); +bool CMC_(PFX, _print)(struct SNAME *_map_, FILE *fptr, const char *start, const char *separator, const char *end, + const char *key_val_sep); + +#endif /* CMC_EXT_STR */ diff --git a/cmc/hashmap/struct.h b/cmc/hashmap/struct.h index 323d361..3c16e01 100644 --- a/cmc/hashmap/struct.h +++ b/cmc/hashmap/struct.h @@ -58,3 +58,31 @@ struct CMC_DEF_ENTRY(SNAME) /* The sate of this node (DELETED, EMPTY, FILLED) */ enum cmc_entry_state state; }; + +/** + * ITER + * + * Hashmap bi-directional iterator. + */ +#ifdef CMC_EXT_ITER + +/* HashMap Iterator */ +struct CMC_DEF_ITER(SNAME) +{ + /* Target hashmap */ + 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; +}; + +#endif /* CMC_EXT_ITER */ diff --git a/cmc/hashmultimap.h b/cmc/hashmultimap.h index f0e8b51..d94d130 100644 --- a/cmc/hashmultimap.h +++ b/cmc/hashmultimap.h @@ -80,28 +80,22 @@ * PFX - functions prefix */ -/* Structs definition */ -#include "cmc/hashmultimap/struct.h" +#if !defined(CMC_STRUCT) && !defined(CMC_HEADER) && !defined(CMC_CODE) +#include "hashmultimap/struct.h" +#include "hashmultimap/header.h" +#include "hashmultimap/code.h" +#endif -/* Function declaration */ -#include "cmc/hashmultimap/header.h" +#ifdef CMC_STRUCT +#include "hashmultimap/struct.h" +#endif /* CMC_STRUCT */ -/* Function implementation */ -#include "cmc/hashmultimap/code.h" +#ifdef CMC_HEADER +#include "hashmultimap/header.h" +#endif /* CMC_HEADER */ -/** - * Extensions - * - * INIT - Initializes the struct on the stack - * ITER - hashmultimap iterator - * STR - Print helper functions - */ -#define CMC_EXT_HASHMULTIMAP_PARTS INIT, ITER, STR -/**/ -#include "cmc/hashmultimap/ext/struct.h" -/**/ -#include "cmc/hashmultimap/ext/header.h" -/**/ -#include "cmc/hashmultimap/ext/code.h" +#ifdef CMC_CODE +#include "hashmultimap/code.h" +#endif /* CMC_CODE */ #include "cor/undef.h" diff --git a/cmc/hashmultimap/code.h b/cmc/hashmultimap/code.h index 8d7a58c..c4fd61a 100644 --- a/cmc/hashmultimap/code.h +++ b/cmc/hashmultimap/code.h @@ -167,6 +167,14 @@ void CMC_(PFX, _free)(struct SNAME *_map_) _map_->alloc->free(_map_); } +// TODO +// struct SNAME CMC_(PFX, _init)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, +// struct CMC_DEF_FVAL(SNAME) * f_val); +// struct SNAME CMC_(PFX, _init_custom)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, +// struct CMC_DEF_FVAL(SNAME) * f_val, CMC_ALLOC_TYPE alloc, +// CMC_CALLBACK_TYPE callbacks); +// void CMC_(PFX, _release)(struct SNAME _map_); + void CMC_(PFX, _customize)(struct SNAME *_map_, CMC_ALLOC_TYPE alloc, CMC_CALLBACK_TYPE callbacks) { #ifdef CMC_DEV @@ -984,3 +992,435 @@ size_t CMC_(PFX, _impl_calculate_size)(size_t required) return cmc_hashtable_primes[i]; } + +/** + * ITER + * + * List bi-directional iterator. + */ +#ifdef CMC_EXT_ITER + +struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + struct CMC_DEF_ITER(SNAME) iter; + + iter.target = target; + iter.curr_entry = NULL; + 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++) + { + struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i][0]; + + if (entry && entry != CMC_ENTRY_DELETED) + { + iter.curr_entry = target->buffer[i][0]; + iter.first = i; + break; + } + } + + iter.cursor = iter.first; + + for (size_t i = target->capacity; i > 0; i--) + { + struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i - 1][1]; + + if (entry && entry != CMC_ENTRY_DELETED) + { + iter.last = i - 1; + break; + } + } + } + + return iter; +} + +struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME *target) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + struct CMC_DEF_ITER(SNAME) iter; + + iter.target = target; + iter.curr_entry = NULL; + 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++) + { + struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i][0]; + + if (entry && entry != CMC_ENTRY_DELETED) + { + iter.first = i; + break; + } + } + + for (size_t i = target->capacity; i > 0; i--) + { + struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i - 1][1]; + + if (entry && entry != CMC_ENTRY_DELETED) + { + iter.curr_entry = target->buffer[i - 1][1]; + 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) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + return CMC_(PFX, _empty)(iter->target) || iter->start; +} + +bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + return CMC_(PFX, _empty)(iter->target) || iter->end; +} + +bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + if (!CMC_(PFX, _empty)(iter->target)) + { + iter->cursor = iter->first; + iter->index = 0; + iter->start = true; + iter->end = CMC_(PFX, _empty)(iter->target); + iter->curr_entry = iter->target->buffer[iter->first][0]; + + return true; + } + + return false; +} + +bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + 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; + iter->curr_entry = iter->target->buffer[iter->last][1]; + + return true; + } + + return false; +} + +bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + if (iter->end) + return false; + + if (iter->curr_entry->next != NULL) + { + iter->curr_entry = iter->curr_entry->next; + iter->index++; + } + else + { + if (iter->cursor == iter->last) + { + iter->end = true; + return false; + } + + iter->cursor++; + + while (iter->target->buffer[iter->cursor][0] == NULL) + iter->cursor++; + + iter->curr_entry = iter->target->buffer[iter->cursor][0]; + + iter->index++; + } + + iter->start = CMC_(PFX, _empty)(iter->target); + + return true; +} + +bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + if (iter->start) + return false; + + if (iter->curr_entry->prev != NULL) + { + iter->curr_entry = iter->curr_entry->prev; + iter->index--; + } + else + { + if (iter->cursor == iter->first) + { + iter->start = true; + return false; + } + + iter->cursor--; + + while (iter->target->buffer[iter->cursor][1] == NULL) + iter->cursor--; + + iter->curr_entry = iter->target->buffer[iter->cursor][1]; + + iter->index--; + } + + iter->end = CMC_(PFX, _empty)(iter->target); + + return true; +} + +/* Returns true only if the iterator moved */ +bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + 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) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + 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) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + 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; +} + +K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + if (CMC_(PFX, _empty)(iter->target)) + return (K){ 0 }; + + return iter->curr_entry->key; +} + +V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + if (CMC_(PFX, _empty)(iter->target)) + return (V){ 0 }; + + return iter->curr_entry->value; +} + +V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + if (CMC_(PFX, _empty)(iter->target)) + return NULL; + + return &(iter->curr_entry->value); +} + +size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + return iter->index; +} + +#endif /* CMC_EXT_ITER */ + +/** + * STR + * + * Print helper functions. + */ +#ifdef CMC_EXT_STR + +bool CMC_(PFX, _to_string)(struct SNAME *_map_, FILE *fptr) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + struct SNAME *m_ = _map_; + + return 0 <= fprintf(fptr, + "struct %s<%s, %s> " + "at %p { " + "buffer:%p, " + "capacity:%" PRIuMAX ", " + "count:%" PRIuMAX ", " + "load:%lf, " + "flag:%d, " + "f_key:%p, " + "f_val:%p, " + "alloc:%p, " + "callbacks:%p }", + CMC_TO_STRING(SNAME), CMC_TO_STRING(K), CMC_TO_STRING(V), m_, m_->buffer, m_->capacity, + m_->count, m_->load, m_->flag, m_->f_key, m_->f_val, m_->alloc, CMC_CALLBACKS_GET(m_)); +} + +bool CMC_(PFX, _print)(struct SNAME *_map_, FILE *fptr, const char *start, const char *separator, const char *end, + const char *key_val_sep) +{ +#ifdef CMC_DEV + CMC_DEV_FCALL; +#endif + + fprintf(fptr, "%s", start); + + size_t last = 0; + for (size_t i = _map_->capacity; i > 0; i--) + { + struct CMC_DEF_ENTRY(SNAME) *entry = _map_->buffer[i - 1][1]; + + if (entry && entry != CMC_ENTRY_DELETED) + { + last = i - 1; + break; + } + } + + for (size_t i = 0; i < _map_->capacity; i++) + { + struct CMC_DEF_ENTRY(SNAME) *scan = _map_->buffer[i][0]; + + while (scan != NULL) + { + if (!_map_->f_key->str(fptr, scan->key)) + return false; + + fprintf(fptr, "%s", key_val_sep); + + if (!_map_->f_val->str(fptr, scan->value)) + return false; + + scan = scan->next; + + if (i + 1 < last) + fprintf(fptr, "%s", separator); + } + } + + fprintf(fptr, "%s", end); + + return true; +} + +#endif /* CMC_EXT_STR */ diff --git a/cmc/hashmultimap/ext/code.h b/cmc/hashmultimap/ext/code.h deleted file mode 100644 index d43ab77..0000000 --- a/cmc/hashmultimap/ext/code.h +++ /dev/null @@ -1,465 +0,0 @@ -/** - * Copyright (c) 2019 Leonardo Vencovsky - * - * This file is part of the C Macro Collections Library. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * INIT - * - * The part 'INIT' gives a new way of initializing a collection. The collection - * struct is not heap allocated, only its internal structure (nodes, buffers). - */ -#ifdef CMC_EXT_INIT - -#endif /* CMC_EXT_INIT */ - -/** - * ITER - * - * List bi-directional iterator. - */ -#ifdef CMC_EXT_ITER - -struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - struct CMC_DEF_ITER(SNAME) iter; - - iter.target = target; - iter.curr_entry = NULL; - 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++) - { - struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i][0]; - - if (entry && entry != CMC_ENTRY_DELETED) - { - iter.curr_entry = target->buffer[i][0]; - iter.first = i; - break; - } - } - - iter.cursor = iter.first; - - for (size_t i = target->capacity; i > 0; i--) - { - struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i - 1][1]; - - if (entry && entry != CMC_ENTRY_DELETED) - { - iter.last = i - 1; - break; - } - } - } - - return iter; -} - -struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME *target) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - struct CMC_DEF_ITER(SNAME) iter; - - iter.target = target; - iter.curr_entry = NULL; - 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++) - { - struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i][0]; - - if (entry && entry != CMC_ENTRY_DELETED) - { - iter.first = i; - break; - } - } - - for (size_t i = target->capacity; i > 0; i--) - { - struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i - 1][1]; - - if (entry && entry != CMC_ENTRY_DELETED) - { - iter.curr_entry = target->buffer[i - 1][1]; - 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) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - return CMC_(PFX, _empty)(iter->target) || iter->start; -} - -bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - return CMC_(PFX, _empty)(iter->target) || iter->end; -} - -bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - if (!CMC_(PFX, _empty)(iter->target)) - { - iter->cursor = iter->first; - iter->index = 0; - iter->start = true; - iter->end = CMC_(PFX, _empty)(iter->target); - iter->curr_entry = iter->target->buffer[iter->first][0]; - - return true; - } - - return false; -} - -bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - 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; - iter->curr_entry = iter->target->buffer[iter->last][1]; - - return true; - } - - return false; -} - -bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - if (iter->end) - return false; - - if (iter->curr_entry->next != NULL) - { - iter->curr_entry = iter->curr_entry->next; - iter->index++; - } - else - { - if (iter->cursor == iter->last) - { - iter->end = true; - return false; - } - - iter->cursor++; - - while (iter->target->buffer[iter->cursor][0] == NULL) - iter->cursor++; - - iter->curr_entry = iter->target->buffer[iter->cursor][0]; - - iter->index++; - } - - iter->start = CMC_(PFX, _empty)(iter->target); - - return true; -} - -bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - if (iter->start) - return false; - - if (iter->curr_entry->prev != NULL) - { - iter->curr_entry = iter->curr_entry->prev; - iter->index--; - } - else - { - if (iter->cursor == iter->first) - { - iter->start = true; - return false; - } - - iter->cursor--; - - while (iter->target->buffer[iter->cursor][1] == NULL) - iter->cursor--; - - iter->curr_entry = iter->target->buffer[iter->cursor][1]; - - iter->index--; - } - - iter->end = CMC_(PFX, _empty)(iter->target); - - return true; -} - -/* Returns true only if the iterator moved */ -bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - 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) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - 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) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - 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; -} - -K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - if (CMC_(PFX, _empty)(iter->target)) - return (K){ 0 }; - - return iter->curr_entry->key; -} - -V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - if (CMC_(PFX, _empty)(iter->target)) - return (V){ 0 }; - - return iter->curr_entry->value; -} - -V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - if (CMC_(PFX, _empty)(iter->target)) - return NULL; - - return &(iter->curr_entry->value); -} - -size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - return iter->index; -} - -#endif /* CMC_EXT_ITER */ - -/** - * STR - * - * Print helper functions. - */ -#ifdef CMC_EXT_STR - -bool CMC_(PFX, _to_string)(struct SNAME *_map_, FILE *fptr) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - struct SNAME *m_ = _map_; - - return 0 <= fprintf(fptr, - "struct %s<%s, %s> " - "at %p { " - "buffer:%p, " - "capacity:%" PRIuMAX ", " - "count:%" PRIuMAX ", " - "load:%lf, " - "flag:%d, " - "f_key:%p, " - "f_val:%p, " - "alloc:%p, " - "callbacks:%p }", - CMC_TO_STRING(SNAME), CMC_TO_STRING(K), CMC_TO_STRING(V), m_, m_->buffer, m_->capacity, - m_->count, m_->load, m_->flag, m_->f_key, m_->f_val, m_->alloc, CMC_CALLBACKS_GET(m_)); -} - -bool CMC_(PFX, _print)(struct SNAME *_map_, FILE *fptr, const char *start, const char *separator, const char *end, - const char *key_val_sep) -{ -#ifdef CMC_DEV - CMC_DEV_FCALL; -#endif - - fprintf(fptr, "%s", start); - - size_t last = 0; - for (size_t i = _map_->capacity; i > 0; i--) - { - struct CMC_DEF_ENTRY(SNAME) *entry = _map_->buffer[i - 1][1]; - - if (entry && entry != CMC_ENTRY_DELETED) - { - last = i - 1; - break; - } - } - - for (size_t i = 0; i < _map_->capacity; i++) - { - struct CMC_DEF_ENTRY(SNAME) *scan = _map_->buffer[i][0]; - - while (scan != NULL) - { - if (!_map_->f_key->str(fptr, scan->key)) - return false; - - fprintf(fptr, "%s", key_val_sep); - - if (!_map_->f_val->str(fptr, scan->value)) - return false; - - scan = scan->next; - - if (i + 1 < last) - fprintf(fptr, "%s", separator); - } - } - - fprintf(fptr, "%s", end); - - return true; -} - -#endif /* CMC_EXT_STR */ diff --git a/cmc/hashmultimap/ext/header.h b/cmc/hashmultimap/ext/header.h deleted file mode 100644 index 9343e19..0000000 --- a/cmc/hashmultimap/ext/header.h +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Copyright (c) 2019 Leonardo Vencovsky - * - * This file is part of the C Macro Collections Library. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * INIT - * - * The part 'INIT' gives a new way of initializing a collection. The collection - * struct is not heap allocated, only its internal structure (nodes, buffers). - */ -#ifdef CMC_EXT_INIT - -#endif /* CMC_EXT_INIT */ - -/** - * ITER - * - * Hashmultimap bi-directional iterator. - */ -#ifdef CMC_EXT_ITER - -/* 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 */ -K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter); -V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); -V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter); -size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter); - -#endif /* CMC_EXT_ITER */ - -/** - * STR - * - * Print helper functions. - */ -#ifdef CMC_EXT_STR - -bool CMC_(PFX, _to_string)(struct SNAME *_map_, FILE *fptr); -bool CMC_(PFX, _print)(struct SNAME *_map_, FILE *fptr, const char *start, const char *separator, const char *end, - const char *key_val_sep); - -#endif /* CMC_EXT_STR */ diff --git a/cmc/hashmultimap/ext/struct.h b/cmc/hashmultimap/ext/struct.h deleted file mode 100644 index 5914204..0000000 --- a/cmc/hashmultimap/ext/struct.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright (c) 2019 Leonardo Vencovsky - * - * This file is part of the C Macro Collections Library. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * ITER - * - * Hashmultimap bi-directional iterator. - */ -#ifdef CMC_EXT_ITER - -/* HashMultiMap Iterator */ -struct CMC_DEF_ITER(SNAME) -{ - /* Target hashmultimap */ - struct SNAME *target; - /* Current entry */ - struct CMC_DEF_ENTRY(SNAME) * curr_entry; - /* 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; -}; - -#endif /* CMC_EXT_ITER */ diff --git a/cmc/hashmultimap/header.h b/cmc/hashmultimap/header.h index 0070af1..17f8df3 100644 --- a/cmc/hashmultimap/header.h +++ b/cmc/hashmultimap/header.h @@ -64,6 +64,14 @@ struct SNAME *CMC_(PFX, _new_custom)(size_t capacity, double load, struct CMC_DE CMC_CALLBACK_TYPE callbacks); void CMC_(PFX, _clear)(struct SNAME *_map_); void CMC_(PFX, _free)(struct SNAME *_map_); +/* Collection Allocation and Deallocation */ +// TODO +// struct SNAME CMC_(PFX, _init)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, +// struct CMC_DEF_FVAL(SNAME) * f_val); +// struct SNAME CMC_(PFX, _init_custom)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, +// struct CMC_DEF_FVAL(SNAME) * f_val, CMC_ALLOC_TYPE alloc, +// CMC_CALLBACK_TYPE callbacks); +// void CMC_(PFX, _release)(struct SNAME _map_); /* Customization of Allocation and Callbacks */ void CMC_(PFX, _customize)(struct SNAME *_map_, CMC_ALLOC_TYPE alloc, CMC_CALLBACK_TYPE callbacks); /* Collection Input and Output */ @@ -90,3 +98,45 @@ int CMC_(PFX, _flag)(struct SNAME *_map_); bool CMC_(PFX, _resize)(struct SNAME *_map_, size_t capacity); struct SNAME *CMC_(PFX, _copy_of)(struct SNAME *_map_); bool CMC_(PFX, _equals)(struct SNAME *_map1_, struct SNAME *_map2_); + +/** + * ITER + * + * Hashmultimap bi-directional iterator. + */ +#ifdef CMC_EXT_ITER + +/* 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 */ +K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter); +V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); +V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter); +size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter); + +#endif /* CMC_EXT_ITER */ + +/** + * STR + * + * Print helper functions. + */ +#ifdef CMC_EXT_STR + +bool CMC_(PFX, _to_string)(struct SNAME *_map_, FILE *fptr); +bool CMC_(PFX, _print)(struct SNAME *_map_, FILE *fptr, const char *start, const char *separator, const char *end, + const char *key_val_sep); + +#endif /* CMC_EXT_STR */ diff --git a/cmc/hashmultimap/struct.h b/cmc/hashmultimap/struct.h index 5dad01f..27fc1a9 100644 --- a/cmc/hashmultimap/struct.h +++ b/cmc/hashmultimap/struct.h @@ -57,3 +57,33 @@ struct CMC_DEF_ENTRY(SNAME) /* Previous entry on the linked list */ struct CMC_DEF_ENTRY(SNAME) * prev; }; + +/** + * ITER + * + * Hashmultimap bi-directional iterator. + */ +#ifdef CMC_EXT_ITER + +/* HashMultiMap Iterator */ +struct CMC_DEF_ITER(SNAME) +{ + /* Target hashmultimap */ + struct SNAME *target; + /* Current entry */ + struct CMC_DEF_ENTRY(SNAME) * curr_entry; + /* 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; +}; + +#endif /* CMC_EXT_ITER */ diff --git a/tests/unt_list.h b/tests/unt_list.h index ee547e9..971ab3b 100644 --- a/tests/unt_list.h +++ b/tests/unt_list.h @@ -48,6 +48,8 @@ CMC_CREATE_UNIT(CMCList, true, { cmc_assert_equals(size_t, 100, l_capacity(l)); cmc_assert_equals(size_t, 0, l_count(l)); cmc_assert_equals(int32_t, CMC_FLAG_OK, l_flag(l)); + + l_free(l); }); CMC_CREATE_TEST(PFX##_clear, {