diff --git a/src/queue.h b/src/queue.h index 0ee201f..3bbb12f 100644 --- a/src/queue.h +++ b/src/queue.h @@ -53,6 +53,8 @@ struct SNAME##_s *target; \ size_t cursor; \ size_t count; \ + bool start; \ + bool end; \ }; \ \ /* HEADER ********************************************************************/ @@ -74,167 +76,231 @@ FMOD size_t PFX##_capacity(SNAME *_queue_); \ \ FMOD void PFX##_iter(SNAME##_iter *iter, SNAME *target); \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ + FMOD void PFX##_iter_tostart(SNAME##_iter *iter); \ + FMOD void PFX##_iter_toend(SNAME##_iter *iter); \ FMOD bool PFX##_iter_next(SNAME##_iter *iter, T *result, size_t *index); \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter, T *result, size_t *index); \ \ /* SOURCE ********************************************************************/ -#define QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, K, T) \ - \ - FMOD bool PFX##_grow(SNAME *_queue_); \ - \ - FMOD SNAME *PFX##_new(size_t size) \ - { \ - if (size < 1) \ - return NULL; \ - \ - SNAME *_queue_ = malloc(sizeof(SNAME)); \ - \ - if (!_queue_) \ - return NULL; \ - \ - _queue_->buffer = malloc(sizeof(T) * size); \ - \ - if (!_queue_->buffer) \ - { \ - free(_queue_); \ - return NULL; \ - } \ - \ - for (size_t i = 0; i < size; i++) \ - { \ - _queue_->buffer[i] = 0; \ - } \ - \ - _queue_->capacity = size; \ - _queue_->count = 0; \ - _queue_->front = 0; \ - _queue_->rear = 0; \ - \ - return _queue_; \ - } \ - \ - FMOD void PFX##_free(SNAME *_queue_) \ - { \ - free(_queue_->buffer); \ - free(_queue_); \ - } \ - \ - FMOD bool PFX##_enqueue(SNAME *_queue_, T element) \ - { \ - if (PFX##_full(_queue_)) \ - { \ - if (!PFX##_grow(_queue_)) \ - return false; \ - } \ - \ - _queue_->buffer[_queue_->rear] = element; \ - \ - _queue_->rear = (_queue_->rear == _queue_->capacity - 1) ? 0 : _queue_->rear + 1; \ - _queue_->count++; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_dequeue(SNAME *_queue_) \ - { \ - if (PFX##_empty(_queue_)) \ - return false; \ - \ - _queue_->buffer[_queue_->front] = 0; \ - \ - _queue_->front = (_queue_->front == _queue_->capacity - 1) ? 0 : _queue_->front + 1; \ - _queue_->count--; \ - \ - return true; \ - } \ - \ - FMOD T PFX##_peek(SNAME *_queue_) \ - { \ - if (PFX##_empty(_queue_)) \ - return 0; \ - \ - return _queue_->buffer[_queue_->front]; \ - } \ - \ - FMOD bool PFX##_enqueue_if(SNAME *_queue_, T 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 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 bool PFX##_grow(SNAME *_queue_) \ - { \ - \ - size_t new_capacity = _queue_->capacity * 2; \ - \ - T *new_buffer = malloc(sizeof(T) * 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_->rear = _queue_->count; \ - \ - return true; \ - } \ - \ - FMOD void PFX##_iter(SNAME##_iter *iter, SNAME *target) \ - { \ - iter->target = target; \ - iter->cursor = target->front; \ - iter->count = 0; \ - } \ - \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter, T *result, size_t *index) \ - { \ - if (iter->count < iter->target->count) \ - { \ - *result = iter->target->buffer[iter->cursor]; \ - iter->cursor = (iter->cursor + 1) % (iter->target->capacity); \ - *index = iter->count; \ - iter->count++; \ - return true; \ - } \ - \ - return false; \ +#define QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, K, T) \ + \ + FMOD bool PFX##_grow(SNAME *_queue_); \ + \ + FMOD SNAME *PFX##_new(size_t size) \ + { \ + if (size < 1) \ + return NULL; \ + \ + SNAME *_queue_ = malloc(sizeof(SNAME)); \ + \ + if (!_queue_) \ + return NULL; \ + \ + _queue_->buffer = malloc(sizeof(T) * size); \ + \ + if (!_queue_->buffer) \ + { \ + free(_queue_); \ + return NULL; \ + } \ + \ + for (size_t i = 0; i < size; i++) \ + { \ + _queue_->buffer[i] = 0; \ + } \ + \ + _queue_->capacity = size; \ + _queue_->count = 0; \ + _queue_->front = 0; \ + _queue_->rear = 0; \ + \ + return _queue_; \ + } \ + \ + FMOD void PFX##_free(SNAME *_queue_) \ + { \ + free(_queue_->buffer); \ + free(_queue_); \ + } \ + \ + FMOD bool PFX##_enqueue(SNAME *_queue_, T element) \ + { \ + if (PFX##_full(_queue_)) \ + { \ + if (!PFX##_grow(_queue_)) \ + return false; \ + } \ + \ + _queue_->buffer[_queue_->rear] = element; \ + \ + _queue_->rear = (_queue_->rear == _queue_->capacity - 1) ? 0 : _queue_->rear + 1; \ + _queue_->count++; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_dequeue(SNAME *_queue_) \ + { \ + if (PFX##_empty(_queue_)) \ + return false; \ + \ + _queue_->buffer[_queue_->front] = 0; \ + \ + _queue_->front = (_queue_->front == _queue_->capacity - 1) ? 0 : _queue_->front + 1; \ + _queue_->count--; \ + \ + return true; \ + } \ + \ + FMOD T PFX##_peek(SNAME *_queue_) \ + { \ + if (PFX##_empty(_queue_)) \ + return 0; \ + \ + return _queue_->buffer[_queue_->front]; \ + } \ + \ + FMOD bool PFX##_enqueue_if(SNAME *_queue_, T 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 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 bool PFX##_grow(SNAME *_queue_) \ + { \ + \ + size_t new_capacity = _queue_->capacity * 2; \ + \ + T *new_buffer = malloc(sizeof(T) * 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_->rear = _queue_->count; \ + \ + return true; \ + } \ + \ + FMOD void PFX##_iter(SNAME##_iter *iter, SNAME *target) \ + { \ + iter->target = target; \ + iter->cursor = target->front; \ + iter->count = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + } \ + \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ + { \ + return iter->cursor == iter->target->front && iter->start; \ + } \ + \ + FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ + { \ + size_t real_rear = iter->target->rear == 0 ? iter->target->capacity - 1 : iter->target->rear - 1; \ + return iter->cursor == real_rear && iter->end; \ + } \ + \ + FMOD void PFX##_iter_tostart(SNAME##_iter *iter) \ + { \ + iter->cursor = iter->target->front; \ + iter->count = 0; \ + iter->start = true; \ + iter->end = false; \ + } \ + \ + FMOD void PFX##_iter_toend(SNAME##_iter *iter) \ + { \ + if (PFX##_empty(iter->target)) \ + iter->cursor = 0; \ + else \ + iter->cursor = (iter->target->rear == 0) ? iter->target->count - 1 : iter->target->rear - 1; \ + \ + iter->count = iter->target->count - 1; \ + iter->start = false; \ + iter->end = true; \ + } \ + \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter, T *result, size_t *index) \ + { \ + if (iter->end) \ + return false; \ + \ + *index = iter->count; \ + *result = iter->target->buffer[iter->cursor]; \ + iter->start = false; \ + \ + if (iter->count == iter->target->count - 1) \ + iter->end = true; \ + else \ + { \ + iter->cursor = (iter->cursor + 1) % (iter->target->capacity); \ + iter->count++; \ + } \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter, T *result, size_t *index) \ + { \ + if (iter->start) \ + return false; \ + \ + *index = iter->count; \ + *result = iter->target->buffer[iter->cursor]; \ + iter->end = false; \ + \ + if (iter->count == 0) \ + iter->start = true; \ + else \ + { \ + iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; \ + iter->count--; \ + } \ + \ + return true; \ } #endif /* CMC_QUEUE_H */ diff --git a/tests/foreach.c b/tests/foreach.c index fb899a7..af147c6 100644 --- a/tests/foreach.c +++ b/tests/foreach.c @@ -80,9 +80,9 @@ int main(int argc, char const *argv[]) sum1 += var; }) - // FOR_EACH_REV(q, queue, , int, q, { - // sum2 += var; - // }) + FOR_EACH_REV(q, queue, , int, q, { + sum2 += var; + }) // FOR_EACH_REV(d, deque, , int, d, { // sum3 += var; @@ -96,8 +96,8 @@ int main(int argc, char const *argv[]) printf("%10s PASSED\n", "LIST"); if (sum1 == 50005000) printf("%10s PASSED\n", "STACK"); - // if (sum2 == 50005000) - // printf("%10s PASSED\n", "QUEUE"); + if (sum2 == 50005000) + printf("%10s PASSED\n", "QUEUE"); // if (sum3 == 50005000) // printf("%10s PASSED\n", "DEQUE"); if (sum4 == 50005000) diff --git a/tests/iterators/queue.c b/tests/iterators/queue.c new file mode 100644 index 0000000..a24a694 --- /dev/null +++ b/tests/iterators/queue.c @@ -0,0 +1,53 @@ +// Checks if the queue iterator can go back and forward in the queue without +// hitting invalid states or a null pointer. Check is done visually. +#include +#include +#include +#include +#include "../../src/queue.h" + +QUEUE_GENERATE(q, queue, static, , int) + +int main(int argc, char const *argv[]) +{ + size_t i; + int r; + + // Initliazie queue and add some elements + queue *q = q_new(10); + for (int i = 0; i < 10; i++) + q_enqueue(q, i); + + // Initialize iterator + queue_iter iter; + q_iter(&iter, q); + + // Make the iterator go back and forward + for (int j = 0; j < 4; j++) + { + while (q_iter_next(&iter, &r, &i)) + printf("C[%2d] = %2d\n", i, r); + printf("\n"); + while (q_iter_prev(&iter, &r, &i)) + printf("C[%2d] = %2d\n", i, r); + printf("\n\n"); + } + + for (q_iter_tostart(&iter); !q_iter_end(&iter); /**/) + { + q_iter_next(&iter, &r, &i); + printf("Q[%2d] = %2d\n", i, r); + } + + printf("\n"); + + for (q_iter_toend(&iter); !q_iter_start(&iter); /**/) + { + q_iter_prev(&iter, &r, &i); + printf("Q[%2d] = %2d\n", i, r); + } + + q_free(q); + + return 0; +}