diff --git a/src/deque.h b/src/deque.h index 3a3896a..d0c8c87 100644 --- a/src/deque.h +++ b/src/deque.h @@ -53,6 +53,8 @@ struct SNAME##_s *target; \ size_t cursor; \ size_t count; \ + bool start; \ + bool end; \ }; \ \ /* HEADER ********************************************************************/ @@ -79,222 +81,286 @@ FMOD size_t PFX##_capacity(SNAME *_deque_); \ \ 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 DEQUE_GENERATE_SOURCE(PFX, SNAME, FMOD, K, T) \ - \ - FMOD bool PFX##_grow(SNAME *_deque_); \ - \ - FMOD SNAME *PFX##_new(size_t size) \ - { \ - if (size < 1) \ - return NULL; \ - \ - SNAME *_deque_ = malloc(sizeof(SNAME)); \ - \ - if (!_deque_) \ - return NULL; \ - \ - _deque_->buffer = malloc(sizeof(T) * size); \ - \ - if (!_deque_->buffer) \ - { \ - free(_deque_); \ - return NULL; \ - } \ - \ - for (size_t i = 0; i < size; i++) \ - _deque_->buffer[i] = 0; \ - \ - _deque_->capacity = size; \ - _deque_->count = 0; \ - _deque_->front = 0; \ - _deque_->rear = 0; \ - \ - return _deque_; \ - } \ - \ - FMOD void PFX##_free(SNAME *_deque_) \ - { \ - free(_deque_->buffer); \ - free(_deque_); \ - } \ - \ - FMOD bool PFX##_push_front(SNAME *_deque_, T element) \ - { \ - if (PFX##_full(_deque_)) \ - { \ - if (!PFX##_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_, T element) \ - { \ - if (PFX##_full(_deque_)) \ - { \ - if (!PFX##_grow(_deque_)) \ - return false; \ - } \ - \ - _deque_->buffer[_deque_->rear] = element; \ - \ - _deque_->rear = (_deque_->rear == _deque_->capacity - 1) ? 0 : _deque_->rear + 1; \ - \ - _deque_->count++; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_pop_front(SNAME *_deque_) \ - { \ - if (PFX##_empty(_deque_)) \ - return false; \ - \ - _deque_->buffer[_deque_->front] = 0; \ - \ - _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_->rear = (_deque_->rear == 0) ? _deque_->capacity - 1 : _deque_->rear - 1; \ - \ - _deque_->buffer[_deque_->rear] = 0; \ - \ - _deque_->count--; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_push_front_if(SNAME *_deque_, T element, bool condition) \ - { \ - if (condition) \ - return PFX##_push_front(_deque_, element); \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_push_back_if(SNAME *_deque_, T 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 T PFX##_back(SNAME *_deque_) \ - { \ - if (PFX##_empty(_deque_)) \ - return 0; \ - \ - return _deque_->buffer[(_deque_->rear == 0) ? _deque_->capacity - 1 : _deque_->rear - 1]; \ - } \ - \ - FMOD T PFX##_front(SNAME *_deque_) \ - { \ - if (PFX##_empty(_deque_)) \ - return 0; \ - \ - return _deque_->buffer[_deque_->front]; \ - } \ - \ - 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 bool PFX##_grow(SNAME *_deque_) \ - { \ - \ - size_t new_capacity = _deque_->capacity * 2; \ - \ - T *new_buffer = malloc(sizeof(T) * 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_->rear = _deque_->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 DEQUE_GENERATE_SOURCE(PFX, SNAME, FMOD, K, T) \ + \ + FMOD bool PFX##_grow(SNAME *_deque_); \ + \ + FMOD SNAME *PFX##_new(size_t size) \ + { \ + if (size < 1) \ + return NULL; \ + \ + SNAME *_deque_ = malloc(sizeof(SNAME)); \ + \ + if (!_deque_) \ + return NULL; \ + \ + _deque_->buffer = malloc(sizeof(T) * size); \ + \ + if (!_deque_->buffer) \ + { \ + free(_deque_); \ + return NULL; \ + } \ + \ + for (size_t i = 0; i < size; i++) \ + _deque_->buffer[i] = 0; \ + \ + _deque_->capacity = size; \ + _deque_->count = 0; \ + _deque_->front = 0; \ + _deque_->rear = 0; \ + \ + return _deque_; \ + } \ + \ + FMOD void PFX##_free(SNAME *_deque_) \ + { \ + free(_deque_->buffer); \ + free(_deque_); \ + } \ + \ + FMOD bool PFX##_push_front(SNAME *_deque_, T element) \ + { \ + if (PFX##_full(_deque_)) \ + { \ + if (!PFX##_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_, T element) \ + { \ + if (PFX##_full(_deque_)) \ + { \ + if (!PFX##_grow(_deque_)) \ + return false; \ + } \ + \ + _deque_->buffer[_deque_->rear] = element; \ + \ + _deque_->rear = (_deque_->rear == _deque_->capacity - 1) ? 0 : _deque_->rear + 1; \ + \ + _deque_->count++; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_pop_front(SNAME *_deque_) \ + { \ + if (PFX##_empty(_deque_)) \ + return false; \ + \ + _deque_->buffer[_deque_->front] = 0; \ + \ + _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_->rear = (_deque_->rear == 0) ? _deque_->capacity - 1 : _deque_->rear - 1; \ + \ + _deque_->buffer[_deque_->rear] = 0; \ + \ + _deque_->count--; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_push_front_if(SNAME *_deque_, T element, bool condition) \ + { \ + if (condition) \ + return PFX##_push_front(_deque_, element); \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_push_back_if(SNAME *_deque_, T 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 T PFX##_back(SNAME *_deque_) \ + { \ + if (PFX##_empty(_deque_)) \ + return 0; \ + \ + return _deque_->buffer[(_deque_->rear == 0) ? _deque_->capacity - 1 : _deque_->rear - 1]; \ + } \ + \ + FMOD T PFX##_front(SNAME *_deque_) \ + { \ + if (PFX##_empty(_deque_)) \ + return 0; \ + \ + return _deque_->buffer[_deque_->front]; \ + } \ + \ + 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 bool PFX##_grow(SNAME *_deque_) \ + { \ + \ + size_t new_capacity = _deque_->capacity * 2; \ + \ + T *new_buffer = malloc(sizeof(T) * 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_->rear = _deque_->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_DEQUE_H */ diff --git a/tests/foreach.c b/tests/foreach.c index af147c6..75eb979 100644 --- a/tests/foreach.c +++ b/tests/foreach.c @@ -84,9 +84,9 @@ int main(int argc, char const *argv[]) sum2 += var; }) - // FOR_EACH_REV(d, deque, , int, d, { - // sum3 += var; - // }) + FOR_EACH_REV(d, deque, , int, d, { + sum3 += var; + }) FOR_EACH_REV(ll, linked, , int, ll, { sum4 += var; @@ -98,8 +98,8 @@ int main(int argc, char const *argv[]) printf("%10s PASSED\n", "STACK"); if (sum2 == 50005000) printf("%10s PASSED\n", "QUEUE"); - // if (sum3 == 50005000) - // printf("%10s PASSED\n", "DEQUE"); + if (sum3 == 50005000) + printf("%10s PASSED\n", "DEQUE"); if (sum4 == 50005000) printf("%10s PASSED\n", "LINKEDLIST"); diff --git a/tests/iterators/deque.c b/tests/iterators/deque.c new file mode 100644 index 0000000..4e759d3 --- /dev/null +++ b/tests/iterators/deque.c @@ -0,0 +1,55 @@ +// Checks if the deque iterator can go back and forward in the deque without +// hitting invalid states or a null pointer. Check is done visually. +#include +#include +#include +#include +#include "../../src/deque.h" + +DEQUE_GENERATE(d, deque, static, , int) + +int main(int argc, char const *argv[]) +{ + size_t i; + int r; + + // Initliazie deque and add some elements + deque *d = d_new(10); + for (int i = 0; i < 10; i++) + { + i % 2 == 0 ? d_push_back(d, i) : d_push_front(d, i); + } + + // Initialize iterator + deque_iter iter; + d_iter(&iter, d); + + // Make the iterator go back and forward + for (int j = 0; j < 4; j++) + { + while (d_iter_next(&iter, &r, &i)) + printf("C[%2d] = %2d\n", i, r); + printf("\n"); + while (d_iter_prev(&iter, &r, &i)) + printf("C[%2d] = %2d\n", i, r); + printf("\n\n"); + } + + for (d_iter_tostart(&iter); !d_iter_end(&iter); /**/) + { + d_iter_next(&iter, &r, &i); + printf("D[%2d] = %2d\n", i, r); + } + + printf("\n"); + + for (d_iter_toend(&iter); !d_iter_start(&iter); /**/) + { + d_iter_prev(&iter, &r, &i); + printf("D[%2d] = %2d\n", i, r); + } + + d_free(d); + + return 0; +}