diff --git a/src/cmc/deque.h b/src/cmc/deque.h index 811fe91..cb3bb65 100644 --- a/src/cmc/deque.h +++ b/src/cmc/deque.h @@ -99,8 +99,8 @@ /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ FMOD SNAME *PFX##_new(size_t capacity); \ - FMOD void PFX##_clear(SNAME *_deque_); \ - FMOD void PFX##_free(SNAME *_deque_); \ + FMOD void PFX##_clear(SNAME *_deque_, void (*deallocator)(V)); \ + FMOD void PFX##_free(SNAME *_deque_, void (*deallocator)(V)); \ /* Collection Input and Output */ \ FMOD bool PFX##_push_front(SNAME *_deque_, V element); \ FMOD bool PFX##_push_back(SNAME *_deque_, V element); \ @@ -153,366 +153,382 @@ } \ \ /* SOURCE ********************************************************************/ -#define DEQUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ - \ - /* Implementation Detail Functions */ \ - static bool PFX##_impl_grow(SNAME *_deque_); \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_deque_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_deque_); \ - \ - FMOD SNAME *PFX##_new(size_t capacity) \ - { \ - if (capacity < 1) \ - return NULL; \ - \ - SNAME *_deque_ = malloc(sizeof(SNAME)); \ - \ - if (!_deque_) \ - return NULL; \ - \ - _deque_->buffer = malloc(sizeof(V) * capacity); \ - \ - if (!_deque_->buffer) \ - { \ - free(_deque_); \ - return NULL; \ - } \ - \ - memset(_deque_->buffer, 0, sizeof(V) * capacity); \ - \ - _deque_->capacity = capacity; \ - _deque_->count = 0; \ - _deque_->front = 0; \ - _deque_->back = 0; \ - \ - _deque_->it_start = PFX##_impl_it_start; \ - _deque_->it_end = PFX##_impl_it_end; \ - \ - return _deque_; \ - } \ - \ - FMOD void PFX##_clear(SNAME *_deque_) \ - { \ - memset(_deque_->buffer, 0, sizeof(V) * _deque_->capacity); \ - \ - _deque_->count = 0; \ - _deque_->front = 0; \ - _deque_->back = 0; \ - } \ - \ - FMOD void PFX##_free(SNAME *_deque_) \ - { \ - free(_deque_->buffer); \ - free(_deque_); \ - } \ - \ - FMOD bool PFX##_push_front(SNAME *_deque_, V element) \ - { \ - if (PFX##_full(_deque_)) \ - { \ - if (!PFX##_impl_grow(_deque_)) \ - return false; \ - } \ - \ - _deque_->front = (_deque_->front == 0) ? _deque_->capacity - 1 : _deque_->front - 1; \ - \ - _deque_->buffer[_deque_->front] = element; \ - \ - _deque_->count++; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_push_back(SNAME *_deque_, V element) \ - { \ - if (PFX##_full(_deque_)) \ - { \ - if (!PFX##_impl_grow(_deque_)) \ - return false; \ - } \ - \ - _deque_->buffer[_deque_->back] = element; \ - \ - _deque_->back = (_deque_->back == _deque_->capacity - 1) ? 0 : _deque_->back + 1; \ - \ - _deque_->count++; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_pop_front(SNAME *_deque_) \ - { \ - if (PFX##_empty(_deque_)) \ - return false; \ - \ - _deque_->buffer[_deque_->front] = PFX##_impl_default_value(); \ - \ - _deque_->front = (_deque_->front == _deque_->capacity - 1) ? 0 : _deque_->front + 1; \ - \ - _deque_->count--; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_pop_back(SNAME *_deque_) \ - { \ - if (PFX##_empty(_deque_)) \ - return false; \ - \ - _deque_->back = (_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1; \ - \ - _deque_->buffer[_deque_->back] = PFX##_impl_default_value(); \ - \ - _deque_->count--; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_push_front_if(SNAME *_deque_, V element, bool condition) \ - { \ - if (condition) \ - return PFX##_push_front(_deque_, element); \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_push_back_if(SNAME *_deque_, V element, bool condition) \ - { \ - if (condition) \ - return PFX##_push_back(_deque_, element); \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_pop_front_if(SNAME *_deque_, bool condition) \ - { \ - if (condition) \ - return PFX##_pop_front(_deque_); \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_pop_back_if(SNAME *_deque_, bool condition) \ - { \ - if (condition) \ - return PFX##_pop_back(_deque_); \ - \ - return false; \ - } \ - \ - FMOD V PFX##_front(SNAME *_deque_) \ - { \ - if (PFX##_empty(_deque_)) \ - return PFX##_impl_default_value(); \ - \ - return _deque_->buffer[_deque_->front]; \ - } \ - \ - FMOD V PFX##_back(SNAME *_deque_) \ - { \ - if (PFX##_empty(_deque_)) \ - return PFX##_impl_default_value(); \ - \ - return _deque_->buffer[(_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1]; \ - } \ - \ - FMOD bool PFX##_contains(SNAME *_deque_, V element, int (*comparator)(V, V)) \ - { \ - for (size_t i = _deque_->front, j = 0; j < _deque_->count; i = (i + 1) % _deque_->count, j++) \ - { \ - if (comparator(_deque_->buffer[i], element) == 0) \ - return true; \ - } \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_empty(SNAME *_deque_) \ - { \ - return _deque_->count == 0; \ - } \ - \ - FMOD bool PFX##_full(SNAME *_deque_) \ - { \ - return _deque_->count >= _deque_->capacity; \ - } \ - \ - FMOD size_t PFX##_count(SNAME *_deque_) \ - { \ - return _deque_->count; \ - } \ - \ - FMOD size_t PFX##_capacity(SNAME *_deque_) \ - { \ - return _deque_->capacity; \ - } \ - \ - FMOD cmc_string PFX##_to_string(SNAME *_deque_) \ - { \ - cmc_string str; \ - SNAME *d_ = _deque_; \ - const char *name = #SNAME; \ - \ - snprintf(str.s, cmc_string_len, cmc_string_fmt_deque, \ - name, d_, d_->buffer, d_->capacity, d_->count, d_->front, d_->back); \ - \ - return str; \ - } \ - \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ - { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - FMOD void PFX##_iter_free(SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ - { \ - iter->target = target; \ - iter->cursor = target->front; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - } \ - \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ - { \ - iter->cursor = iter->target->front; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - } \ - \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - iter->cursor = 0; \ - else \ - iter->cursor = (iter->target->back == 0) ? iter->target->capacity - 1 : iter->target->back - 1; \ - \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - } \ - \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - if (iter->index == iter->target->count - 1) \ - iter->end = true; \ - else \ - { \ - iter->cursor = (iter->cursor + 1) % (iter->target->capacity); \ - iter->index++; \ - } \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - if (iter->index == 0) \ - iter->start = true; \ - else \ - { \ - iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; \ - iter->index--; \ - } \ - \ - return true; \ - } \ - \ - FMOD V PFX##_iter_value(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return PFX##_impl_default_value(); \ - \ - return iter->target->buffer[iter->cursor]; \ - } \ - \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->target->buffer[iter->cursor]); \ - } \ - \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - static bool PFX##_impl_grow(SNAME *_deque_) \ - { \ - size_t new_capacity = _deque_->capacity * 2; \ - \ - V *new_buffer = malloc(sizeof(V) * new_capacity); \ - \ - if (!new_buffer) \ - return false; \ - \ - for (size_t i = _deque_->front, j = 0; j < _deque_->count; i = (i + 1) % _deque_->capacity, j++) \ - { \ - new_buffer[j] = _deque_->buffer[i]; \ - } \ - \ - free(_deque_->buffer); \ - \ - _deque_->buffer = new_buffer; \ - _deque_->capacity = new_capacity; \ - _deque_->front = 0; \ - _deque_->back = _deque_->count; \ - \ - return true; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_deque_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _deque_); \ - \ - return iter; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_deque_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _deque_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ +#define DEQUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ + \ + /* Implementation Detail Functions */ \ + static bool PFX##_impl_grow(SNAME *_deque_); \ + static SNAME##_iter PFX##_impl_it_start(SNAME *_deque_); \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_deque_); \ + \ + FMOD SNAME *PFX##_new(size_t capacity) \ + { \ + if (capacity < 1) \ + return NULL; \ + \ + SNAME *_deque_ = malloc(sizeof(SNAME)); \ + \ + if (!_deque_) \ + return NULL; \ + \ + _deque_->buffer = malloc(sizeof(V) * capacity); \ + \ + if (!_deque_->buffer) \ + { \ + free(_deque_); \ + return NULL; \ + } \ + \ + memset(_deque_->buffer, 0, sizeof(V) * capacity); \ + \ + _deque_->capacity = capacity; \ + _deque_->count = 0; \ + _deque_->front = 0; \ + _deque_->back = 0; \ + \ + _deque_->it_start = PFX##_impl_it_start; \ + _deque_->it_end = PFX##_impl_it_end; \ + \ + return _deque_; \ + } \ + \ + FMOD void PFX##_clear(SNAME *_deque_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = _deque_->front, j = 0; j < _deque_->count; i = (i + 1) % _deque_->capacity, j++) \ + { \ + deallocator(_deque_->buffer[i]); \ + } \ + } \ + \ + memset(_deque_->buffer, 0, sizeof(V) * _deque_->capacity); \ + \ + _deque_->count = 0; \ + _deque_->front = 0; \ + _deque_->back = 0; \ + } \ + \ + FMOD void PFX##_free(SNAME *_deque_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = _deque_->front, j = 0; j < _deque_->count; i = (i + 1) % _deque_->capacity, j++) \ + { \ + deallocator(_deque_->buffer[i]); \ + } \ + } \ + \ + free(_deque_->buffer); \ + free(_deque_); \ + } \ + \ + FMOD bool PFX##_push_front(SNAME *_deque_, V element) \ + { \ + if (PFX##_full(_deque_)) \ + { \ + if (!PFX##_impl_grow(_deque_)) \ + return false; \ + } \ + \ + _deque_->front = (_deque_->front == 0) ? _deque_->capacity - 1 : _deque_->front - 1; \ + \ + _deque_->buffer[_deque_->front] = element; \ + \ + _deque_->count++; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_push_back(SNAME *_deque_, V element) \ + { \ + if (PFX##_full(_deque_)) \ + { \ + if (!PFX##_impl_grow(_deque_)) \ + return false; \ + } \ + \ + _deque_->buffer[_deque_->back] = element; \ + \ + _deque_->back = (_deque_->back == _deque_->capacity - 1) ? 0 : _deque_->back + 1; \ + \ + _deque_->count++; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_pop_front(SNAME *_deque_) \ + { \ + if (PFX##_empty(_deque_)) \ + return false; \ + \ + _deque_->buffer[_deque_->front] = PFX##_impl_default_value(); \ + \ + _deque_->front = (_deque_->front == _deque_->capacity - 1) ? 0 : _deque_->front + 1; \ + \ + _deque_->count--; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_pop_back(SNAME *_deque_) \ + { \ + if (PFX##_empty(_deque_)) \ + return false; \ + \ + _deque_->back = (_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1; \ + \ + _deque_->buffer[_deque_->back] = PFX##_impl_default_value(); \ + \ + _deque_->count--; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_push_front_if(SNAME *_deque_, V element, bool condition) \ + { \ + if (condition) \ + return PFX##_push_front(_deque_, element); \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_push_back_if(SNAME *_deque_, V element, bool condition) \ + { \ + if (condition) \ + return PFX##_push_back(_deque_, element); \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_pop_front_if(SNAME *_deque_, bool condition) \ + { \ + if (condition) \ + return PFX##_pop_front(_deque_); \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_pop_back_if(SNAME *_deque_, bool condition) \ + { \ + if (condition) \ + return PFX##_pop_back(_deque_); \ + \ + return false; \ + } \ + \ + FMOD V PFX##_front(SNAME *_deque_) \ + { \ + if (PFX##_empty(_deque_)) \ + return PFX##_impl_default_value(); \ + \ + return _deque_->buffer[_deque_->front]; \ + } \ + \ + FMOD V PFX##_back(SNAME *_deque_) \ + { \ + if (PFX##_empty(_deque_)) \ + return PFX##_impl_default_value(); \ + \ + return _deque_->buffer[(_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1]; \ + } \ + \ + FMOD bool PFX##_contains(SNAME *_deque_, V element, int (*comparator)(V, V)) \ + { \ + for (size_t i = _deque_->front, j = 0; j < _deque_->count; i = (i + 1) % _deque_->count, j++) \ + { \ + if (comparator(_deque_->buffer[i], element) == 0) \ + return true; \ + } \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_empty(SNAME *_deque_) \ + { \ + return _deque_->count == 0; \ + } \ + \ + FMOD bool PFX##_full(SNAME *_deque_) \ + { \ + return _deque_->count >= _deque_->capacity; \ + } \ + \ + FMOD size_t PFX##_count(SNAME *_deque_) \ + { \ + return _deque_->count; \ + } \ + \ + FMOD size_t PFX##_capacity(SNAME *_deque_) \ + { \ + return _deque_->capacity; \ + } \ + \ + FMOD cmc_string PFX##_to_string(SNAME *_deque_) \ + { \ + cmc_string str; \ + SNAME *d_ = _deque_; \ + const char *name = #SNAME; \ + \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_deque, \ + name, d_, d_->buffer, d_->capacity, d_->count, d_->front, d_->back); \ + \ + return str; \ + } \ + \ + FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ + { \ + SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + FMOD void PFX##_iter_free(SNAME##_iter *iter) \ + { \ + free(iter); \ + } \ + \ + FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + { \ + iter->target = target; \ + iter->cursor = target->front; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + } \ + \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ + { \ + iter->cursor = iter->target->front; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ + \ + FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + iter->cursor = 0; \ + else \ + iter->cursor = (iter->target->back == 0) ? iter->target->capacity - 1 : iter->target->back - 1; \ + \ + iter->index = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + } \ + \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ + { \ + if (iter->end) \ + return false; \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + if (iter->index == iter->target->count - 1) \ + iter->end = true; \ + else \ + { \ + iter->cursor = (iter->cursor + 1) % (iter->target->capacity); \ + iter->index++; \ + } \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + if (iter->index == 0) \ + iter->start = true; \ + else \ + { \ + iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; \ + iter->index--; \ + } \ + \ + return true; \ + } \ + \ + FMOD V PFX##_iter_value(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return PFX##_impl_default_value(); \ + \ + return iter->target->buffer[iter->cursor]; \ + } \ + \ + FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return NULL; \ + \ + return &(iter->target->buffer[iter->cursor]); \ + } \ + \ + FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + static bool PFX##_impl_grow(SNAME *_deque_) \ + { \ + size_t new_capacity = _deque_->capacity * 2; \ + \ + V *new_buffer = malloc(sizeof(V) * new_capacity); \ + \ + if (!new_buffer) \ + return false; \ + \ + for (size_t i = _deque_->front, j = 0; j < _deque_->count; i = (i + 1) % _deque_->capacity, j++) \ + { \ + new_buffer[j] = _deque_->buffer[i]; \ + } \ + \ + free(_deque_->buffer); \ + \ + _deque_->buffer = new_buffer; \ + _deque_->capacity = new_capacity; \ + _deque_->front = 0; \ + _deque_->back = _deque_->count; \ + \ + return true; \ + } \ + \ + static SNAME##_iter PFX##_impl_it_start(SNAME *_deque_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _deque_); \ + \ + return iter; \ + } \ + \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_deque_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _deque_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_DEQUE_H */ diff --git a/src/cmc/hashmap.h b/src/cmc/hashmap.h index 464774f..b168375 100644 --- a/src/cmc/hashmap.h +++ b/src/cmc/hashmap.h @@ -157,8 +157,8 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ FMOD SNAME *PFX##_new(size_t capacity, double load, int (*compare)(K, K), size_t (*hash)(K)); \ - FMOD void PFX##_clear(SNAME *_map_); \ - FMOD void PFX##_free(SNAME *_map_); \ + FMOD void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)); \ + FMOD void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)); \ /* Collection Input and Output */ \ FMOD bool PFX##_insert(SNAME *_map_, K key, V value); \ FMOD bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value); \ @@ -268,15 +268,41 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return _map_; \ } \ \ - FMOD void PFX##_clear(SNAME *_map_) \ + FMOD void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)) \ { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _map_->capacity; i++) \ + { \ + SNAME##_entry *entry = &(_map_->buffer[i]); \ + \ + if (entry->state == CMC_ES_FILLED) \ + { \ + deallocator(entry->key, entry->value); \ + } \ + } \ + } \ + \ memset(_map_->buffer, 0, sizeof(SNAME##_entry) * _map_->capacity); \ \ _map_->count = 0; \ } \ \ - FMOD void PFX##_free(SNAME *_map_) \ + FMOD void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)) \ { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _map_->capacity; i++) \ + { \ + SNAME##_entry *entry = &(_map_->buffer[i]); \ + \ + if (entry->state == CMC_ES_FILLED) \ + { \ + deallocator(entry->key, entry->value); \ + } \ + } \ + } \ + \ free(_map_->buffer); \ free(_map_); \ } \ @@ -696,7 +722,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ if (_map_->count != _new_map_->count) \ { \ - PFX##_free(_new_map_); \ + PFX##_free(_new_map_, NULL); \ return false; \ } \ \ @@ -706,7 +732,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ _map_->capacity = _new_map_->capacity; \ \ - PFX##_free(_new_map_); \ + PFX##_free(_new_map_, NULL); \ \ return true; \ } \ diff --git a/src/cmc/hashset.h b/src/cmc/hashset.h index 81705d3..8dd076b 100644 --- a/src/cmc/hashset.h +++ b/src/cmc/hashset.h @@ -152,8 +152,8 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ FMOD SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), size_t (*hash)(V)); \ - FMOD void PFX##_clear(SNAME *_set_); \ - FMOD void PFX##_free(SNAME *_set_); \ + FMOD void PFX##_clear(SNAME *_set_, void (*deallocator)(V)); \ + FMOD void PFX##_free(SNAME *_set_, void (*deallocator)(V)); \ /* Collection Input and Output */ \ FMOD bool PFX##_insert(SNAME *_set_, V element); \ FMOD bool PFX##_remove(SNAME *_set_, V element); \ @@ -258,15 +258,41 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return _set_; \ } \ \ - FMOD void PFX##_clear(SNAME *_set_) \ + FMOD void PFX##_clear(SNAME *_set_, void (*deallocator)(V)) \ { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _set_->capacity; i++) \ + { \ + SNAME##_entry *entry = &(_set_->buffer[i]); \ + \ + if (entry->state == CMC_ES_FILLED) \ + { \ + deallocator(entry->value); \ + } \ + } \ + } \ + \ memset(_set_->buffer, 0, sizeof(SNAME##_entry) * _set_->capacity); \ \ _set_->count = 0; \ } \ \ - FMOD void PFX##_free(SNAME *_set_) \ + FMOD void PFX##_free(SNAME *_set_, void (*deallocator)(V)) \ { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _set_->capacity; i++) \ + { \ + SNAME##_entry *entry = &(_set_->buffer[i]); \ + \ + if (entry->state == CMC_ES_FILLED) \ + { \ + deallocator(entry->value); \ + } \ + } \ + } \ + \ free(_set_->buffer); \ free(_set_); \ } \ @@ -800,7 +826,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ if (_set_->count != _new_set_->count) \ { \ - PFX##_free(_new_set_); \ + PFX##_free(_new_set_, NULL); \ \ return false; \ } \ @@ -811,7 +837,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ _set_->capacity = _new_set_->capacity; \ \ - PFX##_free(_new_set_); \ + PFX##_free(_new_set_, NULL); \ \ return true; \ } \ diff --git a/src/cmc/heap.h b/src/cmc/heap.h index 74b4f8e..83da512 100644 --- a/src/cmc/heap.h +++ b/src/cmc/heap.h @@ -101,8 +101,8 @@ typedef enum cmc_heap_order_e /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ FMOD SNAME *PFX##_new(size_t capacity, cmc_heap_order HO, int (*compare)(V, V)); \ - FMOD void PFX##_clear(SNAME *_heap_); \ - FMOD void PFX##_free(SNAME *_heap_); \ + FMOD void PFX##_clear(SNAME *_heap_, void (*deallocator)(V)); \ + FMOD void PFX##_free(SNAME *_heap_, void (*deallocator)(V)); \ /* Collection Input and Output */ \ FMOD bool PFX##_insert(SNAME *_heap_, V element); \ FMOD bool PFX##_remove(SNAME *_heap_, V *result); \ @@ -193,15 +193,31 @@ typedef enum cmc_heap_order_e return _heap_; \ } \ \ - FMOD void PFX##_clear(SNAME *_heap_) \ + FMOD void PFX##_clear(SNAME *_heap_, void (*deallocator)(V)) \ { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _heap_->count; i++) \ + { \ + deallocator(_heap_->buffer[i]); \ + } \ + } \ + \ memset(_heap_->buffer, 0, sizeof(V) * _heap_->capacity); \ \ _heap_->count = 0; \ } \ \ - FMOD void PFX##_free(SNAME *_heap_) \ + FMOD void PFX##_free(SNAME *_heap_, void (*deallocator)(V)) \ { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _heap_->count; i++) \ + { \ + deallocator(_heap_->buffer[i]); \ + } \ + } \ + \ free(_heap_->buffer); \ free(_heap_); \ } \ diff --git a/src/cmc/linkedlist.h b/src/cmc/linkedlist.h index c2fba4d..001b321 100644 --- a/src/cmc/linkedlist.h +++ b/src/cmc/linkedlist.h @@ -104,8 +104,8 @@ /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ FMOD SNAME *PFX##_new(void); \ - FMOD void PFX##_clear(SNAME *_list_); \ - FMOD void PFX##_free(SNAME *_list_); \ + FMOD void PFX##_clear(SNAME *_list_, void (*deallocator)(V)); \ + FMOD void PFX##_free(SNAME *_list_, void (*deallocator)(V)); \ /* Collection Input and Output */ \ FMOD bool PFX##_push_front(SNAME *_list_, V element); \ FMOD bool PFX##_push(SNAME *_list_, V element, size_t index); \ @@ -200,14 +200,21 @@ return _list_; \ } \ \ - FMOD void PFX##_clear(SNAME *_list_) \ + FMOD void PFX##_clear(SNAME *_list_, void (*deallocator)(V)) \ { \ SNAME##_node *scan = _list_->head; \ \ while (_list_->head != NULL) \ { \ _list_->head = _list_->head->next; \ + \ + if (deallocator) \ + { \ + deallocator(scan->data); \ + } \ + \ free(scan); \ + \ scan = _list_->head; \ } \ \ @@ -216,9 +223,9 @@ _list_->tail = NULL; \ } \ \ - FMOD void PFX##_free(SNAME *_list_) \ + FMOD void PFX##_free(SNAME *_list_, void (*deallocator)(V)) \ { \ - PFX##_clear(_list_); \ + PFX##_clear(_list_, deallocator); \ \ free(_list_); \ } \ diff --git a/src/cmc/list.h b/src/cmc/list.h index 4418f41..0fd6b6c 100644 --- a/src/cmc/list.h +++ b/src/cmc/list.h @@ -103,8 +103,8 @@ /* Collection Allocation and Deallocation */ \ FMOD SNAME *PFX##_new(size_t capacity); \ FMOD SNAME *PFX##_new_from(V *elements, size_t size); \ - FMOD void PFX##_clear(SNAME *_list_); \ - FMOD void PFX##_free(SNAME *_list_); \ + FMOD void PFX##_clear(SNAME *_list_, void (*deallocator)(V)); \ + FMOD void PFX##_free(SNAME *_list_, void (*deallocator)(V)); \ /* Collection Input and Output */ \ FMOD bool PFX##_push_front(SNAME *_list_, V element); \ FMOD bool PFX##_push(SNAME *_list_, V element, size_t index); \ @@ -220,15 +220,27 @@ return _list_; \ } \ \ - FMOD void PFX##_clear(SNAME *_list_) \ + FMOD void PFX##_clear(SNAME *_list_, void (*deallocator)(V)) \ { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _list_->count; i++) \ + deallocator(_list_->buffer[i]); \ + } \ + \ memset(_list_->buffer, 0, sizeof(V) * _list_->capacity); \ \ _list_->count = 0; \ } \ \ - FMOD void PFX##_free(SNAME *_list_) \ + FMOD void PFX##_free(SNAME *_list_, void (*deallocator)(V)) \ { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _list_->count; i++) \ + deallocator(_list_->buffer[i]); \ + } \ + \ free(_list_->buffer); \ free(_list_); \ } \ diff --git a/src/cmc/queue.h b/src/cmc/queue.h index 5812481..eae6b7b 100644 --- a/src/cmc/queue.h +++ b/src/cmc/queue.h @@ -111,8 +111,8 @@ /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ FMOD SNAME *PFX##_new(size_t capacity); \ - FMOD void PFX##_clear(SNAME *_queue_); \ - FMOD void PFX##_free(SNAME *_queue_); \ + FMOD void PFX##_clear(SNAME *_queue_, void (*deallocator)(V)); \ + FMOD void PFX##_free(SNAME *_queue_, void (*deallocator)(V)); \ /* Collection Input and Output */ \ FMOD bool PFX##_enqueue(SNAME *_queue_, V element); \ FMOD bool PFX##_dequeue(SNAME *_queue_); \ @@ -160,311 +160,327 @@ } \ \ /* SOURCE ********************************************************************/ -#define QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ - \ - /* Implementation Detail Functions */ \ - static bool PFX##_impl_grow(SNAME *_queue_); \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_queue_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_queue_); \ - \ - FMOD SNAME *PFX##_new(size_t capacity) \ - { \ - if (capacity < 1) \ - return NULL; \ - \ - SNAME *_queue_ = malloc(sizeof(SNAME)); \ - \ - if (!_queue_) \ - return NULL; \ - \ - _queue_->buffer = malloc(sizeof(V) * capacity); \ - \ - if (!_queue_->buffer) \ - { \ - free(_queue_); \ - return NULL; \ - } \ - \ - memset(_queue_->buffer, 0, sizeof(V) * capacity); \ - \ - _queue_->capacity = capacity; \ - _queue_->count = 0; \ - _queue_->front = 0; \ - _queue_->back = 0; \ - \ - _queue_->it_start = PFX##_impl_it_start; \ - _queue_->it_end = PFX##_impl_it_end; \ - \ - return _queue_; \ - } \ - \ - FMOD void PFX##_clear(SNAME *_queue_) \ - { \ - memset(_queue_->buffer, 0, sizeof(V) * _queue_->capacity); \ - \ - _queue_->count = 0; \ - _queue_->front = 0; \ - _queue_->back = 0; \ - } \ - \ - FMOD void PFX##_free(SNAME *_queue_) \ - { \ - free(_queue_->buffer); \ - free(_queue_); \ - } \ - \ - FMOD bool PFX##_enqueue(SNAME *_queue_, V element) \ - { \ - if (PFX##_full(_queue_)) \ - { \ - if (!PFX##_impl_grow(_queue_)) \ - return false; \ - } \ - \ - _queue_->buffer[_queue_->back] = element; \ - \ - _queue_->back = (_queue_->back == _queue_->capacity - 1) ? 0 : _queue_->back + 1; \ - _queue_->count++; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_dequeue(SNAME *_queue_) \ - { \ - if (PFX##_empty(_queue_)) \ - return false; \ - \ - _queue_->buffer[_queue_->front] = PFX##_impl_default_value(); \ - \ - _queue_->front = (_queue_->front == _queue_->capacity - 1) ? 0 : _queue_->front + 1; \ - _queue_->count--; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_enqueue_if(SNAME *_queue_, V element, bool condition) \ - { \ - if (condition) \ - return PFX##_enqueue(_queue_, element); \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_dequeue_if(SNAME *_queue_, bool condition) \ - { \ - if (condition) \ - return PFX##_dequeue(_queue_); \ - \ - return false; \ - } \ - \ - FMOD V PFX##_peek(SNAME *_queue_) \ - { \ - if (PFX##_empty(_queue_)) \ - return PFX##_impl_default_value(); \ - \ - return _queue_->buffer[_queue_->front]; \ - } \ - \ - FMOD bool PFX##_contains(SNAME *_queue_, V element, int (*comparator)(V, V)) \ - { \ - for (size_t i = _queue_->front, j = 0; j < _queue_->count; i = (i + 1) % _queue_->count, j++) \ - { \ - if (comparator(_queue_->buffer[i], element) == 0) \ - return true; \ - } \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_empty(SNAME *_queue_) \ - { \ - return _queue_->count == 0; \ - } \ - \ - FMOD bool PFX##_full(SNAME *_queue_) \ - { \ - return _queue_->count >= _queue_->capacity; \ - } \ - \ - FMOD size_t PFX##_count(SNAME *_queue_) \ - { \ - return _queue_->count; \ - } \ - \ - FMOD size_t PFX##_capacity(SNAME *_queue_) \ - { \ - return _queue_->capacity; \ - } \ - \ - FMOD cmc_string PFX##_to_string(SNAME *_queue_) \ - { \ - cmc_string str; \ - SNAME *q_ = _queue_; \ - const char *name = #SNAME; \ - \ - snprintf(str.s, cmc_string_len, cmc_string_fmt_queue, \ - name, q_, q_->buffer, q_->capacity, q_->count, q_->front, q_->back); \ - \ - return str; \ - } \ - \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ - { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - FMOD void PFX##_iter_free(SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ - { \ - iter->target = target; \ - iter->cursor = target->front; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - } \ - \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ - { \ - iter->cursor = iter->target->front; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - } \ - \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - iter->cursor = 0; \ - else \ - iter->cursor = (iter->target->back == 0) ? iter->target->capacity - 1 : iter->target->back - 1; \ - \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - } \ - \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - if (iter->index == iter->target->count - 1) \ - iter->end = true; \ - else \ - { \ - iter->cursor = (iter->cursor + 1) % (iter->target->capacity); \ - iter->index++; \ - } \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - iter->end = PFX##_empty(iter->target); \ - \ - if (iter->index == 0) \ - iter->start = true; \ - else \ - { \ - iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; \ - iter->index--; \ - } \ - \ - return true; \ - } \ - \ - FMOD V PFX##_iter_value(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return PFX##_impl_default_value(); \ - \ - return iter->target->buffer[iter->cursor]; \ - } \ - \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->target->buffer[iter->cursor]); \ - } \ - \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - static bool PFX##_impl_grow(SNAME *_queue_) \ - { \ - \ - size_t new_capacity = _queue_->capacity * 2; \ - \ - V *new_buffer = malloc(sizeof(V) * new_capacity); \ - \ - if (!new_buffer) \ - return false; \ - \ - for (size_t i = _queue_->front, j = 0; j < _queue_->count; i = (i + 1) % _queue_->capacity, j++) \ - { \ - new_buffer[j] = _queue_->buffer[i]; \ - } \ - \ - free(_queue_->buffer); \ - \ - _queue_->buffer = new_buffer; \ - _queue_->capacity = new_capacity; \ - _queue_->front = 0; \ - _queue_->back = _queue_->count; \ - \ - return true; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_queue_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _queue_); \ - PFX##_iter_to_start(&iter); \ - \ - return iter; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_queue_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _queue_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ +#define QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ + \ + /* Implementation Detail Functions */ \ + static bool PFX##_impl_grow(SNAME *_queue_); \ + static SNAME##_iter PFX##_impl_it_start(SNAME *_queue_); \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_queue_); \ + \ + FMOD SNAME *PFX##_new(size_t capacity) \ + { \ + if (capacity < 1) \ + return NULL; \ + \ + SNAME *_queue_ = malloc(sizeof(SNAME)); \ + \ + if (!_queue_) \ + return NULL; \ + \ + _queue_->buffer = malloc(sizeof(V) * capacity); \ + \ + if (!_queue_->buffer) \ + { \ + free(_queue_); \ + return NULL; \ + } \ + \ + memset(_queue_->buffer, 0, sizeof(V) * capacity); \ + \ + _queue_->capacity = capacity; \ + _queue_->count = 0; \ + _queue_->front = 0; \ + _queue_->back = 0; \ + \ + _queue_->it_start = PFX##_impl_it_start; \ + _queue_->it_end = PFX##_impl_it_end; \ + \ + return _queue_; \ + } \ + \ + FMOD void PFX##_clear(SNAME *_queue_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = _queue_->front, j = 0; j < _queue_->count; i = (i + 1) % _queue_->capacity, j++) \ + { \ + deallocator(_queue_->buffer[i]); \ + } \ + } \ + \ + memset(_queue_->buffer, 0, sizeof(V) * _queue_->capacity); \ + \ + _queue_->count = 0; \ + _queue_->front = 0; \ + _queue_->back = 0; \ + } \ + \ + FMOD void PFX##_free(SNAME *_queue_, void (*deallocator)(V)) \ + { \ + if (deallocator) \ + { \ + for (size_t i = _queue_->front, j = 0; j < _queue_->count; i = (i + 1) % _queue_->capacity, j++) \ + { \ + deallocator(_queue_->buffer[i]); \ + } \ + } \ + \ + free(_queue_->buffer); \ + free(_queue_); \ + } \ + \ + FMOD bool PFX##_enqueue(SNAME *_queue_, V element) \ + { \ + if (PFX##_full(_queue_)) \ + { \ + if (!PFX##_impl_grow(_queue_)) \ + return false; \ + } \ + \ + _queue_->buffer[_queue_->back] = element; \ + \ + _queue_->back = (_queue_->back == _queue_->capacity - 1) ? 0 : _queue_->back + 1; \ + _queue_->count++; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_dequeue(SNAME *_queue_) \ + { \ + if (PFX##_empty(_queue_)) \ + return false; \ + \ + _queue_->buffer[_queue_->front] = PFX##_impl_default_value(); \ + \ + _queue_->front = (_queue_->front == _queue_->capacity - 1) ? 0 : _queue_->front + 1; \ + _queue_->count--; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_enqueue_if(SNAME *_queue_, V element, bool condition) \ + { \ + if (condition) \ + return PFX##_enqueue(_queue_, element); \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_dequeue_if(SNAME *_queue_, bool condition) \ + { \ + if (condition) \ + return PFX##_dequeue(_queue_); \ + \ + return false; \ + } \ + \ + FMOD V PFX##_peek(SNAME *_queue_) \ + { \ + if (PFX##_empty(_queue_)) \ + return PFX##_impl_default_value(); \ + \ + return _queue_->buffer[_queue_->front]; \ + } \ + \ + FMOD bool PFX##_contains(SNAME *_queue_, V element, int (*comparator)(V, V)) \ + { \ + for (size_t i = _queue_->front, j = 0; j < _queue_->count; i = (i + 1) % _queue_->count, j++) \ + { \ + if (comparator(_queue_->buffer[i], element) == 0) \ + return true; \ + } \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_empty(SNAME *_queue_) \ + { \ + return _queue_->count == 0; \ + } \ + \ + FMOD bool PFX##_full(SNAME *_queue_) \ + { \ + return _queue_->count >= _queue_->capacity; \ + } \ + \ + FMOD size_t PFX##_count(SNAME *_queue_) \ + { \ + return _queue_->count; \ + } \ + \ + FMOD size_t PFX##_capacity(SNAME *_queue_) \ + { \ + return _queue_->capacity; \ + } \ + \ + FMOD cmc_string PFX##_to_string(SNAME *_queue_) \ + { \ + cmc_string str; \ + SNAME *q_ = _queue_; \ + const char *name = #SNAME; \ + \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_queue, \ + name, q_, q_->buffer, q_->capacity, q_->count, q_->front, q_->back); \ + \ + return str; \ + } \ + \ + FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ + { \ + SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + FMOD void PFX##_iter_free(SNAME##_iter *iter) \ + { \ + free(iter); \ + } \ + \ + FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + { \ + iter->target = target; \ + iter->cursor = target->front; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + } \ + \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ + { \ + iter->cursor = iter->target->front; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ + \ + FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + iter->cursor = 0; \ + else \ + iter->cursor = (iter->target->back == 0) ? iter->target->capacity - 1 : iter->target->back - 1; \ + \ + iter->index = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + } \ + \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ + { \ + if (iter->end) \ + return false; \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + if (iter->index == iter->target->count - 1) \ + iter->end = true; \ + else \ + { \ + iter->cursor = (iter->cursor + 1) % (iter->target->capacity); \ + iter->index++; \ + } \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + if (iter->index == 0) \ + iter->start = true; \ + else \ + { \ + iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; \ + iter->index--; \ + } \ + \ + return true; \ + } \ + \ + FMOD V PFX##_iter_value(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return PFX##_impl_default_value(); \ + \ + return iter->target->buffer[iter->cursor]; \ + } \ + \ + FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return NULL; \ + \ + return &(iter->target->buffer[iter->cursor]); \ + } \ + \ + FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + static bool PFX##_impl_grow(SNAME *_queue_) \ + { \ + \ + size_t new_capacity = _queue_->capacity * 2; \ + \ + V *new_buffer = malloc(sizeof(V) * new_capacity); \ + \ + if (!new_buffer) \ + return false; \ + \ + for (size_t i = _queue_->front, j = 0; j < _queue_->count; i = (i + 1) % _queue_->capacity, j++) \ + { \ + new_buffer[j] = _queue_->buffer[i]; \ + } \ + \ + free(_queue_->buffer); \ + \ + _queue_->buffer = new_buffer; \ + _queue_->capacity = new_capacity; \ + _queue_->front = 0; \ + _queue_->back = _queue_->count; \ + \ + return true; \ + } \ + \ + static SNAME##_iter PFX##_impl_it_start(SNAME *_queue_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _queue_); \ + PFX##_iter_to_start(&iter); \ + \ + return iter; \ + } \ + \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_queue_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _queue_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_QUEUE_H */ diff --git a/src/cmc/stack.h b/src/cmc/stack.h index a33e596..8871fc1 100644 --- a/src/cmc/stack.h +++ b/src/cmc/stack.h @@ -87,8 +87,8 @@ /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ FMOD SNAME *PFX##_new(size_t capacity); \ - FMOD void PFX##_clear(SNAME *_stack_); \ - FMOD void PFX##_free(SNAME *_stack_); \ + FMOD void PFX##_clear(SNAME *_stack_, void (*deallocator)(V)); \ + FMOD void PFX##_free(SNAME *_stack_, void (*deallocator)(V)); \ /* Collection Input and Output */ \ FMOD bool PFX##_push(SNAME *_stack_, V element); \ FMOD bool PFX##_pop(SNAME *_stack_); \ @@ -172,16 +172,28 @@ return _stack_; \ } \ \ - FMOD void PFX##_clear(SNAME *_stack_) \ + FMOD void PFX##_clear(SNAME *_stack_, void (*deallocator)(V)) \ { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _stack_->count; i++) \ + deallocator(_stack_->buffer[i]); \ + } \ + \ memset(_stack_->buffer, 0, sizeof(V) * _stack_->capacity); \ \ _stack_->count = 0; \ } \ \ - FMOD void PFX##_free(SNAME *_stack_) \ + FMOD void PFX##_free(SNAME *_stack_, void (*deallocator)(V)) \ { \ free(_stack_->buffer); \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _stack_->count; i++) \ + deallocator(_stack_->buffer[i]); \ + } \ + \ free(_stack_); \ } \ \ diff --git a/src/cmc/treemap.h b/src/cmc/treemap.h index c076731..aa5c083 100644 --- a/src/cmc/treemap.h +++ b/src/cmc/treemap.h @@ -36,895 +36,901 @@ TREEMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) /* HEADER ********************************************************************/ -#define TREEMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \ - \ - /* Treemap Structure */ \ - typedef struct SNAME##_s \ - { \ - /* Root node */ \ - struct SNAME##_node_s *root; \ - \ - /* Current amount of keys */ \ - size_t count; \ - \ - /* Key comparison function */ \ - int (*cmp)(K, K); \ - \ - /* Function that returns an iterator to the start of the treemap */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - /* Function that returns an iterator to the end of the treemap */ \ - struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Treemap Node */ \ - typedef struct SNAME##_node_s \ - { \ - /* Node Key */ \ - K key; \ - \ - /* Node Value */ \ - V value; \ - \ - /* Node height used by the AVL tree to keep it strictly balanced */ \ - unsigned char height; \ - \ - /* Right child node or subtree */ \ - struct SNAME##_node_s *right; \ - \ - /* Left child node or subtree */ \ - struct SNAME##_node_s *left; \ - \ - /* Parent node */ \ - struct SNAME##_node_s *parent; \ - \ - } SNAME##_node, *SNAME##_node_ptr; \ - \ - /* Treemap Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target treemap */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's current node */ \ - struct SNAME##_node_s *cursor; \ - \ - /* The first node in the iteration */ \ - struct SNAME##_node_s *first; \ - \ - /* The last node in the iteration */ \ - struct SNAME##_node_s *last; \ - \ - /* 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; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - FMOD SNAME *PFX##_new(int (*compare)(K, K)); \ - FMOD void PFX##_clear(SNAME *_map_); \ - FMOD void PFX##_free(SNAME *_map_); \ - /* Collection Input and Output */ \ - FMOD bool PFX##_insert(SNAME *_map_, K key, V value); \ - FMOD bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value); \ - FMOD bool PFX##_remove(SNAME *_map_, K key, V *value); \ - /* Conditional Input and Output */ \ - FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition); \ - FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition); \ - /* Element Access */ \ - FMOD bool PFX##_max(SNAME *_map_, K *key, V *value); \ - FMOD bool PFX##_min(SNAME *_map_, K *key, V *value); \ - FMOD V PFX##_get(SNAME *_map_, K key); \ - FMOD V *PFX##_get_ref(SNAME *_map_, K key); \ - FMOD bool PFX##_set(SNAME *_map_, K key, V new_value); \ - /* Collection State */ \ - FMOD bool PFX##_contains(SNAME *_map_, K key); \ - FMOD bool PFX##_empty(SNAME *_map_); \ - FMOD size_t PFX##_count(SNAME *_map_); \ - /* Collection Utility */ \ - FMOD cmc_string PFX##_to_string(SNAME *_map_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ - FMOD void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ - /* Iterator Access */ \ - FMOD K PFX##_iter_key(SNAME##_iter *iter); \ - FMOD V PFX##_iter_value(SNAME##_iter *iter); \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ - /* Default Key */ \ - static inline K PFX##_impl_default_key(void) \ - { \ - K _empty_key_; \ - \ - memset(&_empty_key_, 0, sizeof(K)); \ - \ - return _empty_key_; \ - } \ - \ - /* Default Value */ \ - static inline V PFX##_impl_default_value(void) \ - { \ - V _empty_value_; \ - \ - memset(&_empty_value_, 0, sizeof(V)); \ - \ - return _empty_value_; \ - } \ - \ +#define TREEMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \ + \ + /* Treemap Structure */ \ + typedef struct SNAME##_s \ + { \ + /* Root node */ \ + struct SNAME##_node_s *root; \ + \ + /* Current amount of keys */ \ + size_t count; \ + \ + /* Key comparison function */ \ + int (*cmp)(K, K); \ + \ + /* Function that returns an iterator to the start of the treemap */ \ + struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ + \ + /* Function that returns an iterator to the end of the treemap */ \ + struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \ + \ + } SNAME, *SNAME##_ptr; \ + \ + /* Treemap Node */ \ + typedef struct SNAME##_node_s \ + { \ + /* Node Key */ \ + K key; \ + \ + /* Node Value */ \ + V value; \ + \ + /* Node height used by the AVL tree to keep it strictly balanced */ \ + unsigned char height; \ + \ + /* Right child node or subtree */ \ + struct SNAME##_node_s *right; \ + \ + /* Left child node or subtree */ \ + struct SNAME##_node_s *left; \ + \ + /* Parent node */ \ + struct SNAME##_node_s *parent; \ + \ + } SNAME##_node, *SNAME##_node_ptr; \ + \ + /* Treemap Iterator */ \ + typedef struct SNAME##_iter_s \ + { \ + /* Target treemap */ \ + struct SNAME##_s *target; \ + \ + /* Cursor's current node */ \ + struct SNAME##_node_s *cursor; \ + \ + /* The first node in the iteration */ \ + struct SNAME##_node_s *first; \ + \ + /* The last node in the iteration */ \ + struct SNAME##_node_s *last; \ + \ + /* 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; \ + \ + } SNAME##_iter, *SNAME##_iter_ptr; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + FMOD SNAME *PFX##_new(int (*compare)(K, K)); \ + FMOD void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)); \ + FMOD void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)); \ + /* Collection Input and Output */ \ + FMOD bool PFX##_insert(SNAME *_map_, K key, V value); \ + FMOD bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value); \ + FMOD bool PFX##_remove(SNAME *_map_, K key, V *value); \ + /* Conditional Input and Output */ \ + FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition); \ + FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition); \ + /* Element Access */ \ + FMOD bool PFX##_max(SNAME *_map_, K *key, V *value); \ + FMOD bool PFX##_min(SNAME *_map_, K *key, V *value); \ + FMOD V PFX##_get(SNAME *_map_, K key); \ + FMOD V *PFX##_get_ref(SNAME *_map_, K key); \ + FMOD bool PFX##_set(SNAME *_map_, K key, V new_value); \ + /* Collection State */ \ + FMOD bool PFX##_contains(SNAME *_map_, K key); \ + FMOD bool PFX##_empty(SNAME *_map_); \ + FMOD size_t PFX##_count(SNAME *_map_); \ + /* Collection Utility */ \ + FMOD cmc_string PFX##_to_string(SNAME *_map_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ + FMOD void PFX##_iter_free(SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ + /* Iterator State */ \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ + /* Iterator Movement */ \ + FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ + FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ + /* Iterator Access */ \ + FMOD K PFX##_iter_key(SNAME##_iter *iter); \ + FMOD V PFX##_iter_value(SNAME##_iter *iter); \ + FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \ + FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ + \ + /* Default Key */ \ + static inline K PFX##_impl_default_key(void) \ + { \ + K _empty_key_; \ + \ + memset(&_empty_key_, 0, sizeof(K)); \ + \ + return _empty_key_; \ + } \ + \ + /* Default Value */ \ + static inline V PFX##_impl_default_value(void) \ + { \ + V _empty_value_; \ + \ + memset(&_empty_value_, 0, sizeof(V)); \ + \ + return _empty_value_; \ + } \ + \ /* SOURCE ********************************************************************/ -#define TREEMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) \ - \ - /* Implementation Detail Functions */ \ - static SNAME##_node *PFX##_impl_new_node(K key, V value); \ - static SNAME##_node *PFX##_impl_get_node(SNAME *_map_, K key); \ - static unsigned char PFX##_impl_h(SNAME##_node *node); \ - static unsigned char PFX##_impl_hupdate(SNAME##_node *node); \ - static void PFX##_impl_rotate_right(SNAME##_node **Z); \ - static void PFX##_impl_rotate_left(SNAME##_node **Z); \ - static void PFX##_impl_rebalance(SNAME *_map_, SNAME##_node *node); \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_map_); \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_map_); \ - \ - FMOD SNAME *PFX##_new(int (*compare)(K, K)) \ - { \ - SNAME *_map_ = malloc(sizeof(SNAME)); \ - \ - if (!_map_) \ - return NULL; \ - \ - _map_->count = 0; \ - _map_->root = NULL; \ - _map_->cmp = compare; \ - \ - _map_->it_start = PFX##_impl_it_start; \ - _map_->it_end = PFX##_impl_it_end; \ - \ - return _map_; \ - } \ - \ - FMOD void PFX##_clear(SNAME *_map_) \ - { \ - SNAME##_node *scan = _map_->root; \ - SNAME##_node *up = NULL; \ - \ - while (scan != NULL) \ - { \ - if (scan->left != NULL) \ - { \ - SNAME##_node *left = scan->left; \ - \ - scan->left = up; \ - up = scan; \ - scan = left; \ - } \ - else if (scan->right != NULL) \ - { \ - SNAME##_node *right = scan->right; \ - \ - scan->left = up; \ - scan->right = NULL; \ - up = scan; \ - scan = right; \ - } \ - else \ - { \ - if (up == NULL) \ - { \ - free(scan); \ - scan = NULL; \ - } \ - \ - while (up != NULL) \ - { \ - free(scan); \ - \ - if (up->right != NULL) \ - { \ - scan = up->right; \ - up->right = NULL; \ - break; \ - } \ - else \ - { \ - scan = up; \ - up = up->left; \ - } \ - } \ - } \ - } \ - \ - _map_->count = 0; \ - _map_->root = NULL; \ - } \ - \ - FMOD void PFX##_free(SNAME *_map_) \ - { \ - PFX##_clear(_map_); \ - \ - free(_map_); \ - } \ - \ - FMOD bool PFX##_insert(SNAME *_map_, K key, V value) \ - { \ - if (PFX##_empty(_map_)) \ - { \ - _map_->root = PFX##_impl_new_node(key, value); \ - \ - if (!_map_->root) \ - return false; \ - } \ - else \ - { \ - SNAME##_node *scan = _map_->root; \ - SNAME##_node *parent = scan; \ - \ - while (scan != NULL) \ - { \ - parent = scan; \ - \ - if (_map_->cmp(scan->key, key) > 0) \ - scan = scan->left; \ - else if (_map_->cmp(scan->key, key) < 0) \ - scan = scan->right; \ - else \ - return false; \ - } \ - \ - SNAME##_node *node; \ - \ - if (_map_->cmp(parent->key, key) > 0) \ - { \ - parent->left = PFX##_impl_new_node(key, value); \ - \ - if (!parent->left) \ - return false; \ - \ - parent->left->parent = parent; \ - node = parent->left; \ - } \ - else \ - { \ - parent->right = PFX##_impl_new_node(key, value); \ - \ - if (!parent->right) \ - return false; \ - \ - parent->right->parent = parent; \ - node = parent->right; \ - } \ - \ - PFX##_impl_rebalance(_map_, node); \ - } \ - \ - _map_->count++; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value) \ - { \ - SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ - \ - if (!node) \ - return false; \ - \ - *old_value = node->value; \ - node->value = new_value; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_remove(SNAME *_map_, K key, V *value) \ - { \ - SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ - \ - if (!node) \ - return false; \ - \ - *value = node->value; \ - \ - SNAME##_node *temp = NULL, *unbalanced = NULL; \ - \ - bool is_root = node->parent == NULL; \ - \ - if (node->left == NULL && node->right == NULL) \ - { \ - if (is_root) \ - _map_->root = NULL; \ - else \ - { \ - unbalanced = node->parent; \ - \ - if (node->parent->right == node) \ - node->parent->right = NULL; \ - else \ - node->parent->left = NULL; \ - } \ - \ - free(node); \ - } \ - else if (node->left == NULL) \ - { \ - if (is_root) \ - { \ - _map_->root = node->right; \ - _map_->root->parent = NULL; \ - } \ - else \ - { \ - unbalanced = node->parent; \ - \ - node->right->parent = node->parent; \ - \ - if (node->parent->right == node) \ - node->parent->right = node->right; \ - else \ - node->parent->left = node->right; \ - } \ - \ - free(node); \ - } \ - else if (node->right == NULL) \ - { \ - if (is_root) \ - { \ - _map_->root = node->left; \ - _map_->root->parent = NULL; \ - } \ - else \ - { \ - unbalanced = node->parent; \ - \ - node->left->parent = node->parent; \ - \ - if (node->parent->right == node) \ - node->parent->right = node->left; \ - else \ - node->parent->left = node->left; \ - } \ - \ - free(node); \ - } \ - else \ - { \ - temp = node->right; \ - while (temp->left != NULL) \ - temp = temp->left; \ - \ - K temp_key = temp->key; \ - V temp_val = temp->value; \ - \ - unbalanced = temp->parent; \ - \ - if (temp->left == NULL && temp->right == NULL) \ - { \ - if (temp->parent->right == temp) \ - temp->parent->right = NULL; \ - else \ - temp->parent->left = NULL; \ - } \ - else if (temp->left == NULL) \ - { \ - temp->right->parent = temp->parent; \ - \ - if (temp->parent->right == temp) \ - temp->parent->right = temp->right; \ - else \ - temp->parent->left = temp->right; \ - } \ - else if (temp->right == NULL) \ - { \ - temp->left->parent = temp->parent; \ - \ - if (temp->parent->right == temp) \ - temp->parent->right = temp->left; \ - else \ - temp->parent->left = temp->left; \ - } \ - \ - free(temp); \ - \ - node->key = temp_key; \ - node->value = temp_val; \ - } \ - \ - if (unbalanced != NULL) \ - PFX##_impl_rebalance(_map_, unbalanced); \ - \ - _map_->count--; \ - \ - if (_map_->count == 0) \ - _map_->root = NULL; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition) \ - { \ - if (condition) \ - return PFX##_insert(_map_, key, value); \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition) \ - { \ - if (condition) \ - return PFX##_remove(_map_, key, value); \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_max(SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - SNAME##_node *scan = _map_->root; \ - \ - while (scan->right != NULL) \ - scan = scan->right; \ - \ - *key = scan->key; \ - *value = scan->value; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_min(SNAME *_map_, K *key, V *value) \ - { \ - if (PFX##_empty(_map_)) \ - return false; \ - \ - SNAME##_node *scan = _map_->root; \ - \ - while (scan->left != NULL) \ - scan = scan->left; \ - \ - *key = scan->key; \ - *value = scan->value; \ - \ - return true; \ - } \ - \ - FMOD V PFX##_get(SNAME *_map_, K key) \ - { \ - SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ - \ - if (!node) \ - return PFX##_impl_default_value(); \ - \ - return node->value; \ - } \ - \ - FMOD V *PFX##_get_ref(SNAME *_map_, K key) \ - { \ - SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ - \ - if (!node) \ - return NULL; \ - \ - return &(node->value); \ - } \ - \ - FMOD bool PFX##_set(SNAME *_map_, K key, V new_value) \ - { \ - SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ - \ - if (!node) \ - return false; \ - \ - node->value = new_value; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_contains(SNAME *_map_, K key) \ - { \ - SNAME##_node *scan = _map_->root; \ - \ - while (scan != NULL) \ - { \ - if (_map_->cmp(scan->key, key) > 0) \ - scan = scan->left; \ - else if (_map_->cmp(scan->key, key) < 0) \ - scan = scan->right; \ - else \ - return true; \ - } \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_empty(SNAME *_map_) \ - { \ - return _map_->count == 0; \ - } \ - \ - FMOD size_t PFX##_count(SNAME *_map_) \ - { \ - return _map_->count; \ - } \ - \ - FMOD cmc_string PFX##_to_string(SNAME *_map_) \ - { \ - cmc_string str; \ - SNAME *m_ = _map_; \ - const char *name = #SNAME; \ - \ - snprintf(str.s, cmc_string_len, cmc_string_fmt_treemap, \ - name, m_, m_->root, m_->count, m_->cmp); \ - \ - return str; \ - } \ - \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ - { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - FMOD void PFX##_iter_free(SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ - { \ - iter->target = target; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - \ - iter->cursor = target->root; \ - while (iter->cursor->left != NULL) \ - iter->cursor = iter->cursor->left; \ - \ - iter->first = iter->cursor; \ - \ - iter->last = target->root; \ - while (iter->last->right != NULL) \ - iter->last = iter->last->right; \ - } \ - \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ - { \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - \ - iter->cursor = iter->first; \ - } \ - \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ - { \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - \ - iter->cursor = iter->last; \ - } \ - \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - iter->start = false; \ - \ - if (iter->cursor->right != NULL) \ - { \ - iter->cursor = iter->cursor->right; \ - while (iter->cursor->left != NULL) \ - iter->cursor = iter->cursor->left; \ - \ - iter->index++; \ - \ - return true; \ - } \ - \ - while (true) \ - { \ - if (iter->cursor == iter->last) \ - { \ - iter->end = true; \ - \ - return true; \ - } \ - if (iter->cursor->parent->left == iter->cursor) \ - { \ - iter->cursor = iter->cursor->parent; \ - \ - iter->index++; \ - \ - return true; \ - } \ - \ - iter->cursor = iter->cursor->parent; \ - } \ - } \ - \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ - { \ - if (iter->start) \ - return false; \ - \ - iter->end = false; \ - \ - if (iter->cursor->left != NULL) \ - { \ - iter->cursor = iter->cursor->left; \ - \ - while (iter->cursor->right != NULL) \ - iter->cursor = iter->cursor->right; \ - \ - iter->index--; \ - \ - return true; \ - } \ - \ - while (true) \ - { \ - if (iter->cursor == iter->first) \ - { \ - iter->start = true; \ - \ - return true; \ - } \ - if (iter->cursor->parent->right == iter->cursor) \ - { \ - iter->cursor = iter->cursor->parent; \ - \ - iter->index--; \ - \ - return true; \ - } \ - \ - iter->cursor = iter->cursor->parent; \ - } \ - } \ - \ - FMOD K PFX##_iter_key(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return PFX##_impl_default_key(); \ - \ - return iter->cursor->key; \ - } \ - \ - FMOD V PFX##_iter_value(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return PFX##_impl_default_value(); \ - \ - return iter->cursor->value; \ - } \ - \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->cursor->value); \ - } \ - \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - static SNAME##_node *PFX##_impl_new_node(K key, V value) \ - { \ - SNAME##_node *node = malloc(sizeof(SNAME##_node)); \ - \ - if (!node) \ - return NULL; \ - \ - node->key = key; \ - node->value = value; \ - node->right = NULL; \ - node->left = NULL; \ - node->parent = NULL; \ - node->height = 0; \ - \ - return node; \ - } \ - \ - static SNAME##_node *PFX##_impl_get_node(SNAME *_map_, K key) \ - { \ - if (PFX##_empty(_map_)) \ - return NULL; \ - \ - SNAME##_node *scan = _map_->root; \ - \ - while (scan != NULL) \ - { \ - if (_map_->cmp(scan->key, key) > 0) \ - scan = scan->left; \ - else if (_map_->cmp(scan->key, key) < 0) \ - scan = scan->right; \ - else \ - return scan; \ - } \ - \ - return NULL; \ - } \ - \ - static unsigned char PFX##_impl_h(SNAME##_node *node) \ - { \ - if (node == NULL) \ - return 0; \ - \ - return node->height; \ - } \ - \ - static unsigned char PFX##_impl_hupdate(SNAME##_node *node) \ - { \ - if (node == NULL) \ - return 0; \ - \ - unsigned char h_l = PFX##_impl_h(node->left); \ - unsigned char h_r = PFX##_impl_h(node->right); \ - \ - return 1 + (h_l > h_r ? h_l : h_r); \ - } \ - \ - static void PFX##_impl_rotate_right(SNAME##_node **Z) \ - { \ - SNAME##_node *root = *Z; \ - SNAME##_node *new_root = root->left; \ - \ - if (root->parent != NULL) \ - { \ - if (root->parent->left == root) \ - root->parent->left = new_root; \ - else \ - root->parent->right = new_root; \ - } \ - \ - new_root->parent = root->parent; \ - \ - root->parent = new_root; \ - root->left = new_root->right; \ - \ - if (root->left) \ - root->left->parent = root; \ - \ - new_root->right = root; \ - \ - root->height = PFX##_impl_hupdate(root); \ - new_root->height = PFX##_impl_hupdate(new_root); \ - \ - *Z = new_root; \ - } \ - \ - static void PFX##_impl_rotate_left(SNAME##_node **Z) \ - { \ - SNAME##_node *root = *Z; \ - SNAME##_node *new_root = root->right; \ - \ - if (root->parent != NULL) \ - { \ - if (root->parent->right == root) \ - root->parent->right = new_root; \ - else \ - root->parent->left = new_root; \ - } \ - \ - new_root->parent = root->parent; \ - \ - root->parent = new_root; \ - root->right = new_root->left; \ - \ - if (root->right) \ - root->right->parent = root; \ - \ - new_root->left = root; \ - \ - root->height = PFX##_impl_hupdate(root); \ - new_root->height = PFX##_impl_hupdate(new_root); \ - \ - *Z = new_root; \ - } \ - \ - static void PFX##_impl_rebalance(SNAME *_map_, SNAME##_node *node) \ - { \ - SNAME##_node *scan = node, *child = NULL; \ - \ - int balance; \ - bool is_root = false; \ - \ - while (scan != NULL) \ - { \ - if (scan->parent == NULL) \ - is_root = true; \ - \ - scan->height = PFX##_impl_hupdate(scan); \ - balance = PFX##_impl_h(scan->right) - PFX##_impl_h(scan->left); \ - \ - if (balance >= 2) \ - { \ - child = scan->right; \ - \ - if (PFX##_impl_h(child->right) < PFX##_impl_h(child->left)) \ - PFX##_impl_rotate_right(&(scan->right)); \ - \ - PFX##_impl_rotate_left(&scan); \ - } \ - else if (balance <= -2) \ - { \ - child = scan->left; \ - \ - if (PFX##_impl_h(child->left) < PFX##_impl_h(child->right)) \ - PFX##_impl_rotate_left(&(scan->left)); \ - \ - PFX##_impl_rotate_right(&scan); \ - } \ - \ - if (is_root) \ - { \ - _map_->root = scan; \ - is_root = false; \ - } \ - \ - scan = scan->parent; \ - } \ - } \ - \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_map_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _map_); \ - \ - return iter; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_end(SNAME *_map_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _map_); \ - PFX##_iter_to_end(&iter); \ - \ - return iter; \ +#define TREEMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) \ + \ + /* Implementation Detail Functions */ \ + static SNAME##_node *PFX##_impl_new_node(K key, V value); \ + static SNAME##_node *PFX##_impl_get_node(SNAME *_map_, K key); \ + static unsigned char PFX##_impl_h(SNAME##_node *node); \ + static unsigned char PFX##_impl_hupdate(SNAME##_node *node); \ + static void PFX##_impl_rotate_right(SNAME##_node **Z); \ + static void PFX##_impl_rotate_left(SNAME##_node **Z); \ + static void PFX##_impl_rebalance(SNAME *_map_, SNAME##_node *node); \ + static SNAME##_iter PFX##_impl_it_start(SNAME *_map_); \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_map_); \ + \ + FMOD SNAME *PFX##_new(int (*compare)(K, K)) \ + { \ + SNAME *_map_ = malloc(sizeof(SNAME)); \ + \ + if (!_map_) \ + return NULL; \ + \ + _map_->count = 0; \ + _map_->root = NULL; \ + _map_->cmp = compare; \ + \ + _map_->it_start = PFX##_impl_it_start; \ + _map_->it_end = PFX##_impl_it_end; \ + \ + return _map_; \ + } \ + \ + FMOD void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)) \ + { \ + SNAME##_node *scan = _map_->root; \ + SNAME##_node *up = NULL; \ + \ + while (scan != NULL) \ + { \ + if (scan->left != NULL) \ + { \ + SNAME##_node *left = scan->left; \ + \ + scan->left = up; \ + up = scan; \ + scan = left; \ + } \ + else if (scan->right != NULL) \ + { \ + SNAME##_node *right = scan->right; \ + \ + scan->left = up; \ + scan->right = NULL; \ + up = scan; \ + scan = right; \ + } \ + else \ + { \ + if (up == NULL) \ + { \ + if (deallocator) \ + deallocator(scan->key, scan->value); \ + \ + free(scan); \ + scan = NULL; \ + } \ + \ + while (up != NULL) \ + { \ + if (deallocator) \ + deallocator(scan->key, scan->value); \ + \ + free(scan); \ + \ + if (up->right != NULL) \ + { \ + scan = up->right; \ + up->right = NULL; \ + break; \ + } \ + else \ + { \ + scan = up; \ + up = up->left; \ + } \ + } \ + } \ + } \ + \ + _map_->count = 0; \ + _map_->root = NULL; \ + } \ + \ + FMOD void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)) \ + { \ + PFX##_clear(_map_, deallocator); \ + \ + free(_map_); \ + } \ + \ + FMOD bool PFX##_insert(SNAME *_map_, K key, V value) \ + { \ + if (PFX##_empty(_map_)) \ + { \ + _map_->root = PFX##_impl_new_node(key, value); \ + \ + if (!_map_->root) \ + return false; \ + } \ + else \ + { \ + SNAME##_node *scan = _map_->root; \ + SNAME##_node *parent = scan; \ + \ + while (scan != NULL) \ + { \ + parent = scan; \ + \ + if (_map_->cmp(scan->key, key) > 0) \ + scan = scan->left; \ + else if (_map_->cmp(scan->key, key) < 0) \ + scan = scan->right; \ + else \ + return false; \ + } \ + \ + SNAME##_node *node; \ + \ + if (_map_->cmp(parent->key, key) > 0) \ + { \ + parent->left = PFX##_impl_new_node(key, value); \ + \ + if (!parent->left) \ + return false; \ + \ + parent->left->parent = parent; \ + node = parent->left; \ + } \ + else \ + { \ + parent->right = PFX##_impl_new_node(key, value); \ + \ + if (!parent->right) \ + return false; \ + \ + parent->right->parent = parent; \ + node = parent->right; \ + } \ + \ + PFX##_impl_rebalance(_map_, node); \ + } \ + \ + _map_->count++; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value) \ + { \ + SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ + \ + if (!node) \ + return false; \ + \ + *old_value = node->value; \ + node->value = new_value; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_remove(SNAME *_map_, K key, V *value) \ + { \ + SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ + \ + if (!node) \ + return false; \ + \ + *value = node->value; \ + \ + SNAME##_node *temp = NULL, *unbalanced = NULL; \ + \ + bool is_root = node->parent == NULL; \ + \ + if (node->left == NULL && node->right == NULL) \ + { \ + if (is_root) \ + _map_->root = NULL; \ + else \ + { \ + unbalanced = node->parent; \ + \ + if (node->parent->right == node) \ + node->parent->right = NULL; \ + else \ + node->parent->left = NULL; \ + } \ + \ + free(node); \ + } \ + else if (node->left == NULL) \ + { \ + if (is_root) \ + { \ + _map_->root = node->right; \ + _map_->root->parent = NULL; \ + } \ + else \ + { \ + unbalanced = node->parent; \ + \ + node->right->parent = node->parent; \ + \ + if (node->parent->right == node) \ + node->parent->right = node->right; \ + else \ + node->parent->left = node->right; \ + } \ + \ + free(node); \ + } \ + else if (node->right == NULL) \ + { \ + if (is_root) \ + { \ + _map_->root = node->left; \ + _map_->root->parent = NULL; \ + } \ + else \ + { \ + unbalanced = node->parent; \ + \ + node->left->parent = node->parent; \ + \ + if (node->parent->right == node) \ + node->parent->right = node->left; \ + else \ + node->parent->left = node->left; \ + } \ + \ + free(node); \ + } \ + else \ + { \ + temp = node->right; \ + while (temp->left != NULL) \ + temp = temp->left; \ + \ + K temp_key = temp->key; \ + V temp_val = temp->value; \ + \ + unbalanced = temp->parent; \ + \ + if (temp->left == NULL && temp->right == NULL) \ + { \ + if (temp->parent->right == temp) \ + temp->parent->right = NULL; \ + else \ + temp->parent->left = NULL; \ + } \ + else if (temp->left == NULL) \ + { \ + temp->right->parent = temp->parent; \ + \ + if (temp->parent->right == temp) \ + temp->parent->right = temp->right; \ + else \ + temp->parent->left = temp->right; \ + } \ + else if (temp->right == NULL) \ + { \ + temp->left->parent = temp->parent; \ + \ + if (temp->parent->right == temp) \ + temp->parent->right = temp->left; \ + else \ + temp->parent->left = temp->left; \ + } \ + \ + free(temp); \ + \ + node->key = temp_key; \ + node->value = temp_val; \ + } \ + \ + if (unbalanced != NULL) \ + PFX##_impl_rebalance(_map_, unbalanced); \ + \ + _map_->count--; \ + \ + if (_map_->count == 0) \ + _map_->root = NULL; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition) \ + { \ + if (condition) \ + return PFX##_insert(_map_, key, value); \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition) \ + { \ + if (condition) \ + return PFX##_remove(_map_, key, value); \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_max(SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + SNAME##_node *scan = _map_->root; \ + \ + while (scan->right != NULL) \ + scan = scan->right; \ + \ + *key = scan->key; \ + *value = scan->value; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_min(SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + SNAME##_node *scan = _map_->root; \ + \ + while (scan->left != NULL) \ + scan = scan->left; \ + \ + *key = scan->key; \ + *value = scan->value; \ + \ + return true; \ + } \ + \ + FMOD V PFX##_get(SNAME *_map_, K key) \ + { \ + SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ + \ + if (!node) \ + return PFX##_impl_default_value(); \ + \ + return node->value; \ + } \ + \ + FMOD V *PFX##_get_ref(SNAME *_map_, K key) \ + { \ + SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ + \ + if (!node) \ + return NULL; \ + \ + return &(node->value); \ + } \ + \ + FMOD bool PFX##_set(SNAME *_map_, K key, V new_value) \ + { \ + SNAME##_node *node = PFX##_impl_get_node(_map_, key); \ + \ + if (!node) \ + return false; \ + \ + node->value = new_value; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_contains(SNAME *_map_, K key) \ + { \ + SNAME##_node *scan = _map_->root; \ + \ + while (scan != NULL) \ + { \ + if (_map_->cmp(scan->key, key) > 0) \ + scan = scan->left; \ + else if (_map_->cmp(scan->key, key) < 0) \ + scan = scan->right; \ + else \ + return true; \ + } \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_empty(SNAME *_map_) \ + { \ + return _map_->count == 0; \ + } \ + \ + FMOD size_t PFX##_count(SNAME *_map_) \ + { \ + return _map_->count; \ + } \ + \ + FMOD cmc_string PFX##_to_string(SNAME *_map_) \ + { \ + cmc_string str; \ + SNAME *m_ = _map_; \ + const char *name = #SNAME; \ + \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_treemap, \ + name, m_, m_->root, m_->count, m_->cmp); \ + \ + return str; \ + } \ + \ + FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ + { \ + SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ + \ + if (!iter) \ + return NULL; \ + \ + PFX##_iter_init(iter, target); \ + \ + return iter; \ + } \ + \ + FMOD void PFX##_iter_free(SNAME##_iter *iter) \ + { \ + free(iter); \ + } \ + \ + FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ + { \ + iter->target = target; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + \ + iter->cursor = target->root; \ + while (iter->cursor->left != NULL) \ + iter->cursor = iter->cursor->left; \ + \ + iter->first = iter->cursor; \ + \ + iter->last = target->root; \ + while (iter->last->right != NULL) \ + iter->last = iter->last->right; \ + } \ + \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->start; \ + } \ + \ + FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ + { \ + return PFX##_empty(iter->target) || iter->end; \ + } \ + \ + FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ + { \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->cursor = iter->first; \ + } \ + \ + FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ + { \ + iter->index = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + \ + iter->cursor = iter->last; \ + } \ + \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ + { \ + if (iter->end) \ + return false; \ + \ + iter->start = false; \ + \ + if (iter->cursor->right != NULL) \ + { \ + iter->cursor = iter->cursor->right; \ + while (iter->cursor->left != NULL) \ + iter->cursor = iter->cursor->left; \ + \ + iter->index++; \ + \ + return true; \ + } \ + \ + while (true) \ + { \ + if (iter->cursor == iter->last) \ + { \ + iter->end = true; \ + \ + return true; \ + } \ + if (iter->cursor->parent->left == iter->cursor) \ + { \ + iter->cursor = iter->cursor->parent; \ + \ + iter->index++; \ + \ + return true; \ + } \ + \ + iter->cursor = iter->cursor->parent; \ + } \ + } \ + \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \ + { \ + if (iter->start) \ + return false; \ + \ + iter->end = false; \ + \ + if (iter->cursor->left != NULL) \ + { \ + iter->cursor = iter->cursor->left; \ + \ + while (iter->cursor->right != NULL) \ + iter->cursor = iter->cursor->right; \ + \ + iter->index--; \ + \ + return true; \ + } \ + \ + while (true) \ + { \ + if (iter->cursor == iter->first) \ + { \ + iter->start = true; \ + \ + return true; \ + } \ + if (iter->cursor->parent->right == iter->cursor) \ + { \ + iter->cursor = iter->cursor->parent; \ + \ + iter->index--; \ + \ + return true; \ + } \ + \ + iter->cursor = iter->cursor->parent; \ + } \ + } \ + \ + FMOD K PFX##_iter_key(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return PFX##_impl_default_key(); \ + \ + return iter->cursor->key; \ + } \ + \ + FMOD V PFX##_iter_value(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return PFX##_impl_default_value(); \ + \ + return iter->cursor->value; \ + } \ + \ + FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + return NULL; \ + \ + return &(iter->cursor->value); \ + } \ + \ + FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ + { \ + return iter->index; \ + } \ + \ + static SNAME##_node *PFX##_impl_new_node(K key, V value) \ + { \ + SNAME##_node *node = malloc(sizeof(SNAME##_node)); \ + \ + if (!node) \ + return NULL; \ + \ + node->key = key; \ + node->value = value; \ + node->right = NULL; \ + node->left = NULL; \ + node->parent = NULL; \ + node->height = 0; \ + \ + return node; \ + } \ + \ + static SNAME##_node *PFX##_impl_get_node(SNAME *_map_, K key) \ + { \ + if (PFX##_empty(_map_)) \ + return NULL; \ + \ + SNAME##_node *scan = _map_->root; \ + \ + while (scan != NULL) \ + { \ + if (_map_->cmp(scan->key, key) > 0) \ + scan = scan->left; \ + else if (_map_->cmp(scan->key, key) < 0) \ + scan = scan->right; \ + else \ + return scan; \ + } \ + \ + return NULL; \ + } \ + \ + static unsigned char PFX##_impl_h(SNAME##_node *node) \ + { \ + if (node == NULL) \ + return 0; \ + \ + return node->height; \ + } \ + \ + static unsigned char PFX##_impl_hupdate(SNAME##_node *node) \ + { \ + if (node == NULL) \ + return 0; \ + \ + unsigned char h_l = PFX##_impl_h(node->left); \ + unsigned char h_r = PFX##_impl_h(node->right); \ + \ + return 1 + (h_l > h_r ? h_l : h_r); \ + } \ + \ + static void PFX##_impl_rotate_right(SNAME##_node **Z) \ + { \ + SNAME##_node *root = *Z; \ + SNAME##_node *new_root = root->left; \ + \ + if (root->parent != NULL) \ + { \ + if (root->parent->left == root) \ + root->parent->left = new_root; \ + else \ + root->parent->right = new_root; \ + } \ + \ + new_root->parent = root->parent; \ + \ + root->parent = new_root; \ + root->left = new_root->right; \ + \ + if (root->left) \ + root->left->parent = root; \ + \ + new_root->right = root; \ + \ + root->height = PFX##_impl_hupdate(root); \ + new_root->height = PFX##_impl_hupdate(new_root); \ + \ + *Z = new_root; \ + } \ + \ + static void PFX##_impl_rotate_left(SNAME##_node **Z) \ + { \ + SNAME##_node *root = *Z; \ + SNAME##_node *new_root = root->right; \ + \ + if (root->parent != NULL) \ + { \ + if (root->parent->right == root) \ + root->parent->right = new_root; \ + else \ + root->parent->left = new_root; \ + } \ + \ + new_root->parent = root->parent; \ + \ + root->parent = new_root; \ + root->right = new_root->left; \ + \ + if (root->right) \ + root->right->parent = root; \ + \ + new_root->left = root; \ + \ + root->height = PFX##_impl_hupdate(root); \ + new_root->height = PFX##_impl_hupdate(new_root); \ + \ + *Z = new_root; \ + } \ + \ + static void PFX##_impl_rebalance(SNAME *_map_, SNAME##_node *node) \ + { \ + SNAME##_node *scan = node, *child = NULL; \ + \ + int balance; \ + bool is_root = false; \ + \ + while (scan != NULL) \ + { \ + if (scan->parent == NULL) \ + is_root = true; \ + \ + scan->height = PFX##_impl_hupdate(scan); \ + balance = PFX##_impl_h(scan->right) - PFX##_impl_h(scan->left); \ + \ + if (balance >= 2) \ + { \ + child = scan->right; \ + \ + if (PFX##_impl_h(child->right) < PFX##_impl_h(child->left)) \ + PFX##_impl_rotate_right(&(scan->right)); \ + \ + PFX##_impl_rotate_left(&scan); \ + } \ + else if (balance <= -2) \ + { \ + child = scan->left; \ + \ + if (PFX##_impl_h(child->left) < PFX##_impl_h(child->right)) \ + PFX##_impl_rotate_left(&(scan->left)); \ + \ + PFX##_impl_rotate_right(&scan); \ + } \ + \ + if (is_root) \ + { \ + _map_->root = scan; \ + is_root = false; \ + } \ + \ + scan = scan->parent; \ + } \ + } \ + \ + static SNAME##_iter PFX##_impl_it_start(SNAME *_map_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _map_); \ + \ + return iter; \ + } \ + \ + static SNAME##_iter PFX##_impl_it_end(SNAME *_map_) \ + { \ + SNAME##_iter iter; \ + \ + PFX##_iter_init(&iter, _map_); \ + PFX##_iter_to_end(&iter); \ + \ + return iter; \ } #endif /* CMC_TREEMAP_H */ diff --git a/src/cmc/treeset.h b/src/cmc/treeset.h index 44407a9..a9c2055 100644 --- a/src/cmc/treeset.h +++ b/src/cmc/treeset.h @@ -107,8 +107,8 @@ /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ FMOD SNAME *PFX##_new(int (*compare)(V, V)); \ - FMOD void PFX##_clear(SNAME *_set_); \ - FMOD void PFX##_free(SNAME *_set_); \ + FMOD void PFX##_clear(SNAME *_set_, void (*deallocator)(V)); \ + FMOD void PFX##_free(SNAME *_set_, void (*deallocator)(V)); \ /* Collection Input and Output */ \ FMOD bool PFX##_insert(SNAME *_set_, V element); \ FMOD bool PFX##_remove(SNAME *_set_, V element); \ @@ -123,7 +123,7 @@ FMOD bool PFX##_empty(SNAME *_set_); \ FMOD size_t PFX##_count(SNAME *_set_); \ /* Collection Utility */ \ - FMOD cmc_string PFX##_to_string(SNAME *_map_); \ + FMOD cmc_string PFX##_to_string(SNAME *_set_); \ \ /* Set Operations */ \ FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_); \ @@ -195,7 +195,7 @@ return _set_; \ } \ \ - FMOD void PFX##_clear(SNAME *_set_) \ + FMOD void PFX##_clear(SNAME *_set_, void (*deallocator)(V)) \ { \ SNAME##_node *scan = _set_->root; \ SNAME##_node *up = NULL; \ @@ -223,12 +223,18 @@ { \ if (up == NULL) \ { \ + if (deallocator) \ + deallocator(scan->value); \ + \ free(scan); \ scan = NULL; \ } \ \ while (up != NULL) \ { \ + if (deallocator) \ + deallocator(scan->value); \ + \ free(scan); \ \ if (up->right != NULL) \ @@ -250,9 +256,9 @@ _set_->root = NULL; \ } \ \ - FMOD void PFX##_free(SNAME *_set_) \ + FMOD void PFX##_free(SNAME *_set_, void (*deallocator)(V)) \ { \ - PFX##_clear(_set_); \ + PFX##_clear(_set_, deallocator); \ \ free(_set_); \ } \ diff --git a/src/ext/intervalheap.h b/src/ext/intervalheap.h index 553605e..80cda2d 100644 --- a/src/ext/intervalheap.h +++ b/src/ext/intervalheap.h @@ -95,8 +95,8 @@ /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ FMOD SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)); \ - FMOD void PFX##_clear(SNAME *_heap_); \ - FMOD void PFX##_free(SNAME *_heap_); \ + FMOD void PFX##_clear(SNAME *_heap_, void (*deallocator)(V)); \ + FMOD void PFX##_free(SNAME *_heap_, void (*deallocator)(V)); \ /* Collection Input and Output */ \ FMOD bool PFX##_insert(SNAME *_heap_, V element); \ FMOD bool PFX##_remove_max(SNAME *_heap_, V *result); \ @@ -192,16 +192,32 @@ return _heap_; \ } \ \ - FMOD void PFX##_clear(SNAME *_heap_) \ + FMOD void PFX##_clear(SNAME *_heap_, void (*deallocator)(V)) \ { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _heap_->count; i++) \ + { \ + deallocator(_heap_->buffer[i / 2].data[i % 2]); \ + } \ + } \ + \ memset(_heap_->buffer, 0, sizeof(V) * _heap_->capacity); \ \ _heap_->size = 0; \ _heap_->count = 0; \ } \ \ - FMOD void PFX##_free(SNAME *_heap_) \ + FMOD void PFX##_free(SNAME *_heap_, void (*deallocator)(V)) \ { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _heap_->count; i++) \ + { \ + deallocator(_heap_->buffer[i / 2].data[i % 2]); \ + } \ + } \ + \ free(_heap_->buffer); \ \ free(_heap_); \ diff --git a/src/ext/linkedqueue.h b/src/ext/linkedqueue.h deleted file mode 100644 index 344fd7c..0000000 --- a/src/ext/linkedqueue.h +++ /dev/null @@ -1,384 +0,0 @@ -/** - * linkedqueue.h - * - * Creation Date: 21/06/2019 - * - * Authors: - * Leonardo Vencovsky (https://github.com/LeoVen) - * - */ - -/** - * A node-based Queue using a Singly Linked List - * - * enqueue : is equivalent to a push_back from a LinkedList - * dequeue : is equivalent to a pop_front from a LinkedList - * - * This Queue has a one-way iterator - */ - -#ifndef CMC_LINKEDQUEUE_H -#define CMC_LINKEDQUEUE_H - -#include -#include -#include - -#define LINKEDQUEUE_GENERATE(PFX, SNAME, FMOD, V) \ - LINKEDQUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - LINKEDQUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) - -#define LINKEDQUEUE_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \ - LINKEDQUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) - -#define LINKEDQUEUE_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \ - LINKEDQUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) - -/* HEADER ********************************************************************/ -#define LINKEDQUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - \ - /* Linked Queue Structure */ \ - typedef struct SNAME##_s \ - { \ - /* First node in the list */ \ - struct SNAME##_node_s *head; \ - \ - /* Last node in the list */ \ - struct SNAME##_node_s *tail; \ - \ - /* Current amount of elements in the list */ \ - size_t count; \ - \ - /* Function that returns an iterator to the start of the list */ \ - struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \ - \ - } SNAME, *SNAME##_ptr; \ - \ - /* Singly-linked list node */ \ - typedef struct SNAME##_node_s \ - { \ - /* Node's data */ \ - V data; \ - \ - /* Pointer to the next node on the linked list */ \ - struct SNAME##_node_s *next; \ - \ - } SNAME##_node, *SNAME##_node_ptr; \ - \ - /* Linked Queue Iterator */ \ - typedef struct SNAME##_iter_s \ - { \ - /* Target Linked Queue */ \ - struct SNAME##_s *target; \ - \ - /* Cursor's current node */ \ - struct SNAME##_node_s *cursor; \ - \ - /* Keeps track of relative index to the iteration of elements */ \ - size_t index; \ - \ - /* If the iterator is at the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - \ - } SNAME##_iter, *SNAME##_iter_ptr; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - FMOD SNAME *PFX##_new(void); \ - FMOD void PFX##_clear(SNAME *_lqueue_); \ - FMOD void PFX##_free(SNAME *_lqueue_); \ - /* Collection Input and Output */ \ - FMOD bool PFX##_enqueue(SNAME *_lqueue_, V element); \ - FMOD bool PFX##_dequeue(SNAME *_lqueue_); \ - /* Conditional Input and Output */ \ - FMOD bool PFX##_enqueue_if(SNAME *_lqueue_, V element, bool condition); \ - FMOD bool PFX##_dequeue_if(SNAME *_lqueue_, bool condition); \ - /* Element Access */ \ - FMOD V PFX##_peek(SNAME *_lqueue_); \ - /* Collection State */ \ - FMOD bool PFX##_contains(SNAME *_lqueue_, V element, int (*comparator)(V, V)); \ - FMOD bool PFX##_empty(SNAME *_lqueue_); \ - FMOD size_t PFX##_count(SNAME *_lqueue_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \ - FMOD void PFX##_iter_free(SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \ - /* Iterator State */ \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ - /* Iterator Movement */ \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ - /* Iterator Access */ \ - FMOD V PFX##_iter_value(SNAME##_iter *iter); \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ - \ - /* Default Value */ \ - static inline V PFX##_impl_default_value(void) \ - { \ - V _empty_value_; \ - \ - memset(&_empty_value_, 0, sizeof(V)); \ - \ - return _empty_value_; \ - } \ - \ -/* SOURCE ********************************************************************/ -#define LINKEDQUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ - \ - /* Implementation Detail Functions */ \ - FMOD SNAME##_node *PFX##_impl_new_node(V element); \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_lqueue_); \ - \ - FMOD SNAME *PFX##_new(void) \ - { \ - SNAME *_lqueue_ = malloc(sizeof(SNAME)); \ - \ - if (!_lqueue_) \ - return NULL; \ - \ - _lqueue_->count = 0; \ - _lqueue_->head = NULL; \ - _lqueue_->tail = NULL; \ - \ - _lqueue_->it_start = PFX##_impl_it_start; \ - \ - return _lqueue_; \ - } \ - \ - FMOD void PFX##_clear(SNAME *_lqueue_) \ - { \ - SNAME##_node *scan = _lqueue_->head; \ - \ - while (_lqueue_->head != NULL) \ - { \ - _lqueue_->head = _lqueue_->head->next; \ - free(scan); \ - scan = _lqueue_->head; \ - } \ - \ - _lqueue_->count = 0; \ - _lqueue_->head = NULL; \ - _lqueue_->tail = NULL; \ - } \ - \ - FMOD void PFX##_free(SNAME *_lqueue_) \ - { \ - PFX##_clear(_lqueue_); \ - \ - free(_lqueue_); \ - } \ - \ - FMOD bool PFX##_enqueue(SNAME *_lqueue_, V element) \ - { \ - SNAME##_node *_node_ = PFX##_impl_new_node(element); \ - \ - if (!_node_) \ - return false; \ - \ - if (PFX##_empty(_lqueue_)) \ - { \ - _lqueue_->head = _node_; \ - _lqueue_->tail = _node_; \ - } \ - else \ - { \ - _lqueue_->tail->next = _node_; \ - _lqueue_->tail = _node_; \ - } \ - \ - _lqueue_->count++; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_dequeue(SNAME *_lqueue_) \ - { \ - if (PFX##_empty(_lqueue_)) \ - return false; \ - \ - SNAME##_node *_node_ = _lqueue_->head; \ - _lqueue_->head = _lqueue_->head->next; \ - \ - free(_node_); \ - \ - if (_lqueue_->head == NULL) \ - _lqueue_->tail = NULL; \ - \ - _lqueue_->count--; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_enqueue_if(SNAME *_lqueue_, V element, bool condition) \ - { \ - if (condition) \ - return PFX##_enqueue(_lqueue_, element); \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_dequeue_if(SNAME *_lqueue_, bool condition) \ - { \ - if (condition) \ - return PFX##_dequeue(_lqueue_); \ - \ - return false; \ - } \ - \ - FMOD V PFX##_peek(SNAME *_lqueue_) \ - { \ - if (PFX##_empty(_lqueue_)) \ - return PFX##_impl_default_value(); \ - \ - return _lqueue_->head->data; \ - } \ - \ - FMOD bool PFX##_contains(SNAME *_lqueue_, V element, int (*comparator)(V, V)) \ - { \ - SNAME##_node *scan = _lqueue_->head; \ - \ - while (scan != NULL) \ - { \ - if (comparator(scan->data, element) == 0) \ - return true; \ - \ - scan = scan->next; \ - } \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_empty(SNAME *_lqueue_) \ - { \ - return _lqueue_->count == 0; \ - } \ - \ - FMOD size_t PFX##_count(SNAME *_lqueue_) \ - { \ - return _lqueue_->count; \ - } \ - \ - FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \ - { \ - SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \ - \ - if (!iter) \ - return NULL; \ - \ - PFX##_iter_init(iter, target); \ - \ - return iter; \ - } \ - \ - FMOD void PFX##_iter_free(SNAME##_iter *iter) \ - { \ - free(iter); \ - } \ - \ - FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ - { \ - iter->target = target; \ - iter->cursor = target->head; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(target); \ - } \ - \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->start; \ - } \ - \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ - { \ - return PFX##_empty(iter->target) || iter->end; \ - } \ - \ - FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ - { \ - iter->cursor = iter->target->head; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - } \ - \ - FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ - { \ - iter->cursor = iter->target->tail; \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - } \ - \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ - { \ - if (iter->end) \ - return false; \ - \ - iter->start = PFX##_empty(iter->target); \ - \ - if (iter->cursor->next == NULL) \ - iter->end = true; \ - else \ - { \ - iter->cursor = iter->cursor->next; \ - iter->index++; \ - } \ - \ - return true; \ - } \ - \ - FMOD V PFX##_iter_value(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return PFX##_impl_default_value(); \ - \ - return iter->cursor->data; \ - } \ - \ - FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \ - { \ - if (PFX##_empty(iter->target)) \ - return NULL; \ - \ - return &(iter->cursor->data); \ - } \ - \ - FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \ - { \ - return iter->index; \ - } \ - \ - FMOD SNAME##_node *PFX##_impl_new_node(V element) \ - { \ - SNAME##_node *_node_ = malloc(sizeof(SNAME##_node)); \ - \ - if (!_node_) \ - return NULL; \ - \ - _node_->data = element; \ - _node_->next = NULL; \ - \ - return _node_; \ - } \ - \ - static SNAME##_iter PFX##_impl_it_start(SNAME *_lqueue_) \ - { \ - SNAME##_iter iter; \ - \ - PFX##_iter_init(&iter, _lqueue_); \ - PFX##_iter_to_start(&iter); \ - \ - return iter; \ - } - -#endif /* CMC_LINKEDQUEUE_H */ diff --git a/src/ext/multimap.h b/src/ext/multimap.h index d500040..6fc148c 100644 --- a/src/ext/multimap.h +++ b/src/ext/multimap.h @@ -175,24 +175,25 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ FMOD SNAME *PFX##_new(size_t capacity, double load, int (*compare)(K, K), size_t (*hash)(K)); \ - FMOD void PFX##_clear(SNAME *_map_); \ - FMOD void PFX##_free(SNAME *_map_); \ - /* Collection Input and Output */ \ + FMOD void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)); \ + FMOD void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)); \ + /* Create */ \ FMOD bool PFX##_insert(SNAME *_map_, K key, V value); \ - FMOD bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value); \ - FMOD size_t PFX##_update_all(SNAME *_map_, K key, V new_value, V **old_values); \ - FMOD bool PFX##_remove(SNAME *_map_, K key, V *value); \ - FMOD size_t PFX##_remove_all(SNAME *_map_, K key); \ - /* Conditional Input and Output */ \ FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition); \ - FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition); \ - /* Element Access */ \ + /* Read */ \ FMOD bool PFX##_max(SNAME *_map_, K *key, V *value); \ FMOD bool PFX##_min(SNAME *_map_, K *key, V *value); \ FMOD V PFX##_get(SNAME *_map_, K key); \ FMOD V *PFX##_get_ref(SNAME *_map_, K key); \ + /* Update */ \ + FMOD bool PFX##_update(SNAME *_map_, K key, V new_value, V *old_value); \ + FMOD size_t PFX##_update_all(SNAME *_map_, K key, V new_value, V **old_values); \ FMOD bool PFX##_set(SNAME *_map_, K key, V new_value); \ FMOD size_t PFX##_set_all(SNAME *_map_, K key, V new_value); \ + /* Delete */ \ + FMOD bool PFX##_remove(SNAME *_map_, K key, V *value); \ + FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition); \ + FMOD size_t PFX##_remove_all(SNAME *_map_, K key); \ /* Collection State */ \ FMOD bool PFX##_contains(SNAME *_map_, K key); \ FMOD bool PFX##_empty(SNAME *_map_); \ @@ -286,7 +287,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return _map_; \ } \ \ - FMOD void PFX##_clear(SNAME *_map_) \ + FMOD void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)) \ { \ size_t index = 0; \ SNAME##_entry *scan; \ @@ -307,6 +308,8 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ scan = scan->next; \ \ + deallocator(tmp->key, tmp->scan); \ + \ free(tmp); \ } \ } \ @@ -320,9 +323,37 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, _map_->count = 0; \ } \ \ - FMOD void PFX##_free(SNAME *_map_) \ + FMOD void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)) \ { \ - PFX##_clear(_map_); \ + size_t index = 0; \ + SNAME##_entry *scan; \ + \ + while (index < _map_->capacity) \ + { \ + scan = _map_->buffer[index][0]; \ + \ + if (scan != NULL) \ + { \ + if (scan->next == NULL && scan->prev == NULL) \ + free(scan); \ + else \ + { \ + while (scan != NULL) \ + { \ + SNAME##_entry *tmp = scan; \ + \ + scan = scan->next; \ + \ + deallocator(tmp->key, tmp->scan); \ + \ + free(tmp); \ + } \ + } \ + } \ + \ + index++; \ + } \ + \ free(_map_->buffer); \ free(_map_); \ } \ @@ -888,7 +919,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ if (_map_->count != _new_map_->count) \ { \ - PFX##_free(_new_map_); \ + PFX##_free(_new_map_, NULL); \ return false; \ } \ \ @@ -900,7 +931,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, _map_->capacity = _new_map_->capacity; \ _new_map_->capacity = tmp_c; \ \ - PFX##_free(_new_map_); \ + PFX##_free(_new_map_, NULL); \ \ return true; \ } \ diff --git a/src/ext/multiset.h b/src/ext/multiset.h index 95a1ac3..7aa8cc9 100644 --- a/src/ext/multiset.h +++ b/src/ext/multiset.h @@ -161,8 +161,8 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ FMOD SNAME *PFX##_new(size_t capacity, double load, int (*compare)(V, V), size_t (*hash)(V)); \ - FMOD void PFX##_clear(SNAME *_set_); \ - FMOD void PFX##_free(SNAME *_set_); \ + FMOD void PFX##_clear(SNAME *_set_, void (*deallocator)(V)); \ + FMOD void PFX##_free(SNAME *_set_, void (*deallocator)(V)); \ /* Collection Input and Output */ \ FMOD bool PFX##_insert(SNAME *_set_, V element); \ FMOD bool PFX##_insert_many(SNAME *_set_, V element, size_t count); \ @@ -276,15 +276,41 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return _set_; \ } \ \ - FMOD void PFX##_clear(SNAME *_set_) \ + FMOD void PFX##_clear(SNAME *_set_, void (*deallocator)(V)) \ { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _set_->capacity; i++) \ + { \ + SNAME##_entry *entry = &(_set_->buffer[i]); \ + \ + if (entry->state == CMC_ES_FILLED) \ + { \ + deallocator(entry->value); \ + } \ + } \ + } \ + \ memset(_set_->buffer, 0, sizeof(SNAME##_entry) * _set_->capacity); \ \ _set_->count = 0; \ } \ \ - FMOD void PFX##_free(SNAME *_set_) \ + FMOD void PFX##_free(SNAME *_set_, void (*deallocator)(V)) \ { \ + if (deallocator) \ + { \ + for (size_t i = 0; i < _set_->capacity; i++) \ + { \ + SNAME##_entry *entry = &(_set_->buffer[i]); \ + \ + if (entry->state == CMC_ES_FILLED) \ + { \ + deallocator(entry->value); \ + } \ + } \ + } \ + \ free(_set_->buffer); \ free(_set_); \ } \ @@ -988,7 +1014,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ if (_set_->count != _new_set_->count) \ { \ - PFX##_free(_new_set_); \ + PFX##_free(_new_set_, NULL); \ \ return false; \ } \ @@ -999,7 +1025,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ _set_->capacity = _new_set_->capacity; \ \ - PFX##_free(_new_set_); \ + PFX##_free(_new_set_, NULL); \ \ return true; \ } \ diff --git a/src/macro_collections.h b/src/macro_collections.h index fe7466f..1dfdea9 100644 --- a/src/macro_collections.h +++ b/src/macro_collections.h @@ -41,7 +41,6 @@ #include "cmc/treeset.h" #include "ext/intervalheap.h" -#include "ext/linkedqueue.h" #include "ext/multimap.h" #include "ext/multiset.h" diff --git a/tests/Makefile b/tests/Makefile index 65dc46e..854a050 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -3,15 +3,21 @@ CFLAGS = -std=c11 -Wall -Wextra CFLAGS += -Wno-unused-function -Wno-unused-paramter -Wno-unused-variable -Wno-unused-label main: - $(CC) foreach.c -o foreach $(CFLAGS) - ./foreach - $(CC) iterators.c -o iterators $(CFLAGS) - ./iterators - $(CC) contains.c -o contains $(CFLAGS) - ./contains - $(CC) types.c -o types $(CFLAGS) - ./types + $(CC) foreach.c -o foreach.exe $(CFLAGS) + ./foreach.exe + $(CC) iterators.c -o iterators.exe $(CFLAGS) + ./iterators.exe + $(CC) contains.c -o contains.exe $(CFLAGS) + ./contains.exe + $(CC) types.c -o types.exe $(CFLAGS) + ./types.exe $(CC) -c ./sep/sep.c -o ./sep/sep.o $(CFLAGS) $(CC) -c ./sep/main.c -o ./sep/main.o $(CFLAGS) - $(CC) ./sep/sep.o ./sep/main.o -o ./sep/sep - ./sep/sep + $(CC) ./sep/sep.o ./sep/main.o -o ./sep/sep.exe + ./sep/sep.exe + +dev: main + rm *.exe ./sep/*.o ./sep/*.exe + +windev: main + del *.exe .\\sep\\*.o .\\sep\\*.exe diff --git a/tests/contains.c b/tests/contains.c index 86a6716..6e7ceec 100644 --- a/tests/contains.c +++ b/tests/contains.c @@ -125,16 +125,16 @@ int main(void) a[9] = a[9] || ts_contains(ts, i); } - d_clear(d); - hm_clear(hm); - hs_clear(hs); - h_clear(h); - ll_clear(ll); - l_clear(l); - q_clear(q); - s_clear(s); - tm_clear(tm); - ts_clear(ts); + d_clear(d, NULL); + hm_clear(hm, NULL); + hs_clear(hs, NULL); + h_clear(h, NULL); + ll_clear(ll, NULL); + l_clear(l, NULL); + q_clear(q, NULL); + s_clear(s, NULL); + tm_clear(tm, NULL); + ts_clear(ts, NULL); b[0] = b[0] || d_contains(d, 1, intcmp); b[1] = b[1] || hm_contains(hm, 1); @@ -189,16 +189,16 @@ int main(void) else printf("%10s FAILED\n", "TREESET"); - l_free(l); - ll_free(ll); - s_free(s); - q_free(q); - d_free(d); - h_free(h); - ts_free(ts); - tm_free(tm); - hs_free(hs); - hm_free(hm); + l_free(l, NULL); + ll_free(ll, NULL); + s_free(s, NULL); + q_free(q, NULL); + d_free(d, NULL); + h_free(h, NULL); + ts_free(ts, NULL); + tm_free(tm, NULL); + hs_free(hs, NULL); + hm_free(hm, NULL); return 0; } diff --git a/tests/foreach.c b/tests/foreach.c index f72249c..56dafcb 100644 --- a/tests/foreach.c +++ b/tests/foreach.c @@ -243,16 +243,16 @@ int main(void) else printf("%10s FAILED\n", "TREESET"); - l_free(l); - ll_free(ll); - s_free(s); - q_free(q); - d_free(d); - h_free(h); - ts_free(ts); - tm_free(tm); - hs_free(hs); - hm_free(hm); + l_free(l, NULL); + ll_free(ll, NULL); + s_free(s, NULL); + q_free(q, NULL); + d_free(d, NULL); + h_free(h, NULL); + ts_free(ts, NULL); + tm_free(tm, NULL); + hs_free(hs, NULL); + hm_free(hm, NULL); return 0; } diff --git a/tests/iterators.c b/tests/iterators.c index 8f2377d..9f0015b 100644 --- a/tests/iterators.c +++ b/tests/iterators.c @@ -69,7 +69,7 @@ COLLECTION_GENERATE(HASHMAP, hm, hmap, /* FMOD */, int, double) sumbody; \ } \ \ - PFX##_free(coll); \ + PFX##_free(coll, NULL); \ \ if (validation1 && validation2) \ printf("%10s PASSED\n", #NAME); \ diff --git a/tests/sep/main.c b/tests/sep/main.c index 6b44d0e..351d91e 100644 --- a/tests/sep/main.c +++ b/tests/sep/main.c @@ -35,16 +35,16 @@ int main(void) printf("| Separate Header and Source is Working |\n"); printf("+--------------------------------------------------+\n"); - l_free(l); - ll_free(ll); - s_free(s); - q_free(q); - d_free(d); - h_free(h); - ts_free(ts); - tm_free(tm); - hs_free(hs); - hm_free(hm); + l_free(l, NULL); + ll_free(ll, NULL); + s_free(s, NULL); + q_free(q, NULL); + d_free(d, NULL); + h_free(h, NULL); + ts_free(ts, NULL); + tm_free(tm, NULL); + hs_free(hs, NULL); + hm_free(hm, NULL); return 0; -} \ No newline at end of file +}