diff --git a/src/cmc/heap.h b/src/cmc/heap.h index 833b2cd..e04ac1c 100644 --- a/src/cmc/heap.h +++ b/src/cmc/heap.h @@ -112,7 +112,7 @@ static const char *cmc_string_fmt_heap = "struct %s<%s> " "capacity:%" PRIuMAX ", " "count:%" PRIuMAX ", " "type:%s, " - "cmp:%p, " + "f_val:%p, " "alloc:%p, " "callbacks: %p}"; @@ -161,20 +161,45 @@ struct cmc_callbacks_heap /* Heap order (MaxHeap or MinHeap) */ \ enum cmc_heap_order HO; \ \ - /* Element comparison function */ \ - int (*cmp)(V, V); \ + /* Flags indicating errors or success */ \ + int flag; \ \ - /* Function that returns an iterator to the start of the heap */ \ - struct SNAME##_iter (*it_start)(struct SNAME *); \ - \ - /* Function that returns an iterator to the end of the heap */ \ - struct SNAME##_iter (*it_end)(struct SNAME *); \ + /* Value function table */ \ + struct SNAME##_ftab_val *f_val; \ \ /* Custom allocation functions */ \ struct cmc_alloc_node *alloc; \ \ /* Custom callback functions */ \ struct cmc_callbacks_heap *callbacks; \ + \ + /* Function that returns an iterator to the start of the heap */ \ + struct SNAME##_iter (*it_start)(struct SNAME *); \ + \ + /* Function that returns an iterator to the end of the heap */ \ + struct SNAME##_iter (*it_end)(struct SNAME *); \ + }; \ + \ + /* Value struct function table */ \ + struct SNAME##_ftab_val \ + { \ + /* Comparator function */ \ + int (*cmp)(V, V); \ + \ + /* Copy function */ \ + V (*cpy)(V); \ + \ + /* To string function */ \ + bool (*str)(FILE *, V); \ + \ + /* Free from memory function */ \ + void (*free)(V); \ + \ + /* Hash function */ \ + size_t (*hash)(V); \ + \ + /* Priority function */ \ + int (*pri)(V, V); \ }; \ \ /* Heap Iterator */ \ @@ -196,12 +221,13 @@ struct cmc_callbacks_heap /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ struct SNAME *PFX##_new(size_t capacity, enum cmc_heap_order HO, \ - int (*compare)(V, V)); \ - struct SNAME *PFX##_new_custom( \ - size_t capacity, enum cmc_heap_order HO, int (*compare)(V, V), \ - struct cmc_alloc_node *alloc, struct cmc_callbacks_heap *callbacks); \ - void PFX##_clear(struct SNAME *_heap_, void (*deallocator)(V)); \ - void PFX##_free(struct SNAME *_heap_, void (*deallocator)(V)); \ + struct SNAME##_ftab_val *f_val); \ + struct SNAME *PFX##_new_custom(size_t capacity, enum cmc_heap_order HO, \ + struct SNAME##_ftab_val *f_val, \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_heap *callbacks); \ + void PFX##_clear(struct SNAME *_heap_); \ + void PFX##_free(struct SNAME *_heap_); \ /* Customization of Allocation and Callbacks */ \ void PFX##_customize(struct SNAME *_heap_, struct cmc_alloc_node *alloc, \ struct cmc_callbacks_heap *callbacks); \ @@ -218,7 +244,7 @@ struct cmc_callbacks_heap size_t PFX##_capacity(struct SNAME *_heap_); \ /* Collection Utility */ \ bool PFX##_resize(struct SNAME *_heap_, size_t capacity); \ - struct SNAME *PFX##_copy_of(struct SNAME *_heap_, V (*copy_func)(V)); \ + struct SNAME *PFX##_copy_of(struct SNAME *_heap_); \ bool PFX##_equals(struct SNAME *_heap1_, struct SNAME *_heap2_); \ struct cmc_string PFX##_to_string(struct SNAME *_heap_); \ \ @@ -255,7 +281,7 @@ struct cmc_callbacks_heap static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_heap_); \ \ struct SNAME *PFX##_new(size_t capacity, enum cmc_heap_order HO, \ - int (*compare)(V, V)) \ + struct SNAME##_ftab_val *f_val) \ { \ struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ \ @@ -265,6 +291,9 @@ struct cmc_callbacks_heap if (HO != cmc_min_heap && HO != cmc_max_heap) \ return NULL; \ \ + if (!f_val) \ + return NULL; \ + \ struct SNAME *_heap_ = alloc->malloc(sizeof(struct SNAME)); \ \ if (!_heap_) \ @@ -281,20 +310,20 @@ struct cmc_callbacks_heap _heap_->capacity = capacity; \ _heap_->count = 0; \ _heap_->HO = HO; \ - _heap_->cmp = compare; \ - \ - _heap_->it_start = PFX##_impl_it_start; \ - _heap_->it_end = PFX##_impl_it_end; \ - \ + _heap_->flag = cmc_flags.OK; \ + _heap_->f_val = f_val; \ _heap_->alloc = alloc; \ _heap_->callbacks = NULL; \ + _heap_->it_start = PFX##_impl_it_start; \ + _heap_->it_end = PFX##_impl_it_end; \ \ return _heap_; \ } \ \ - struct SNAME *PFX##_new_custom( \ - size_t capacity, enum cmc_heap_order HO, int (*compare)(V, V), \ - struct cmc_alloc_node *alloc, struct cmc_callbacks_heap *callbacks) \ + struct SNAME *PFX##_new_custom(size_t capacity, enum cmc_heap_order HO, \ + struct SNAME##_ftab_val *f_val, \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_heap *callbacks) \ { \ if (capacity < 1) \ return NULL; \ @@ -302,6 +331,9 @@ struct cmc_callbacks_heap if (HO != cmc_min_heap && HO != cmc_max_heap) \ return NULL; \ \ + if (!f_val) \ + return NULL; \ + \ if (!alloc) \ alloc = &cmc_alloc_node_default; \ \ @@ -321,24 +353,23 @@ struct cmc_callbacks_heap _heap_->capacity = capacity; \ _heap_->count = 0; \ _heap_->HO = HO; \ - _heap_->cmp = compare; \ - \ - _heap_->it_start = PFX##_impl_it_start; \ - _heap_->it_end = PFX##_impl_it_end; \ - \ + _heap_->flag = cmc_flags.OK; \ + _heap_->f_val = f_val; \ _heap_->alloc = alloc; \ _heap_->callbacks = callbacks; \ + _heap_->it_start = PFX##_impl_it_start; \ + _heap_->it_end = PFX##_impl_it_end; \ \ return _heap_; \ } \ \ - void PFX##_clear(struct SNAME *_heap_, void (*deallocator)(V)) \ + void PFX##_clear(struct SNAME *_heap_) \ { \ - if (deallocator) \ + if (_heap_->f_val->free) \ { \ for (size_t i = 0; i < _heap_->count; i++) \ { \ - deallocator(_heap_->buffer[i]); \ + _heap_->f_val->free(_heap_->buffer[i]); \ } \ } \ \ @@ -347,13 +378,13 @@ struct cmc_callbacks_heap _heap_->count = 0; \ } \ \ - void PFX##_free(struct SNAME *_heap_, void (*deallocator)(V)) \ + void PFX##_free(struct SNAME *_heap_) \ { \ - if (deallocator) \ + if (_heap_->f_val->free) \ { \ for (size_t i = 0; i < _heap_->count; i++) \ { \ - deallocator(_heap_->buffer[i]); \ + _heap_->f_val->free(_heap_->buffer[i]); \ } \ } \ \ @@ -422,7 +453,7 @@ struct cmc_callbacks_heap { \ for (size_t i = 0; i < _heap_->count; i++) \ { \ - if (_heap_->cmp(_heap_->buffer[i], element) == 0) \ + if (_heap_->f_val->cmp(_heap_->buffer[i], element) == 0) \ return true; \ } \ \ @@ -463,25 +494,27 @@ struct cmc_callbacks_heap if (!new_buffer) \ return false; \ \ + /* TODO zero out new slots */ \ + \ _heap_->buffer = new_buffer; \ _heap_->capacity = capacity; \ \ return true; \ } \ \ - struct SNAME *PFX##_copy_of(struct SNAME *_heap_, V (*copy_func)(V)) \ + struct SNAME *PFX##_copy_of(struct SNAME *_heap_) \ { \ struct SNAME *result = \ - PFX##_new_custom(_heap_->capacity, _heap_->HO, _heap_->cmp, \ + PFX##_new_custom(_heap_->capacity, _heap_->HO, _heap_->f_val, \ _heap_->alloc, _heap_->callbacks); \ \ if (!result) \ return NULL; \ \ - if (copy_func) \ + if (_heap_->f_val->cpy) \ { \ for (size_t i = 0; i < _heap_->count; i++) \ - result->buffer[i] = copy_func(_heap_->buffer[i]); \ + result->buffer[i] = _heap_->f_val->cpy(_heap_->buffer[i]); \ } \ else \ memcpy(result->buffer, _heap_->buffer, sizeof(V) * _heap_->count); \ @@ -498,7 +531,8 @@ struct cmc_callbacks_heap \ for (size_t i = 0; i < PFX##_count(_heap1_); i++) \ { \ - if (_heap1_->cmp(_heap1_->buffer[i], _heap2_->buffer[i]) != 0) \ + if (_heap1_->f_val->cmp(_heap1_->buffer[i], _heap2_->buffer[i]) != \ + 0) \ return false; \ } \ \ @@ -513,14 +547,9 @@ struct cmc_callbacks_heap \ int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_heap, #SNAME, \ #V, h_, h_->buffer, h_->capacity, h_->count, t, \ - h_->cmp, h_->alloc, h_->callbacks); \ + h_->f_val, h_->alloc, h_->callbacks); \ \ - if (n < 0 || n == (int)cmc_string_len) \ - return (struct cmc_string){ 0 }; \ - \ - str.s[n] = '\0'; \ - \ - return str; \ + return n >= 0 ? str : (struct cmc_string){ 0 }; \ } \ \ struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ @@ -699,7 +728,7 @@ struct cmc_callbacks_heap \ int mod = _heap_->HO; \ \ - while (C > 0 && _heap_->cmp(child, parent) * mod > 0) \ + while (C > 0 && _heap_->f_val->cmp(child, parent) * mod > 0) \ { \ /* Swap between C (current element) and its parent */ \ V tmp = _heap_->buffer[C]; \ @@ -728,13 +757,17 @@ struct cmc_callbacks_heap \ /* Determine if we swap with the left or right element */ \ if (L < _heap_->count && \ - _heap_->cmp(_heap_->buffer[L], _heap_->buffer[C]) * mod > 0) \ + _heap_->f_val->cmp(_heap_->buffer[L], _heap_->buffer[C]) * \ + mod > \ + 0) \ { \ C = L; \ } \ \ if (R < _heap_->count && \ - _heap_->cmp(_heap_->buffer[R], _heap_->buffer[C]) * mod > 0) \ + _heap_->f_val->cmp(_heap_->buffer[R], _heap_->buffer[C]) * \ + mod > \ + 0) \ { \ C = R; \ } \ diff --git a/src/cmc/intervalheap.h b/src/cmc/intervalheap.h index 4e5a7cb..5df8c90 100644 --- a/src/cmc/intervalheap.h +++ b/src/cmc/intervalheap.h @@ -89,7 +89,7 @@ static const char *cmc_string_fmt_intervalheap = "struct %s<%s> " "capacity:%" PRIuMAX ", " "size:%" PRIuMAX ", " "count:%" PRIuMAX ", " - "cmp:%p, " + "f_val:%p, " "alloc:%p, " "callbacks:%p }"; @@ -121,115 +121,141 @@ struct cmc_callbacks_intervalheap /* ------------------------------------------------------------------------- * Header * ------------------------------------------------------------------------- */ -#define CMC_GENERATE_INTERVALHEAP_HEADER(PFX, SNAME, V) \ - \ - /* Heap Structure */ \ - struct SNAME \ - { \ - /* Dynamic array of nodes */ \ - struct SNAME##_node *buffer; \ - \ - /* Current array capacity (how many nodes can be stored) */ \ - size_t capacity; \ - \ - /* Current amount of nodes in the dynamic array */ \ - size_t size; \ - \ - /* Current amount of elements in the heap */ \ - size_t count; \ - \ - /* Element comparison function */ \ - int (*cmp)(V, V); \ - \ - /* Function that returns an iterator to the start of the heap */ \ - struct SNAME##_iter (*it_start)(struct SNAME *); \ - \ - /* Function that returns an iterator to the end of the heap */ \ - struct SNAME##_iter (*it_end)(struct SNAME *); \ - \ - /* Custom allocation functions */ \ - struct cmc_alloc_node *alloc; \ - \ - /* Custom callback functions */ \ - struct cmc_callbacks_intervalheap *callbacks; \ - }; \ - \ - /* Heap Node */ \ - struct SNAME##_node \ - { \ - /* 0 - Value belonging to the MinHeap */ \ - /* 1 - Value belonging to the MaxHeap */ \ - V data[2]; \ - }; \ - \ - /* Heap Iterator */ \ - struct SNAME##_iter \ - { \ - /* Target heap */ \ - struct SNAME *target; \ - \ - /* Cursor's position (index) */ \ - size_t cursor; \ - \ - /* If the iterator has reached the start of the iteration */ \ - bool start; \ - \ - /* If the iterator has reached the end of the iteration */ \ - bool end; \ - }; \ - \ - /* Collection Functions */ \ - /* Collection Allocation and Deallocation */ \ - struct SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)); \ - struct SNAME *PFX##_new_custom( \ - size_t capacity, int (*compare)(V, V), struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_intervalheap *callbacks); \ - void PFX##_clear(struct SNAME *_heap_, void (*deallocator)(V)); \ - void PFX##_free(struct SNAME *_heap_, void (*deallocator)(V)); \ - /* Customization of Allocation and Callbacks */ \ - void PFX##_customize(struct SNAME *_heap_, struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_intervalheap *callbacks); \ - /* Collection Input and Output */ \ - bool PFX##_insert(struct SNAME *_heap_, V element); \ - bool PFX##_remove_max(struct SNAME *_heap_, V *result); \ - bool PFX##_remove_min(struct SNAME *_heap_, V *result); \ - /* Collection Update */ \ - bool PFX##_update_max(struct SNAME *_heap_, V element); \ - bool PFX##_update_min(struct SNAME *_heap_, V element); \ - /* Element Access */ \ - bool PFX##_max(struct SNAME *_heap_, V *value); \ - bool PFX##_min(struct SNAME *_heap_, V *value); \ - /* Collection State */ \ - bool PFX##_contains(struct SNAME *_heap_, V element); \ - bool PFX##_empty(struct SNAME *_heap_); \ - bool PFX##_full(struct SNAME *_heap_); \ - size_t PFX##_count(struct SNAME *_heap_); \ - size_t PFX##_capacity(struct SNAME *_heap_); \ - /* Collection Utility */ \ - bool PFX##_resize(struct SNAME *_heap_, size_t capacity); \ - struct SNAME *PFX##_copy_of(struct SNAME *_set_, V (*copy_func)(V)); \ - bool PFX##_equals(struct SNAME *_heap1_, struct SNAME *_heap2_); \ - struct cmc_string PFX##_to_string(struct SNAME *_heap_); \ - \ - /* Iterator Functions */ \ - /* Iterator Allocation and Deallocation */ \ - struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ - void PFX##_iter_free(struct SNAME##_iter *iter); \ - /* Iterator Initialization */ \ - void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ - /* Iterator State */ \ - bool PFX##_iter_start(struct SNAME##_iter *iter); \ - bool PFX##_iter_end(struct SNAME##_iter *iter); \ - /* Iterator Movement */ \ - void PFX##_iter_to_start(struct SNAME##_iter *iter); \ - void PFX##_iter_to_end(struct SNAME##_iter *iter); \ - bool PFX##_iter_next(struct SNAME##_iter *iter); \ - bool PFX##_iter_prev(struct SNAME##_iter *iter); \ - bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ - bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ - /* Iterator Access */ \ - V PFX##_iter_value(struct SNAME##_iter *iter); \ +#define CMC_GENERATE_INTERVALHEAP_HEADER(PFX, SNAME, V) \ + \ + /* Heap Structure */ \ + struct SNAME \ + { \ + /* Dynamic array of nodes */ \ + struct SNAME##_node *buffer; \ + \ + /* Current array capacity (how many nodes can be stored) */ \ + size_t capacity; \ + \ + /* Current amount of nodes in the dynamic array */ \ + size_t size; \ + \ + /* Current amount of elements in the heap */ \ + size_t count; \ + \ + /* Flags indicating errors or success */ \ + int flag; \ + \ + /* Value function table */ \ + struct SNAME##_ftab_val *f_val; \ + \ + /* Function that returns an iterator to the start of the heap */ \ + struct SNAME##_iter (*it_start)(struct SNAME *); \ + \ + /* Function that returns an iterator to the end of the heap */ \ + struct SNAME##_iter (*it_end)(struct SNAME *); \ + \ + /* Custom allocation functions */ \ + struct cmc_alloc_node *alloc; \ + \ + /* Custom callback functions */ \ + struct cmc_callbacks_intervalheap *callbacks; \ + }; \ + \ + /* Heap Node */ \ + struct SNAME##_node \ + { \ + /* 0 - Value belonging to the MinHeap */ \ + /* 1 - Value belonging to the MaxHeap */ \ + V data[2]; \ + }; \ + \ + /* Value struct function table */ \ + struct SNAME##_ftab_val \ + { \ + /* Comparator function */ \ + int (*cmp)(V, V); \ + \ + /* Copy function */ \ + V (*cpy)(V); \ + \ + /* To string function */ \ + bool (*str)(FILE *, V); \ + \ + /* Free from memory function */ \ + void (*free)(V); \ + \ + /* Hash function */ \ + size_t (*hash)(V); \ + \ + /* Priority function */ \ + int (*pri)(V, V); \ + }; \ + \ + /* Heap Iterator */ \ + struct SNAME##_iter \ + { \ + /* Target heap */ \ + struct SNAME *target; \ + \ + /* Cursor's position (index) */ \ + size_t cursor; \ + \ + /* If the iterator has reached the start of the iteration */ \ + bool start; \ + \ + /* If the iterator has reached the end of the iteration */ \ + bool end; \ + }; \ + \ + /* Collection Functions */ \ + /* Collection Allocation and Deallocation */ \ + struct SNAME *PFX##_new(size_t capacity, struct SNAME##_ftab_val *f_val); \ + struct SNAME *PFX##_new_custom( \ + size_t capacity, struct SNAME##_ftab_val *f_val, \ + struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_intervalheap *callbacks); \ + void PFX##_clear(struct SNAME *_heap_); \ + void PFX##_free(struct SNAME *_heap_); \ + /* Customization of Allocation and Callbacks */ \ + void PFX##_customize(struct SNAME *_heap_, struct cmc_alloc_node *alloc, \ + struct cmc_callbacks_intervalheap *callbacks); \ + /* Collection Input and Output */ \ + bool PFX##_insert(struct SNAME *_heap_, V element); \ + bool PFX##_remove_max(struct SNAME *_heap_, V *result); \ + bool PFX##_remove_min(struct SNAME *_heap_, V *result); \ + /* Collection Update */ \ + bool PFX##_update_max(struct SNAME *_heap_, V element); \ + bool PFX##_update_min(struct SNAME *_heap_, V element); \ + /* Element Access */ \ + bool PFX##_max(struct SNAME *_heap_, V *value); \ + bool PFX##_min(struct SNAME *_heap_, V *value); \ + /* Collection State */ \ + bool PFX##_contains(struct SNAME *_heap_, V element); \ + bool PFX##_empty(struct SNAME *_heap_); \ + bool PFX##_full(struct SNAME *_heap_); \ + size_t PFX##_count(struct SNAME *_heap_); \ + size_t PFX##_capacity(struct SNAME *_heap_); \ + /* Collection Utility */ \ + bool PFX##_resize(struct SNAME *_heap_, size_t capacity); \ + struct SNAME *PFX##_copy_of(struct SNAME *_set_); \ + bool PFX##_equals(struct SNAME *_heap1_, struct SNAME *_heap2_); \ + struct cmc_string PFX##_to_string(struct SNAME *_heap_); \ + \ + /* Iterator Functions */ \ + /* Iterator Allocation and Deallocation */ \ + struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \ + void PFX##_iter_free(struct SNAME##_iter *iter); \ + /* Iterator Initialization */ \ + void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \ + /* Iterator State */ \ + bool PFX##_iter_start(struct SNAME##_iter *iter); \ + bool PFX##_iter_end(struct SNAME##_iter *iter); \ + /* Iterator Movement */ \ + void PFX##_iter_to_start(struct SNAME##_iter *iter); \ + void PFX##_iter_to_end(struct SNAME##_iter *iter); \ + bool PFX##_iter_next(struct SNAME##_iter *iter); \ + bool PFX##_iter_prev(struct SNAME##_iter *iter); \ + bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \ + bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \ + /* Iterator Access */ \ + V PFX##_iter_value(struct SNAME##_iter *iter); \ size_t PFX##_iter_index(struct SNAME##_iter *iter); /* ------------------------------------------------------------------------- @@ -245,13 +271,16 @@ struct cmc_callbacks_intervalheap static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_heap_); \ static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_heap_); \ \ - struct SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)) \ + struct SNAME *PFX##_new(size_t capacity, struct SNAME##_ftab_val *f_val) \ { \ struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ \ if (capacity == 0 || capacity == UINT64_MAX) \ return NULL; \ \ + if (!f_val) \ + return NULL; \ + \ struct SNAME *_heap_ = alloc->malloc(sizeof(struct SNAME)); \ \ if (!_heap_) \ @@ -273,24 +302,27 @@ struct cmc_callbacks_intervalheap _heap_->capacity = capacity; \ _heap_->size = 0; \ _heap_->count = 0; \ - _heap_->cmp = compare; \ - \ - _heap_->it_start = PFX##_impl_it_start; \ - _heap_->it_end = PFX##_impl_it_end; \ - \ + _heap_->flag = cmc_flags.OK; \ + _heap_->f_val = f_val; \ _heap_->alloc = alloc; \ _heap_->callbacks = NULL; \ + _heap_->it_start = PFX##_impl_it_start; \ + _heap_->it_end = PFX##_impl_it_end; \ \ return _heap_; \ } \ \ struct SNAME *PFX##_new_custom( \ - size_t capacity, int (*compare)(V, V), struct cmc_alloc_node *alloc, \ + size_t capacity, struct SNAME##_ftab_val *f_val, \ + struct cmc_alloc_node *alloc, \ struct cmc_callbacks_intervalheap *callbacks) \ { \ if (capacity == 0 || capacity == UINT64_MAX) \ return NULL; \ \ + if (!f_val) \ + return NULL; \ + \ if (!alloc) \ alloc = &cmc_alloc_node_default; \ \ @@ -315,24 +347,23 @@ struct cmc_callbacks_intervalheap _heap_->capacity = capacity; \ _heap_->size = 0; \ _heap_->count = 0; \ - _heap_->cmp = compare; \ - \ - _heap_->it_start = PFX##_impl_it_start; \ - _heap_->it_end = PFX##_impl_it_end; \ - \ + _heap_->flag = cmc_flags.OK; \ + _heap_->f_val = f_val; \ _heap_->alloc = alloc; \ _heap_->callbacks = callbacks; \ + _heap_->it_start = PFX##_impl_it_start; \ + _heap_->it_end = PFX##_impl_it_end; \ \ return _heap_; \ } \ \ - void PFX##_clear(struct SNAME *_heap_, void (*deallocator)(V)) \ + void PFX##_clear(struct SNAME *_heap_) \ { \ - if (deallocator) \ + if (_heap_->f_val->free) \ { \ for (size_t i = 0; i < _heap_->count; i++) \ { \ - deallocator(_heap_->buffer[i / 2].data[i % 2]); \ + _heap_->f_val->free(_heap_->buffer[i / 2].data[i % 2]); \ } \ } \ \ @@ -342,13 +373,13 @@ struct cmc_callbacks_intervalheap _heap_->count = 0; \ } \ \ - void PFX##_free(struct SNAME *_heap_, void (*deallocator)(V)) \ + void PFX##_free(struct SNAME *_heap_) \ { \ - if (deallocator) \ + if (_heap_->f_val->free) \ { \ for (size_t i = 0; i < _heap_->count; i++) \ { \ - deallocator(_heap_->buffer[i / 2].data[i % 2]); \ + _heap_->f_val->free(_heap_->buffer[i / 2].data[i % 2]); \ } \ } \ \ @@ -385,20 +416,19 @@ struct cmc_callbacks_intervalheap } \ else \ { \ - struct SNAME##_node *curr_node = \ - &(_heap_->buffer[_heap_->size - 1]); \ + struct SNAME##_node *node = &(_heap_->buffer[_heap_->size - 1]); \ \ /* Decide if the new element goes into the MinHeap or MaxHeap */ \ - if (_heap_->cmp(curr_node->data[0], element) > 0) \ + if (_heap_->f_val->cmp(node->data[0], element) > 0) \ { \ /* Swap current value and add new element to the MinHeap */ \ - curr_node->data[1] = curr_node->data[0]; \ - curr_node->data[0] = element; \ + node->data[1] = node->data[0]; \ + node->data[0] = element; \ } \ else \ { \ /* No need to swap and add the new element to the MaxHeap */ \ - curr_node->data[1] = element; \ + node->data[1] = element; \ } \ } \ \ @@ -411,9 +441,9 @@ struct cmc_callbacks_intervalheap struct SNAME##_node *parent = \ &(_heap_->buffer[(_heap_->size - 1) / 2]); \ \ - if (_heap_->cmp(parent->data[0], element) > 0) \ + if (_heap_->f_val->cmp(parent->data[0], element) > 0) \ PFX##_impl_float_up_min(_heap_); \ - else if (_heap_->cmp(parent->data[1], element) < 0) \ + else if (_heap_->f_val->cmp(parent->data[1], element) < 0) \ PFX##_impl_float_up_max(_heap_); \ /* else no float up required */ \ \ @@ -519,7 +549,7 @@ struct cmc_callbacks_intervalheap { \ _heap_->buffer[0].data[0] = element; \ } \ - else if (_heap_->cmp(element, _heap_->buffer[0].data[0]) < 0) \ + else if (_heap_->f_val->cmp(element, _heap_->buffer[0].data[0]) < 0) \ { \ /* Corner case: we are updating the Max value but it is less */ \ /* than the Min value */ \ @@ -548,7 +578,7 @@ struct cmc_callbacks_intervalheap { \ _heap_->buffer[0].data[0] = element; \ } \ - else if (_heap_->cmp(element, _heap_->buffer[0].data[1]) > 0) \ + else if (_heap_->f_val->cmp(element, _heap_->buffer[0].data[1]) > 0) \ { \ /* Corner case: we are updating the Min value but it is greater */ \ /* than the Max value. */ \ @@ -597,7 +627,8 @@ struct cmc_callbacks_intervalheap { \ for (size_t i = 0; i < _heap_->count; i++) \ { \ - if (_heap_->cmp(_heap_->buffer[i / 2].data[i % 2], element) == 0) \ + if (_heap_->f_val->cmp(_heap_->buffer[i / 2].data[i % 2], \ + element) == 0) \ return true; \ } \ \ @@ -650,7 +681,7 @@ struct cmc_callbacks_intervalheap return true; \ } \ \ - struct SNAME *PFX##_copy_of(struct SNAME *_heap_, V (*copy_func)(V)) \ + struct SNAME *PFX##_copy_of(struct SNAME *_heap_) \ { \ struct SNAME *result = _heap_->alloc->malloc(sizeof(struct SNAME)); \ \ @@ -668,11 +699,11 @@ struct cmc_callbacks_intervalheap return NULL; \ } \ \ - if (copy_func) \ + if (_heap_->f_val->cpy) \ { \ for (size_t i = 0; i < _heap_->count; i++) \ result->buffer[i / 2].data[i % 2] = \ - copy_func(_heap_->buffer[i / 2].data[i % 2]); \ + _heap_->f_val->cpy(_heap_->buffer[i / 2].data[i % 2]); \ } \ else \ memcpy(result->buffer, _heap_->buffer, \ @@ -694,7 +725,7 @@ struct cmc_callbacks_intervalheap V element1 = _heap1_->buffer[i / 2].data[i % 2]; \ V element2 = _heap2_->buffer[i / 2].data[i % 2]; \ \ - if (_heap1_->cmp(element1, element2) == 0) \ + if (_heap1_->f_val->cmp(element1, element2) == 0) \ return true; \ } \ \ @@ -708,14 +739,9 @@ struct cmc_callbacks_intervalheap \ int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_intervalheap, \ #SNAME, #V, h_, h_->buffer, h_->capacity, h_->size, \ - h_->count, h_->cmp, h_->alloc, h_->callbacks); \ + h_->count, h_->f_val, h_->alloc, h_->callbacks); \ \ - if (n < 0 || n == (int)cmc_string_len) \ - return (struct cmc_string){ 0 }; \ - \ - str.s[n] = '\0'; \ - \ - return str; \ + return n >= 0 ? str : (struct cmc_string){ 0 }; \ } \ \ struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \ @@ -900,7 +926,8 @@ struct cmc_callbacks_intervalheap { \ /* In this case, the current node has no MaxHeap value so */ \ /* we instead compare with the MinHeap value */ \ - if (_heap_->cmp(curr_node->data[0], parent->data[1]) < 0) \ + if (_heap_->f_val->cmp(curr_node->data[0], parent->data[1]) < \ + 0) \ break; \ \ /* Since the comparison above passed now we need to swap */ \ @@ -914,7 +941,8 @@ struct cmc_callbacks_intervalheap else \ { \ /* Usual case, just compare both MaxHeap values */ \ - if (_heap_->cmp(curr_node->data[1], parent->data[1]) < 0) \ + if (_heap_->f_val->cmp(curr_node->data[1], parent->data[1]) < \ + 0) \ break; \ \ /* Swap with parent and repeat */ \ @@ -943,7 +971,7 @@ struct cmc_callbacks_intervalheap \ struct SNAME##_node *parent = &(_heap_->buffer[P_index]); \ \ - if (_heap_->cmp(curr_node->data[0], parent->data[0]) >= 0) \ + if (_heap_->f_val->cmp(curr_node->data[0], parent->data[0]) >= 0) \ break; \ \ /* Swap with parent and repeat */ \ @@ -986,11 +1014,13 @@ struct cmc_callbacks_intervalheap /* then do the comparison with the MinHeap value */ \ if (R_index == _heap_->size - 1 && \ PFX##_count(_heap_) % 2 != 0) \ - child = _heap_->cmp(L->data[1], R->data[0]) > 0 ? L_index \ - : R_index; \ + child = _heap_->f_val->cmp(L->data[1], R->data[0]) > 0 \ + ? L_index \ + : R_index; \ else \ - child = _heap_->cmp(L->data[1], R->data[1]) > 0 ? L_index \ - : R_index; \ + child = _heap_->f_val->cmp(L->data[1], R->data[1]) > 0 \ + ? L_index \ + : R_index; \ } \ /* Pick the only one available */ \ else \ @@ -1005,7 +1035,8 @@ struct cmc_callbacks_intervalheap /* Odd case, compare with MinHeap value */ \ /* If current value is not less than the child node's */ \ /* value it is done */ \ - if (_heap_->cmp(curr_node->data[1], child_node->data[0]) >= 0) \ + if (_heap_->f_val->cmp(curr_node->data[1], \ + child_node->data[0]) >= 0) \ break; \ \ /* Otherwise swap and continue */ \ @@ -1017,7 +1048,8 @@ struct cmc_callbacks_intervalheap { \ /* If current value is not less than the child node's */ \ /* value it is done */ \ - if (_heap_->cmp(curr_node->data[1], child_node->data[1]) >= 0) \ + if (_heap_->f_val->cmp(curr_node->data[1], \ + child_node->data[1]) >= 0) \ break; \ \ /* Otherwise swap and continue */ \ @@ -1027,7 +1059,8 @@ struct cmc_callbacks_intervalheap \ /* Check if the MinHeap and MaxHeap values need to be */ \ /* swapped */ \ - if (_heap_->cmp(child_node->data[0], child_node->data[1]) > 0) \ + if (_heap_->f_val->cmp(child_node->data[0], \ + child_node->data[1]) > 0) \ { \ /* Swap because the MinHeap value is greater than the */ \ /* MaxHeap value */ \ @@ -1067,8 +1100,9 @@ struct cmc_callbacks_intervalheap struct SNAME##_node *L = &(_heap_->buffer[L_index]); \ struct SNAME##_node *R = &(_heap_->buffer[R_index]); \ \ - child = _heap_->cmp(L->data[0], R->data[0]) < 0 ? L_index \ - : R_index; \ + child = _heap_->f_val->cmp(L->data[0], R->data[0]) < 0 \ + ? L_index \ + : R_index; \ } \ /* Pick the only one available */ \ else \ @@ -1078,7 +1112,8 @@ struct cmc_callbacks_intervalheap \ /* If current value is smaller than the child node's value, it */ \ /* is done */ \ - if (_heap_->cmp(curr_node->data[0], child_node->data[0]) < 0) \ + if (_heap_->f_val->cmp(curr_node->data[0], child_node->data[0]) < \ + 0) \ break; \ \ /* Otherwise swap and continue */ \ @@ -1090,7 +1125,8 @@ struct cmc_callbacks_intervalheap /* MaxHeap values need to be swapped */ \ if (child != _heap_->size - 1 || PFX##_count(_heap_) % 2 == 0) \ { \ - if (_heap_->cmp(child_node->data[0], child_node->data[1]) > 0) \ + if (_heap_->f_val->cmp(child_node->data[0], \ + child_node->data[1]) > 0) \ { \ /* Swap because the MinHeap value is greater than the */ \ /* MaxHeap value */ \ diff --git a/tests/main/unt/heap.c b/tests/main/unt/heap.c index bb4a46c..b28dd77 100644 --- a/tests/main/unt/heap.c +++ b/tests/main/unt/heap.c @@ -7,32 +7,39 @@ CMC_GENERATE_HEAP(h, heap, size_t) +struct heap_ftab_val *h_ftab_val = &(struct heap_ftab_val){ .cmp = cmp, + .cpy = copy, + .str = str, + .free = custom_free, + .hash = hash, + .pri = pri }; + CMC_CREATE_UNIT(heap_test, true, { CMC_CREATE_TEST(new, { - struct heap *h = h_new(1000000, cmc_max_heap, cmp); + struct heap *h = h_new(1000000, cmc_max_heap, h_ftab_val); cmc_assert_not_equals(ptr, NULL, h); cmc_assert_not_equals(ptr, NULL, h->buffer); cmc_assert_equals(size_t, 1000000, h_capacity(h)); cmc_assert_equals(size_t, 0, h_count(h)); - h_free(h, NULL); + h_free(h); }); CMC_CREATE_TEST(new[edge_case capacity = 0], { - struct heap *h = h_new(0, cmc_max_heap, cmp); + struct heap *h = h_new(0, cmc_max_heap, h_ftab_val); cmc_assert_equals(ptr, NULL, h); }); CMC_CREATE_TEST(new[edge_case capacity = UINT64_MAX], { - struct heap *h = h_new(UINT64_MAX, cmc_max_heap, cmp); + struct heap *h = h_new(UINT64_MAX, cmc_max_heap, h_ftab_val); cmc_assert_equals(ptr, NULL, h); }); CMC_CREATE_TEST(clear[count capacity], { - struct heap *h = h_new(100, cmc_max_heap, cmp); + struct heap *h = h_new(100, cmc_max_heap, h_ftab_val); cmc_assert_not_equals(ptr, NULL, h); @@ -41,16 +48,16 @@ CMC_CREATE_UNIT(heap_test, true, { cmc_assert_equals(size_t, 50, h_count(h)); - h_clear(h, NULL); + h_clear(h); cmc_assert_equals(size_t, 0, h_count(h)); cmc_assert_equals(size_t, 100, h_capacity(h)); - h_free(h, NULL); + h_free(h); }); CMC_CREATE_TEST(buffer_growth[edge_case capacity = 1], { - struct heap *h = h_new(1, cmc_max_heap, cmp); + struct heap *h = h_new(1, cmc_max_heap, h_ftab_val); cmc_assert_not_equals(ptr, NULL, h); @@ -59,21 +66,21 @@ CMC_CREATE_UNIT(heap_test, true, { cmc_assert_equals(size_t, 50, h_count(h)); - h_free(h, NULL); + h_free(h); }); CMC_CREATE_TEST(insert, { - struct heap *h = h_new(100, cmc_max_heap, cmp); + struct heap *h = h_new(100, cmc_max_heap, h_ftab_val); cmc_assert_not_equals(ptr, NULL, h); cmc_assert(h_insert(h, 10)); - h_free(h, NULL); + h_free(h); }); CMC_CREATE_TEST(insert[item preservation], { - struct heap *h = h_new(50, cmc_max_heap, cmp); + struct heap *h = h_new(50, cmc_max_heap, h_ftab_val); cmc_assert_not_equals(ptr, NULL, h); @@ -86,11 +93,11 @@ CMC_CREATE_UNIT(heap_test, true, { cmc_assert_equals(size_t, 5050, sum); - h_free(h, NULL); + h_free(h); }); CMC_CREATE_TEST(remove, { - struct heap *h = h_new(50, cmc_max_heap, cmp); + struct heap *h = h_new(50, cmc_max_heap, h_ftab_val); cmc_assert_not_equals(ptr, NULL, h); @@ -102,22 +109,22 @@ CMC_CREATE_UNIT(heap_test, true, { cmc_assert_equals(size_t, 100, r); - h_free(h, NULL); + h_free(h); }); CMC_CREATE_TEST(remove[count = 0], { - struct heap *h = h_new(100, cmc_max_heap, cmp); + struct heap *h = h_new(100, cmc_max_heap, h_ftab_val); cmc_assert_not_equals(ptr, NULL, h); size_t _; cmc_assert(!h_remove(h, &_)); - h_free(h, NULL); + h_free(h); }); CMC_CREATE_TEST(remove[sorted], { - struct heap *h = h_new(100, cmc_min_heap, cmp); + struct heap *h = h_new(100, cmc_min_heap, h_ftab_val); cmc_assert_not_equals(ptr, NULL, h); @@ -136,11 +143,11 @@ CMC_CREATE_UNIT(heap_test, true, { cmc_assert_array_sorted_any(size_t, arr, cmp, 0, 99); - h_free(h, NULL); + h_free(h); }); CMC_CREATE_TEST(peek, { - struct heap *h = h_new(100, cmc_max_heap, cmp); + struct heap *h = h_new(100, cmc_max_heap, h_ftab_val); cmc_assert_not_equals(ptr, NULL, h); @@ -149,16 +156,16 @@ CMC_CREATE_UNIT(heap_test, true, { cmc_assert_equals(size_t, 100, h_peek(h)); - h_free(h, NULL); + h_free(h); }); CMC_CREATE_TEST(peek[count = 0], { - struct heap *h = h_new(100, cmc_max_heap, cmp); + struct heap *h = h_new(100, cmc_max_heap, h_ftab_val); cmc_assert_not_equals(ptr, NULL, h); cmc_assert_equals(size_t, (size_t){ 0 }, h_peek(h)); - h_free(h, NULL); + h_free(h); }); }); diff --git a/tests/main/unt/intervalheap.c b/tests/main/unt/intervalheap.c index cc1df47..8fbbc23 100644 --- a/tests/main/unt/intervalheap.c +++ b/tests/main/unt/intervalheap.c @@ -7,68 +7,76 @@ CMC_GENERATE_INTERVALHEAP(ih, intervalheap, size_t) +struct intervalheap_ftab_val *ih_ftab_val = + &(struct intervalheap_ftab_val){ .cmp = cmp, + .cpy = copy, + .str = str, + .free = custom_free, + .hash = hash, + .pri = pri }; + CMC_CREATE_UNIT(intervalheap_test, true, { CMC_CREATE_TEST(new, { - struct intervalheap *ih = ih_new(1000000, cmp); + struct intervalheap *ih = ih_new(1000000, ih_ftab_val); cmc_assert_not_equals(ptr, NULL, ih); cmc_assert_not_equals(ptr, NULL, ih->buffer); cmc_assert_equals(size_t, 500000, ih_capacity(ih)); cmc_assert_equals(size_t, 0, ih_count(ih)); - ih_free(ih, NULL); + ih_free(ih); }); CMC_CREATE_TEST(new[capacity = 0], { - struct intervalheap *ih = ih_new(0, cmp); + struct intervalheap *ih = ih_new(0, ih_ftab_val); cmc_assert_equals(ptr, NULL, ih); if (ih) - ih_free(ih, NULL); + ih_free(ih); }); CMC_CREATE_TEST(new[capacity], { - struct intervalheap *ih = ih_new(1, cmp); + struct intervalheap *ih = ih_new(1, ih_ftab_val); cmc_assert_not_equals(ptr, NULL, ih); cmc_assert_equals(size_t, 1, ih_capacity(ih)); - ih_free(ih, NULL); + ih_free(ih); - ih = ih_new(2, cmp); + ih = ih_new(2, ih_ftab_val); cmc_assert_not_equals(ptr, NULL, ih); cmc_assert_equals(size_t, 1, ih_capacity(ih)); - ih_free(ih, NULL); + ih_free(ih); - ih = ih_new(3, cmp); + ih = ih_new(3, ih_ftab_val); cmc_assert_not_equals(ptr, NULL, ih); cmc_assert_equals(size_t, 2, ih_capacity(ih)); - ih_free(ih, NULL); + ih_free(ih); - ih = ih_new(4, cmp); + ih = ih_new(4, ih_ftab_val); cmc_assert_not_equals(ptr, NULL, ih); cmc_assert_equals(size_t, 2, ih_capacity(ih)); - ih_free(ih, NULL); + ih_free(ih); }); CMC_CREATE_TEST(new[capacity = UINT64_MAX], { - struct intervalheap *ih = ih_new(UINT64_MAX, cmp); + struct intervalheap *ih = ih_new(UINT64_MAX, ih_ftab_val); cmc_assert_equals(ptr, NULL, ih); if (ih) - ih_free(ih, NULL); + ih_free(ih); }); CMC_CREATE_TEST(clear[count capacity], { - struct intervalheap *ih = ih_new(100, cmp); + struct intervalheap *ih = ih_new(100, ih_ftab_val); cmc_assert_not_equals(ptr, NULL, ih); @@ -77,16 +85,16 @@ CMC_CREATE_UNIT(intervalheap_test, true, { cmc_assert_equals(size_t, 50, ih_count(ih)); - ih_clear(ih, NULL); + ih_clear(ih); cmc_assert_equals(size_t, 0, ih_count(ih)); cmc_assert_equals(size_t, 50, ih_capacity(ih)); - ih_free(ih, NULL); + ih_free(ih); }); CMC_CREATE_TEST(buffer_growth[capacity = 1], { - struct intervalheap *ih = ih_new(1, cmp); + struct intervalheap *ih = ih_new(1, ih_ftab_val); cmc_assert_not_equals(ptr, NULL, ih); @@ -96,11 +104,11 @@ CMC_CREATE_UNIT(intervalheap_test, true, { cmc_assert_equals(size_t, 50, ih_count(ih)); cmc_assert_greater(size_t, 50, ih_capacity(ih) * 2); - ih_free(ih, NULL); + ih_free(ih); }); CMC_CREATE_TEST(insert[count], { - struct intervalheap *ih = ih_new(100, cmp); + struct intervalheap *ih = ih_new(100, ih_ftab_val); cmc_assert_not_equals(ptr, NULL, ih); @@ -109,11 +117,11 @@ CMC_CREATE_UNIT(intervalheap_test, true, { cmc_assert_equals(size_t, 2, ih_count(ih)); - ih_free(ih, NULL); + ih_free(ih); }); CMC_CREATE_TEST(insert[max min], { - struct intervalheap *ih = ih_new(1, cmp); + struct intervalheap *ih = ih_new(1, ih_ftab_val); cmc_assert_not_equals(ptr, NULL, ih); @@ -129,6 +137,6 @@ CMC_CREATE_UNIT(intervalheap_test, true, { cmc_assert_equals(size_t, 0, min); cmc_assert_equals(size_t, 1, max); - ih_free(ih, NULL); + ih_free(ih); }); });