diff --git a/src/cmc/queue.h b/src/cmc/queue.h index 77a20b5..33c8bf8 100644 --- a/src/cmc/queue.h +++ b/src/cmc/queue.h @@ -112,6 +112,7 @@ static const char *cmc_string_fmt_queue = "struct %s<%s> " "count:%" PRIuMAX ", " "front:%" PRIuMAX ", " "back:%" PRIuMAX ", " + "f_val:%p, " "alloc:%p, " "callbacks:%p }"; @@ -163,17 +164,45 @@ struct cmc_callbacks_queue /* Index representing the back of the queue */ \ size_t back; \ \ - /* Function that returns an iterator to the start of the queue */ \ - struct SNAME##_iter (*it_start)(struct SNAME *); \ + /* Flags indicating errors or success */ \ + int flag; \ \ - /* Function that returns an iterator to the end of the queue */ \ - 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_queue *callbacks; \ + \ + /* Function that returns an iterator to the start of the queue */ \ + struct SNAME##_iter (*it_start)(struct SNAME *); \ + \ + /* Function that returns an iterator to the end of the queue */ \ + 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); \ }; \ \ /* Queue Iterator */ \ @@ -197,12 +226,12 @@ struct cmc_callbacks_queue \ /* Collection Functions */ \ /* Collection Allocation and Deallocation */ \ - struct SNAME *PFX##_new(size_t capacity); \ - struct SNAME *PFX##_new_custom(size_t capacity, \ - struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_queue *callbacks); \ - void PFX##_clear(struct SNAME *_queue_, void (*deallocator)(V)); \ - void PFX##_free(struct SNAME *_queue_, void (*deallocator)(V)); \ + 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_queue *callbacks); \ + void PFX##_clear(struct SNAME *_queue_); \ + void PFX##_free(struct SNAME *_queue_); \ /* Customization of Allocation and Callbacks */ \ void PFX##_customize(struct SNAME *_queue_, struct cmc_alloc_node *alloc, \ struct cmc_callbacks_queue *callbacks); \ @@ -212,17 +241,15 @@ struct cmc_callbacks_queue /* Element Access */ \ V PFX##_peek(struct SNAME *_queue_); \ /* Collection State */ \ - bool PFX##_contains(struct SNAME *_queue_, V element, \ - int (*comparator)(V, V)); \ + bool PFX##_contains(struct SNAME *_queue_, V element); \ bool PFX##_empty(struct SNAME *_queue_); \ bool PFX##_full(struct SNAME *_queue_); \ size_t PFX##_count(struct SNAME *_queue_); \ size_t PFX##_capacity(struct SNAME *_queue_); \ /* Collection Utility */ \ bool PFX##_resize(struct SNAME *_queue_, size_t capacity); \ - struct SNAME *PFX##_copy_of(struct SNAME *_queue_, V (*copy_func)(V)); \ - bool PFX##_equals(struct SNAME *_queue1_, struct SNAME *_queue2_, \ - int (*comparator)(V, V)); \ + struct SNAME *PFX##_copy_of(struct SNAME *_queue_); \ + bool PFX##_equals(struct SNAME *_queue1_, struct SNAME *_queue2_); \ struct cmc_string PFX##_to_string(struct SNAME *_queue_); \ \ /* Iterator Functions */ \ @@ -256,13 +283,16 @@ struct cmc_callbacks_queue static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_queue_); \ static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_queue_); \ \ - struct SNAME *PFX##_new(size_t capacity) \ + struct SNAME *PFX##_new(size_t capacity, struct SNAME##_ftab_val *f_val) \ { \ struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \ \ if (capacity < 1) \ return NULL; \ \ + if (!f_val) \ + return NULL; \ + \ struct SNAME *_queue_ = alloc->malloc(sizeof(struct SNAME)); \ \ if (!_queue_) \ @@ -280,23 +310,26 @@ struct cmc_callbacks_queue _queue_->count = 0; \ _queue_->front = 0; \ _queue_->back = 0; \ - \ - _queue_->it_start = PFX##_impl_it_start; \ - _queue_->it_end = PFX##_impl_it_end; \ - \ + _queue_->flag = cmc_flags.OK; \ + _queue_->f_val = f_val; \ _queue_->alloc = alloc; \ _queue_->callbacks = NULL; \ + _queue_->it_start = PFX##_impl_it_start; \ + _queue_->it_end = PFX##_impl_it_end; \ \ return _queue_; \ } \ \ - struct SNAME *PFX##_new_custom(size_t capacity, \ - struct cmc_alloc_node *alloc, \ - struct cmc_callbacks_queue *callbacks) \ + struct SNAME *PFX##_new_custom( \ + size_t capacity, struct SNAME##_ftab_val *f_val, \ + struct cmc_alloc_node *alloc, struct cmc_callbacks_queue *callbacks) \ { \ if (capacity < 1) \ return NULL; \ \ + if (!f_val) \ + return NULL; \ + \ if (!alloc) \ alloc = &cmc_alloc_node_default; \ \ @@ -317,23 +350,23 @@ struct cmc_callbacks_queue _queue_->count = 0; \ _queue_->front = 0; \ _queue_->back = 0; \ - \ - _queue_->it_start = PFX##_impl_it_start; \ - _queue_->it_end = PFX##_impl_it_end; \ - \ + _queue_->flag = cmc_flags.OK; \ + _queue_->f_val = f_val; \ _queue_->alloc = alloc; \ _queue_->callbacks = callbacks; \ + _queue_->it_start = PFX##_impl_it_start; \ + _queue_->it_end = PFX##_impl_it_end; \ \ return _queue_; \ } \ \ - void PFX##_clear(struct SNAME *_queue_, void (*deallocator)(V)) \ + void PFX##_clear(struct SNAME *_queue_) \ { \ - if (deallocator) \ + if (_queue_->f_val->free) \ { \ for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) \ { \ - deallocator(_queue_->buffer[i]); \ + _queue_->f_val->free(_queue_->buffer[i]); \ \ i = (i + 1) % _queue_->capacity; \ } \ @@ -346,13 +379,13 @@ struct cmc_callbacks_queue _queue_->back = 0; \ } \ \ - void PFX##_free(struct SNAME *_queue_, void (*deallocator)(V)) \ + void PFX##_free(struct SNAME *_queue_) \ { \ - if (deallocator) \ + if (_queue_->f_val->free) \ { \ for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) \ { \ - deallocator(_queue_->buffer[i]); \ + _queue_->f_val->free(_queue_->buffer[i]); \ \ i = (i + 1) % _queue_->capacity; \ } \ @@ -412,12 +445,11 @@ struct cmc_callbacks_queue return _queue_->buffer[_queue_->front]; \ } \ \ - bool PFX##_contains(struct SNAME *_queue_, V element, \ - int (*comparator)(V, V)) \ + bool PFX##_contains(struct SNAME *_queue_, V element) \ { \ for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) \ { \ - if (comparator(_queue_->buffer[i], element) == 0) \ + if (_queue_->f_val->cmp(_queue_->buffer[i], element) == 0) \ return true; \ \ i = (i + 1) % _queue_->capacity; \ @@ -463,7 +495,7 @@ struct cmc_callbacks_queue { \ new_buffer[j] = _queue_->buffer[i]; \ \ - i = (i + 1) % PFX##_capacity(_queue_); \ + i = (i + 1) % _queue_->capacity; \ } \ \ _queue_->alloc->free(_queue_->buffer); \ @@ -476,19 +508,20 @@ struct cmc_callbacks_queue return true; \ } \ \ - struct SNAME *PFX##_copy_of(struct SNAME *_queue_, V (*copy_func)(V)) \ + struct SNAME *PFX##_copy_of(struct SNAME *_queue_) \ { \ - struct SNAME *result = PFX##_new_custom( \ - _queue_->capacity, _queue_->alloc, _queue_->callbacks); \ + struct SNAME *result = \ + PFX##_new_custom(_queue_->capacity, _queue_->f_val, \ + _queue_->alloc, _queue_->callbacks); \ \ if (!result) \ return NULL; \ \ - if (copy_func) \ + if (_queue_->f_val->cpy) \ { \ for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) \ { \ - result->buffer[j] = copy_func(_queue_->buffer[i]); \ + result->buffer[j] = _queue_->f_val->cpy(_queue_->buffer[i]); \ \ i = (i + 1) % _queue_->capacity; \ } \ @@ -510,8 +543,7 @@ struct cmc_callbacks_queue return result; \ } \ \ - bool PFX##_equals(struct SNAME *_queue1_, struct SNAME *_queue2_, \ - int (*comparator)(V, V)) \ + bool PFX##_equals(struct SNAME *_queue1_, struct SNAME *_queue2_) \ { \ if (PFX##_count(_queue1_) != PFX##_count(_queue2_)) \ return false; \ @@ -520,7 +552,8 @@ struct cmc_callbacks_queue for (i = _queue1_->front, j = _queue2_->front, k = 0; \ k < PFX##_count(_queue1_); k++) \ { \ - if (comparator(_queue1_->buffer[i], _queue2_->buffer[j]) != 0) \ + if (_queue1_->f_val->cmp(_queue1_->buffer[i], \ + _queue2_->buffer[j]) != 0) \ return false; \ \ i = (i + 1) % _queue1_->capacity; \ @@ -535,16 +568,12 @@ struct cmc_callbacks_queue struct cmc_string str; \ struct SNAME *q_ = _queue_; \ \ - int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_queue, #SNAME, \ - #V, q_, q_->buffer, q_->capacity, q_->count, \ - q_->front, q_->back, q_->alloc, q_->callbacks); \ + int n = \ + snprintf(str.s, cmc_string_len, cmc_string_fmt_queue, #SNAME, #V, \ + q_, q_->buffer, q_->capacity, q_->count, q_->front, \ + q_->back, q_->f_val, q_->alloc, q_->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) \ diff --git a/tests/main/unt/queue.c b/tests/main/unt/queue.c index 2b33349..31df9be 100644 --- a/tests/main/unt/queue.c +++ b/tests/main/unt/queue.c @@ -7,9 +7,17 @@ CMC_GENERATE_QUEUE(q, queue, size_t) +struct queue_ftab_val *q_ftab_val = + &(struct queue_ftab_val){ .cmp = cmp, + .cpy = copy, + .str = str, + .free = custom_free, + .hash = hash, + .pri = pri }; + CMC_CREATE_UNIT(queue_test, true, { CMC_CREATE_TEST(new, { - struct queue *q = q_new(1000000); + struct queue *q = q_new(1000000, q_ftab_val); cmc_assert_not_equals(ptr, NULL, q); cmc_assert_not_equals(ptr, NULL, q->buffer); @@ -17,23 +25,23 @@ CMC_CREATE_UNIT(queue_test, true, { cmc_assert_equals(size_t, 0, q_count(q)); cmc_assert_not_equals(ptr, NULL, q->buffer); - q_free(q, NULL); + q_free(q); }); CMC_CREATE_TEST(new[capacity = 0], { - struct queue *q = q_new(0); + struct queue *q = q_new(0, q_ftab_val); cmc_assert_equals(ptr, NULL, q); }); CMC_CREATE_TEST(new[capacity = UINT64_MAX], { - struct queue *q = q_new(UINT64_MAX); + struct queue *q = q_new(UINT64_MAX, q_ftab_val); cmc_assert_equals(ptr, NULL, q); }); CMC_CREATE_TEST(clear[count capacity], { - struct queue *q = q_new(100); + struct queue *q = q_new(100, q_ftab_val); cmc_assert_not_equals(ptr, NULL, q); @@ -42,16 +50,16 @@ CMC_CREATE_UNIT(queue_test, true, { cmc_assert_equals(size_t, 50, q_count(q)); - q_clear(q, NULL); + q_clear(q); cmc_assert_equals(size_t, 0, q_count(q)); cmc_assert_equals(size_t, 100, q_capacity(q)); - q_free(q, NULL); + q_free(q); }); CMC_CREATE_TEST(buffer_growth[capacity = 1], { - struct queue *q = q_new(1); + struct queue *q = q_new(1, q_ftab_val); cmc_assert_not_equals(ptr, NULL, q); @@ -60,11 +68,11 @@ CMC_CREATE_UNIT(queue_test, true, { cmc_assert_equals(size_t, 50, q_count(q)); - q_free(q, NULL); + q_free(q); }); CMC_CREATE_TEST(buffer_growth[item preservation], { - struct queue *q = q_new(100); + struct queue *q = q_new(100, q_ftab_val); cmc_assert_not_equals(ptr, NULL, q); @@ -81,11 +89,11 @@ CMC_CREATE_UNIT(queue_test, true, { cmc_assert_equals(size_t, 1200, q_count(q)); cmc_assert_equals(size_t, 720600, sum); - q_free(q, NULL); + q_free(q); }); CMC_CREATE_TEST(enqueue[count capacity], { - struct queue *q = q_new(100); + struct queue *q = q_new(100, q_ftab_val); cmc_assert_not_equals(ptr, NULL, q); @@ -95,11 +103,11 @@ CMC_CREATE_UNIT(queue_test, true, { cmc_assert_equals(size_t, 150, q_count(q)); cmc_assert_greater(size_t, 100, q_capacity(q)); - q_free(q, NULL); + q_free(q); }); CMC_CREATE_TEST(enqueue[item preservation], { - struct queue *q = q_new(100); + struct queue *q = q_new(100, q_ftab_val); cmc_assert_not_equals(ptr, NULL, q); @@ -116,11 +124,11 @@ CMC_CREATE_UNIT(queue_test, true, { cmc_assert_equals(size_t, 5050, sum); - q_free(q, NULL); + q_free(q); }); CMC_CREATE_TEST(dequeue[count capacity], { - struct queue *q = q_new(100); + struct queue *q = q_new(100, q_ftab_val); cmc_assert_not_equals(ptr, NULL, q); @@ -134,11 +142,11 @@ CMC_CREATE_UNIT(queue_test, true, { cmc_assert_equals(size_t, 0, q_count(q)); - q_free(q, NULL); + q_free(q); }); CMC_CREATE_TEST(dequeue[item preservation], { - struct queue *q = q_new(100); + struct queue *q = q_new(100, q_ftab_val); cmc_assert_not_equals(ptr, NULL, q); @@ -158,11 +166,11 @@ CMC_CREATE_UNIT(queue_test, true, { cmc_assert_equals(size_t, 5050, sum); - q_free(q, NULL); + q_free(q); }); CMC_CREATE_TEST(peek[count = 0], { - struct queue *q = q_new(100); + struct queue *q = q_new(100, q_ftab_val); cmc_assert_not_equals(ptr, NULL, q); @@ -170,11 +178,11 @@ CMC_CREATE_UNIT(queue_test, true, { cmc_assert_equals(size_t, (size_t){ 0 }, r); - q_free(q, NULL); + q_free(q); }); CMC_CREATE_TEST(peek[sum], { - struct queue *q = q_new(100); + struct queue *q = q_new(100, q_ftab_val); cmc_assert_not_equals(ptr, NULL, q); @@ -194,11 +202,11 @@ CMC_CREATE_UNIT(queue_test, true, { cmc_assert_equals(size_t, 5050, sum); - q_free(q, NULL); + q_free(q); }); CMC_CREATE_TEST(contains, { - struct queue *q = q_new(100); + struct queue *q = q_new(100, q_ftab_val); cmc_assert_not_equals(ptr, NULL, q); @@ -206,43 +214,43 @@ CMC_CREATE_UNIT(queue_test, true, { cmc_assert(q_enqueue(q, i)); for (size_t i = 1; i <= 20; i++) - cmc_assert(q_contains(q, i, cmp)); + cmc_assert(q_contains(q, i)); - q_clear(q, NULL); + q_clear(q); for (size_t i = 1; i <= 20; i++) - cmc_assert(!q_contains(q, i, cmp)); + cmc_assert(!q_contains(q, i)); - q_free(q, NULL); + q_free(q); }); CMC_CREATE_TEST(contains[count = 0], { - struct queue *q = q_new(100); + struct queue *q = q_new(100, q_ftab_val); cmc_assert_not_equals(ptr, NULL, q); - cmc_assert(!q_contains(q, 10, cmp)); + cmc_assert(!q_contains(q, 10)); - q_free(q, NULL); + q_free(q); }); CMC_CREATE_TEST(contains[count = 1], { - struct queue *q = q_new(100); + struct queue *q = q_new(100, q_ftab_val); cmc_assert_not_equals(ptr, NULL, q); - cmc_assert(!q_contains(q, 10, cmp)); + cmc_assert(!q_contains(q, 10)); cmc_assert(q_enqueue(q, 100)); - cmc_assert(q_contains(q, 100, cmp)); - cmc_assert(!q_contains(q, 101, cmp)); + cmc_assert(q_contains(q, 100)); + cmc_assert(!q_contains(q, 101)); - q_free(q, NULL); + q_free(q); }); CMC_CREATE_TEST(empty, { - struct queue *q = q_new(100); + struct queue *q = q_new(100, q_ftab_val); cmc_assert_not_equals(ptr, NULL, q); @@ -252,11 +260,11 @@ CMC_CREATE_UNIT(queue_test, true, { cmc_assert(!q_empty(q)); - q_free(q, NULL); + q_free(q); }); CMC_CREATE_TEST(full, { - struct queue *q = q_new(100); + struct queue *q = q_new(100, q_ftab_val); cmc_assert_not_equals(ptr, NULL, q); @@ -267,11 +275,11 @@ CMC_CREATE_UNIT(queue_test, true, { cmc_assert(q_full(q)); - q_free(q, NULL); + q_free(q); }); CMC_CREATE_TEST(count, { - struct queue *q = q_new(100); + struct queue *q = q_new(100, q_ftab_val); cmc_assert_not_equals(ptr, NULL, q); @@ -282,21 +290,21 @@ CMC_CREATE_UNIT(queue_test, true, { cmc_assert_equals(size_t, 100, q_count(q)); - q_free(q, NULL); + q_free(q); }); CMC_CREATE_TEST(capacity, { - struct queue *q = q_new(100); + struct queue *q = q_new(100, q_ftab_val); cmc_assert_not_equals(ptr, NULL, q); cmc_assert_equals(size_t, 100, q_capacity(q)); - q_free(q, NULL); + q_free(q); }); CMC_CREATE_TEST(resize, { - struct queue *q = q_new(100); + struct queue *q = q_new(100, q_ftab_val); cmc_assert_not_equals(ptr, NULL, q); @@ -307,11 +315,11 @@ CMC_CREATE_UNIT(queue_test, true, { cmc_assert(q_resize(q, q_count(q))); cmc_assert_equals(size_t, 150, q_capacity(q)); - q_free(q, NULL); + q_free(q); }); CMC_CREATE_TEST(resize[item preservation], { - struct queue *q = q_new(100); + struct queue *q = q_new(100, q_ftab_val); cmc_assert_not_equals(ptr, NULL, q); @@ -330,18 +338,18 @@ CMC_CREATE_UNIT(queue_test, true, { cmc_assert_equals(size_t, 11325, sum); - q_free(q, NULL); + q_free(q); }); CMC_CREATE_TEST(copy_of, { - struct queue *d1 = q_new(100); + struct queue *d1 = q_new(100, q_ftab_val); cmc_assert_not_equals(ptr, NULL, d1); for (size_t i = 1; i <= 150; i++) cmc_assert(q_enqueue(d1, i)); - struct queue *d2 = q_copy_of(d1, NULL); + struct queue *d2 = q_copy_of(d1); cmc_assert_not_equals(ptr, NULL, d2); cmc_assert_equals(size_t, q_count(d1), q_count(d2)); @@ -354,13 +362,13 @@ CMC_CREATE_UNIT(queue_test, true, { i2 = (i2 + 1) % d2->capacity; } - q_free(d1, NULL); - q_free(d2, NULL); + q_free(d1); + q_free(d2); }); CMC_CREATE_TEST(equals, { - struct queue *d1 = q_new(100); - struct queue *d2 = q_new(100); + struct queue *d1 = q_new(100, q_ftab_val); + struct queue *d2 = q_new(100, q_ftab_val); cmc_assert_not_equals(ptr, NULL, d1); cmc_assert_not_equals(ptr, NULL, d2); @@ -371,14 +379,14 @@ CMC_CREATE_UNIT(queue_test, true, { cmc_assert(q_enqueue(d2, i)); } - cmc_assert(q_equals(d1, d2, cmp)); + cmc_assert(q_equals(d1, d2)); - q_free(d1, NULL); - q_free(d2, NULL); + q_free(d1); + q_free(d2); }); CMC_CREATE_TEST(equals[from copy], { - struct queue *d1 = q_new(100); + struct queue *d1 = q_new(100, q_ftab_val); cmc_assert_not_equals(ptr, NULL, d1); @@ -387,28 +395,28 @@ CMC_CREATE_UNIT(queue_test, true, { cmc_assert(q_enqueue(d1, i)); } - struct queue *d2 = q_copy_of(d1, NULL); + struct queue *d2 = q_copy_of(d1); cmc_assert_not_equals(ptr, NULL, d2); - cmc_assert(q_equals(d1, d2, cmp)); + cmc_assert(q_equals(d1, d2)); - q_free(d1, NULL); - q_free(d2, NULL); + q_free(d1); + q_free(d2); }); CMC_CREATE_TEST(equals[count = 0], { - struct queue *d1 = q_new(100); + struct queue *d1 = q_new(100, q_ftab_val); cmc_assert_not_equals(ptr, NULL, d1); - struct queue *d2 = q_copy_of(d1, NULL); + struct queue *d2 = q_copy_of(d1); cmc_assert_not_equals(ptr, NULL, d2); - cmc_assert(q_equals(d1, d2, cmp)); + cmc_assert(q_equals(d1, d2)); - q_free(d1, NULL); - q_free(d2, NULL); + q_free(d1); + q_free(d2); }); });