From e17e1ba24024a7be704481d454f373070ebedc3d Mon Sep 17 00:00:00 2001 From: Leonardo Date: Fri, 22 Mar 2019 02:44:25 -0300 Subject: [PATCH] Initial files, tests and examples --- .gitignore | 3 + README.md | 24 ++- examples/ex1/Makefile | 13 ++ examples/ex1/containers.c | 6 + examples/ex1/containers.h | 9 ++ examples/ex1/main.c | 265 +++++++++++++++++++++++++++++++ examples/ex2/main.c | 75 +++++++++ src/deque.h | 291 ++++++++++++++++++++++++++++++++++ src/foreach.h | 22 +++ src/list.h | 326 ++++++++++++++++++++++++++++++++++++++ src/macro_containers.h | 41 +++++ src/queue.h | 231 +++++++++++++++++++++++++++ src/stack.h | 207 ++++++++++++++++++++++++ tests/foreach.c | 67 ++++++++ 14 files changed, 1577 insertions(+), 3 deletions(-) create mode 100644 examples/ex1/Makefile create mode 100644 examples/ex1/containers.c create mode 100644 examples/ex1/containers.h create mode 100644 examples/ex1/main.c create mode 100644 examples/ex2/main.c create mode 100644 src/deque.h create mode 100644 src/foreach.h create mode 100644 src/list.h create mode 100644 src/macro_containers.h create mode 100644 src/queue.h create mode 100644 src/stack.h create mode 100644 tests/foreach.c diff --git a/.gitignore b/.gitignore index c6127b3..75185fa 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,6 @@ modules.order Module.symvers Mkfile.old dkms.conf + +# vscode folder +.vscode \ No newline at end of file diff --git a/README.md b/README.md index 4c5402d..fb34cad 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,24 @@ -# C-Macro-Containers +# C-Macro-Collections -Generate Simple Containers of any type in C for you to use in your projects. +Generate Simple Data Structures of any type in C for you to use in your projects. + +## How to use + +All macros have a series of default parameters. Some might not be required or might not be used by the data structure. + +* \*__C__ - Container type (*LIST*, *LINKEDLIST*, *STACK*, *QUEUE*, *DEQUE*, *HASHMAP*, *TREEMAP*, *HASHSET*, *TREESET*, *HEAP*). +* \*__P__ - Permission (PRIVATE, PUBLIC). Only matters when header and source are declared in separate files. + * *PRIVATE* - Members of a struct are hidden in source file and only accessible through functions. + * *PUBLIC* - Members of a struct are visible. +* \*__PFX__ - Functions prefix or namespace. +* \*__SNAME__ - Structure name (`typedef struct SNAME##_s SNAME`). +* __FMOD__ - Function modifier (static). Useful when declaring header and source in the same file. +* \*\*__K__ - Key type. Only used in *HASHMAP* and *TREEMAP*; ignored by others. +* \*__V__ - Value type. Primary type for most data structures, or value to be mapped by *HASHMAP* and *TREEMAP*. + +\* Required parameters + +\*\* Required only by *HASHMAP* and *TREEMAP* ## List @@ -34,7 +52,7 @@ A balanced binary tree that maps a key `K` to a value `V`. The difference from a A hashtable that contains only unique elements to the set. Its elements are not ordered. -## TreeMap +## TreeSet A balanced binary tree that contains only unique elements to the set. Its elements are ordered. diff --git a/examples/ex1/Makefile b/examples/ex1/Makefile new file mode 100644 index 0000000..20d71a0 --- /dev/null +++ b/examples/ex1/Makefile @@ -0,0 +1,13 @@ +CC = gcc +CFLAGS = -Wall -Wextra +INCLUDE = ./ +SRC = ../../src + +main.exe: containers.o main.o $(SRC)/macro_containers.h + $(CC) $^ -o $@ + +%.o: %.c $(SRC)/macro_containers.h + $(CC) -I $(INCLUDE) -I $(SRC) $(CFLAGS) -c $< -o $@ + +run: main.exe $(SRC)/macro_containers.h + ./main.exe \ No newline at end of file diff --git a/examples/ex1/containers.c b/examples/ex1/containers.c new file mode 100644 index 0000000..e2177ff --- /dev/null +++ b/examples/ex1/containers.c @@ -0,0 +1,6 @@ +#include "containers.h" + +CONTAINER_GENERATE_SOURCE(LIST, PUBLIC, il, int_list, , , int) +CONTAINER_GENERATE_SOURCE(STACK, PRIVATE, cs, char_stack, , , char) +CONTAINER_GENERATE_SOURCE(QUEUE, PUBLIC, queue, index_queue, , , size_t) +CONTAINER_GENERATE_SOURCE(DEQUE, PUBLIC, dq, deque, , , int) \ No newline at end of file diff --git a/examples/ex1/containers.h b/examples/ex1/containers.h new file mode 100644 index 0000000..32a14fd --- /dev/null +++ b/examples/ex1/containers.h @@ -0,0 +1,9 @@ +#include +#include +#include +#include "macro_containers.h" + +CONTAINER_GENERATE_HEADER(LIST, PUBLIC, il, int_list, , , int) +CONTAINER_GENERATE_HEADER(STACK, PRIVATE, cs, char_stack, , , char) +CONTAINER_GENERATE_HEADER(QUEUE, PUBLIC, queue, index_queue, , , size_t) +CONTAINER_GENERATE_HEADER(DEQUE, PUBLIC, dq, deque, , , int) \ No newline at end of file diff --git a/examples/ex1/main.c b/examples/ex1/main.c new file mode 100644 index 0000000..dfb850f --- /dev/null +++ b/examples/ex1/main.c @@ -0,0 +1,265 @@ +#include +#include +#include +#include +#include +#include +#include +#include "macro_containers.h" +#include "containers.h" + +double rrandom() +{ + return (double)rand() / ((double)RAND_MAX + 1.0); +} + +int8_t random_int8_t(int8_t min, int8_t max) +{ + return (int8_t)floor(rrandom() * ((double)max - (double)min + 1.0) + (double)min); +} + +size_t random_size_t(size_t min, size_t max) +{ + return (size_t)floor(rrandom() * ((double)max - (double)min + 1.0) + (double)min); +} + +char random_alpha() +{ + const char alpha[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', + 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', + 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', + 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z'}; + return alpha[random_int8_t(0, 61)]; +} + +int main(void) +{ + srand((unsigned)time(NULL)); + + int_list *list = il_new(10); + + for (int i = 0; i < 100; i++) + { + il_push(list, i, list->count == 0 ? list->count : i % list->count); + } + + printf("\n[ "); + + for (size_t i = 0; i < list->count - 1; i++) + printf("%d, ", il_get(list, i)); + + printf("%d ]\n", il_get(list, list->count - 1)); + + il_free(list); + + list = il_new(10); + + for (int i = 0; i < 10; i++) + { + // Add elements + il_push_back(list, i); + + // Print + if (!il_empty(list)) + { + // Print + printf("\n[ "); + for (size_t i = 0; i < list->count - 1; i++) + { + printf("%d, ", il_get(list, i)); + } + printf("%d ]\n", il_get(list, list->count - 1)); + } + } + + for (int i = 0; i < 10; i++) + { + // Remove elements + il_pop_back(list); + + if (!il_empty(list)) + { + // Print + printf("\n[ "); + for (size_t i = 0; i < list->count - 1; i++) + { + printf("%d, ", il_get(list, i)); + } + printf("%d ]\n", il_get(list, list->count - 1)); + } + } + + il_free(list); + + list = il_new(1000); + + for (int i = 0; i < 1000; i++) + { + il_insert_if(list, i, list->count, i % 2 == 0); + } + + // Print all even numbers + if (!il_empty(list)) + { + // Print + printf("\n[ "); + for (size_t i = 0; i < list->count - 1; i++) + { + printf("%d, ", il_get(list, i)); + } + printf("%d ]\n", il_get(list, list->count - 1)); + } + + il_free(list); + + char_stack *stack = cs_new(100); + + for (int i = 0; i < 2000; i++) + { + cs_push(stack, random_alpha()); + } + + size_t s = cs_count(stack); + size_t c = cs_capacity(stack); + printf("Stack size : %" PRIu64 "\n", s); + printf("Stack capacity : %" PRIu64 "\n", c); + + for (size_t i = 0; i < s; i++) + { + printf("%c ", cs_top(stack)); + cs_pop(stack); + } + + printf("\nStack size: %" PRIu64 "", cs_count(stack)); + printf("\nStack capacity : %" PRIu64 "\n", cs_capacity(stack)); + + cs_free(stack); + + index_queue *idxs = queue_new(100); + + size_t sum0 = 0, sum1 = 0, curr; + + printf("\nQueue size : %" PRIu64 "\n", queue_count(idxs)); + printf("Queue capacity : %" PRIu64 "\n", queue_capacity(idxs)); + + for (int i = 1; i <= 600; i++) + { + curr = random_size_t(0, 100); + if (queue_enqueue(idxs, curr)) + sum0 += curr; + + if (i % 11 == 0 && queue_count(idxs) > 0) + { + sum0 -= queue_peek(idxs); + queue_dequeue(idxs); + } + } + + printf("\nQueue size : %" PRIu64 "\n", queue_count(idxs)); + printf("Queue capacity : %" PRIu64 "\n", queue_capacity(idxs)); + + while (!queue_empty(idxs)) + { + sum1 += queue_peek(idxs); + + queue_dequeue(idxs); + } + + printf("\nQueue size : %" PRIu64 "\n", queue_count(idxs)); + printf("Queue capacity : %" PRIu64 "\n", queue_capacity(idxs)); + + if (sum0 == sum1) + printf("\nElements were preserved -> %" PRIu64 " : %" PRIu64 "\n", sum0, sum1); + + queue_free(idxs); + + printf("\nUsing ForEach\n\n"); + + int_list *integers = il_new(1000); + + for (size_t i = 0; i < il_capacity(integers); i++) + il_push_back(integers, i); + + int sum = 0; + FOR_EACH(il, int_list, , int, integers, { + printf("%d, ", var); + sum += var; + }) + + printf("\n\nSUM: %d\n", sum); + + il_free(integers); + + deque *d = dq_new(1000); + + int sum2 = 0, numbers = 0, r = 0; + + for (int i = 0; numbers < 10000; i = rand()) + { + if (i % 2 == 0 || dq_empty(d)) + { + if (i % 4 == 0) + { + dq_push_front(d, ++numbers); + } + else + { + dq_push_back(d, ++numbers); + } + } + else + { + if (i % 3 == 0) + { + r = dq_front(d); + dq_pop_front(d); + } + else + { + r = dq_back(d); + dq_pop_back(d); + } + + sum2 += r; + } + } + + // Emptying the queue + while (!dq_empty(d)) + { + if (rand() % 2 == 0) + { + r = dq_front(d); + dq_pop_front(d); + } + else + { + r = dq_back(d); + dq_pop_back(d); + } + + sum2 += r; + } + + printf("Theoretical Sum: 50005000\nTotal Sum: %d\n", sum2); + + dq_free(d); + + d = dq_new(32); + + for (int i = 1; i < 1001; i++) + i % 2 == 0 ? dq_push_front(d, i) : dq_push_back(d, i); + + int sum3 = 0; + + FOR_EACH(dq, deque, , int, d, { + sum3 += var; + }) + + printf("Deque sum: %d\n", sum3); + + return 0; +} diff --git a/examples/ex2/main.c b/examples/ex2/main.c new file mode 100644 index 0000000..0e7f332 --- /dev/null +++ b/examples/ex2/main.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include "../../src/macro_containers.h" + +CONTAINER_GENERATE(LIST, PUBLIC, l, list, static, , int) +CONTAINER_GENERATE(STACK, PUBLIC, s, stack, static, , int) +CONTAINER_GENERATE(QUEUE, PUBLIC, q, queue, static, , int) +CONTAINER_GENERATE(DEQUE, PUBLIC, d, deque, static, , int) + +int main(int argc, char const *argv[]) +{ + list *l = l_new(100); + stack *s = s_new(100); + queue *q = q_new(100); + deque *d = d_new(100); + + for (int i = 0; i < 20; i++) + { + l_push_back(l, i); + s_push(s, i); + q_enqueue(q, i); + d_push_back(d, i); + } + + s_push(s, 21); + q_enqueue(q, 21); + q_enqueue(q, 22); + d_push_back(d, 21); + d_push_back(d, 22); + d_push_back(d, 23); + + FOR_EACH(l, list, , int, l, { + if (index == 0) + printf("[ %d, ", var); + else if (index == l_count(l) - 1) + printf("%d ]\n", var); + else + printf("%d, ", var); + }) + + FOR_EACH(s, stack, , int, s, { + if (index == 0) + printf("[ %d, ", var); + else if (index == s_count(s) - 1) + printf("%d ]\n", var); + else + printf("%d, ", var); + }) + + FOR_EACH(q, queue, , int, q, { + if (index == 0) + printf("[ %d, ", var); + else if (index == q_count(q) - 1) + printf("%d ]\n", var); + else + printf("%d, ", var); + }) + + FOR_EACH(d, deque, , int, d, { + if (index == 0) + printf("[ %d, ", var); + else if (index == d_count(d) - 1) + printf("%d ]\n", var); + else + printf("%d, ", var); + }) + + l_free(l); + s_free(s); + q_free(q); + d_free(d); + + return 0; +} diff --git a/src/deque.h b/src/deque.h new file mode 100644 index 0000000..8869d70 --- /dev/null +++ b/src/deque.h @@ -0,0 +1,291 @@ +/** + * @file deque.h + * + * Last Update: 22/03/2019 + * + * Authors: + * Leonardo Vencovsky (https://github.com/LeoVen) + * + */ + +/*****************************************************************************/ +/********************************************************************* DEQUE */ +/*****************************************************************************/ + +#ifndef CMC_DEQUE_H +#define CMC_DEQUE_H + +/* PRIVATE *******************************************************************/ +#define DEQUE_GENERATE_HEADER_PRIVATE(PFX, SNAME, FMOD, K, T) \ + DEQUE_GENERATE_HEADER(PFX, SNAME, FMOD, K, T) +#define DEQUE_GENERATE_SOURCE_PRIVATE(PFX, SNAME, FMOD, K, T) \ + DEQUE_GENERATE_STRUCT(PFX, SNAME, FMOD, K, T) \ + DEQUE_GENERATE_SOURCE(PFX, SNAME, FMOD, K, T) +/* PUBLIC ********************************************************************/ +#define DEQUE_GENERATE_HEADER_PUBLIC(PFX, SNAME, FMOD, K, T) \ + DEQUE_GENERATE_STRUCT(PFX, SNAME, FMOD, K, T) \ + DEQUE_GENERATE_HEADER(PFX, SNAME, FMOD, K, T) +#define DEQUE_GENERATE_SOURCE_PUBLIC(PFX, SNAME, FMOD, K, T) \ + DEQUE_GENERATE_SOURCE(PFX, SNAME, FMOD, K, T) +/* STRUCT ********************************************************************/ +#define DEQUE_GENERATE_STRUCT(PFX, SNAME, FMOD, K, T) \ + \ + struct SNAME##_s \ + { \ + T *buffer; \ + size_t capacity; \ + size_t count; \ + size_t front; \ + size_t rear; \ + }; \ + \ + struct SNAME##_iter_s \ + { \ + struct SNAME##_s *target; \ + size_t cursor; \ + size_t count; \ + }; \ + \ +/* HEADER ********************************************************************/ +#define DEQUE_GENERATE_HEADER(PFX, SNAME, FMOD, K, T) \ + \ + typedef struct SNAME##_s SNAME; \ + typedef struct SNAME##_iter_s SNAME##_iter; \ + \ + FMOD SNAME *PFX##_new(size_t size); \ + FMOD void PFX##_free(SNAME *_deque_); \ + FMOD bool PFX##_push_front(SNAME *_deque_, T element); \ + FMOD bool PFX##_push_back(SNAME *_deque_, T element); \ + FMOD bool PFX##_pop_front(SNAME *_deque_); \ + FMOD bool PFX##_pop_back(SNAME *_deque_); \ + FMOD bool PFX##_push_front_if(SNAME *_deque_, T element, bool condition); \ + FMOD bool PFX##_push_back_if(SNAME *_deque_, T element, bool condition); \ + FMOD bool PFX##_pop_front_if(SNAME *_deque_, bool condition); \ + FMOD bool PFX##_pop_back_if(SNAME *_deque_, bool condition); \ + FMOD T PFX##_back(SNAME *_deque_); \ + FMOD T PFX##_front(SNAME *_deque_); \ + FMOD bool PFX##_empty(SNAME *_deque_); \ + FMOD bool PFX##_full(SNAME *_deque_); \ + FMOD size_t PFX##_count(SNAME *_deque_); \ + FMOD size_t PFX##_capacity(SNAME *_deque_); \ + \ + FMOD void PFX##_iter(SNAME##_iter *iter, SNAME *target); \ + FMOD bool PFX##_iter_next(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; \ + } + +#endif /* CMC_DEQUE_H */ diff --git a/src/foreach.h b/src/foreach.h new file mode 100644 index 0000000..fa39dee --- /dev/null +++ b/src/foreach.h @@ -0,0 +1,22 @@ +/** + * @file stack.h + * + * Last Update: 22/03/2019 + * + * Authors: + * Leonardo Vencovsky (https://github.com/LeoVen) + * + */ + +#define FOR_EACH(PFX, SNAME, K, T, TARGET, BODY) \ + do \ + { \ + size_t index; \ + T var; \ + SNAME##_iter _iter_; \ + PFX##_iter(&_iter_, TARGET); \ + while (PFX##_iter_next(&_iter_, &var, &index)) \ + { \ + BODY; \ + } \ + } while (0); diff --git a/src/list.h b/src/list.h new file mode 100644 index 0000000..ed57e70 --- /dev/null +++ b/src/list.h @@ -0,0 +1,326 @@ +/** + * @file list.h + * + * Last Update: 22/03/2019 + * + * Authors: + * Leonardo Vencovsky (https://github.com/LeoVen) + * + */ + +/*****************************************************************************/ +/********************************************************************** LIST */ +/*****************************************************************************/ + +#ifndef CMC_LIST_H +#define CMC_LIST_H + +/* PRIVATE *******************************************************************/ +#define LIST_GENERATE_HEADER_PRIVATE(PFX, SNAME, FMOD, K, T) \ + LIST_GENERATE_HEADER(PFX, SNAME, FMOD, K, T) +#define LIST_GENERATE_SOURCE_PRIVATE(PFX, SNAME, FMOD, K, T) \ + LIST_GENERATE_STRUCT(PFX, SNAME, FMOD, K, T) \ + LIST_GENERATE_SOURCE(PFX, SNAME, FMOD, K, T) +/* PUBLIC ********************************************************************/ +#define LIST_GENERATE_HEADER_PUBLIC(PFX, SNAME, FMOD, K, T) \ + LIST_GENERATE_STRUCT(PFX, SNAME, FMOD, K, T) \ + LIST_GENERATE_HEADER(PFX, SNAME, FMOD, K, T) +#define LIST_GENERATE_SOURCE_PUBLIC(PFX, SNAME, FMOD, K, T) \ + LIST_GENERATE_SOURCE(PFX, SNAME, FMOD, K, T) +/* STRUCT ********************************************************************/ +#define LIST_GENERATE_STRUCT(PFX, SNAME, FMOD, K, T) \ + \ + struct SNAME##_s \ + { \ + T *buffer; \ + size_t capacity; \ + size_t count; \ + }; \ + \ + struct SNAME##_iter_s \ + { \ + struct SNAME##_s *target; \ + size_t cursor; \ + }; \ + \ +/* HEADER ********************************************************************/ +#define LIST_GENERATE_HEADER(PFX, SNAME, FMOD, K, T) \ + \ + typedef struct SNAME##_s SNAME; \ + typedef struct SNAME##_iter_s SNAME##_iter; \ + \ + FMOD SNAME *PFX##_new(size_t size); \ + FMOD void PFX##_free(SNAME *_list_); \ + FMOD bool PFX##_push_front(SNAME *_list_, T element); \ + FMOD bool PFX##_push(SNAME *_list_, T element, size_t index); \ + FMOD bool PFX##_push_back(SNAME *_list_, T element); \ + FMOD bool PFX##_pop_front(SNAME *_list_); \ + FMOD bool PFX##_pop(SNAME *_list_, size_t index); \ + FMOD bool PFX##_pop_back(SNAME *_list_); \ + FMOD bool PFX##_insert_if(SNAME *_list_, T element, size_t index, bool condition); \ + FMOD bool PFX##_remove_if(SNAME *_list_, size_t index, bool condition); \ + FMOD T PFX##_back(SNAME *_list_); \ + FMOD T PFX##_get(SNAME *_list_, size_t index); \ + FMOD T PFX##_front(SNAME *_list_); \ + FMOD bool PFX##_empty(SNAME *_list_); \ + FMOD bool PFX##_full(SNAME *_list_); \ + FMOD size_t PFX##_count(SNAME *_list_); \ + FMOD size_t PFX##_capacity(SNAME *_list_); \ + \ + FMOD void PFX##_iter(SNAME##_iter *iter, SNAME *target); \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter, T *result, size_t *index); \ + \ +/* SOURCE ********************************************************************/ +#define LIST_GENERATE_SOURCE(PFX, SNAME, FMOD, K, T) \ + \ + FMOD bool PFX##_grow(SNAME *_list_); \ + \ + FMOD SNAME *PFX##_new(size_t size) \ + { \ + if (size < 1) \ + return NULL; \ + \ + SNAME *_list_ = malloc(sizeof(SNAME)); \ + \ + if (!_list_) \ + return NULL; \ + \ + _list_->buffer = malloc(sizeof(T) * size); \ + \ + if (!_list_->buffer) \ + { \ + free(_list_); \ + return NULL; \ + } \ + \ + for (size_t i = 0; i < size; i++) \ + { \ + _list_->buffer[i] = 0; \ + } \ + \ + _list_->capacity = size; \ + _list_->count = 0; \ + \ + return _list_; \ + } \ + \ + FMOD void PFX##_free(SNAME *_list_) \ + { \ + free(_list_->buffer); \ + free(_list_); \ + } \ + \ + FMOD bool PFX##_push_front(SNAME *_list_, T element) \ + { \ + if (PFX##_full(_list_)) \ + { \ + if (!PFX##_grow(_list_)) \ + return false; \ + } \ + \ + if (!PFX##_empty(_list_)) \ + { \ + for (size_t i = _list_->count; i > 0; i--) \ + { \ + _list_->buffer[i] = _list_->buffer[i - 1]; \ + } \ + } \ + \ + _list_->buffer[0] = element; \ + \ + _list_->count++; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_push(SNAME *_list_, T element, size_t index) \ + { \ + if (index > _list_->count) \ + return false; \ + \ + if (index == 0) \ + { \ + return PFX##_push_front(_list_, element); \ + } \ + else if (index == _list_->count) \ + { \ + return PFX##_push_back(_list_, element); \ + } \ + \ + if (PFX##_full(_list_)) \ + { \ + if (!PFX##_grow(_list_)) \ + return false; \ + } \ + \ + for (size_t i = _list_->count; i > index; i--) \ + { \ + _list_->buffer[i] = _list_->buffer[i - 1]; \ + } \ + \ + _list_->buffer[index] = element; \ + \ + _list_->count++; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_push_back(SNAME *_list_, T element) \ + { \ + if (PFX##_full(_list_)) \ + { \ + if (!PFX##_grow(_list_)) \ + return false; \ + } \ + \ + _list_->buffer[_list_->count++] = element; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_pop_front(SNAME *_list_) \ + { \ + if (PFX##_empty(_list_)) \ + return false; \ + \ + for (size_t i = 0; i < _list_->count; i++) \ + { \ + _list_->buffer[i] = _list_->buffer[i + 1]; \ + } \ + \ + _list_->buffer[--_list_->count] = 0; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_pop(SNAME *_list_, size_t index) \ + { \ + if (PFX##_empty(_list_)) \ + return false; \ + \ + if (index == 0) \ + { \ + return PFX##_pop_front(_list_); \ + } \ + else if (index == _list_->count - 1) \ + { \ + return PFX##_pop_back(_list_); \ + } \ + \ + for (size_t i = index; i < _list_->count - 1; i++) \ + { \ + _list_->buffer[i] = _list_->buffer[i + 1]; \ + } \ + \ + _list_->buffer[--_list_->count] = 0; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_pop_back(SNAME *_list_) \ + { \ + if (PFX##_empty(_list_)) \ + return false; \ + \ + _list_->buffer[--_list_->count] = 0; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_insert_if(SNAME *_list_, T element, size_t index, bool condition) \ + { \ + if (condition) \ + return PFX##_push(_list_, element, index); \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_remove_if(SNAME *_list_, size_t index, bool condition) \ + { \ + if (condition) \ + return PFX##_pop(_list_, index); \ + \ + return false; \ + } \ + \ + FMOD T PFX##_front(SNAME *_list_) \ + { \ + if (PFX##_empty(_list_)) \ + return 0; \ + \ + return _list_->buffer[0]; \ + } \ + \ + FMOD T PFX##_get(SNAME *_list_, size_t index) \ + { \ + if (index >= _list_->count) \ + return 0; \ + \ + if (PFX##_empty(_list_)) \ + return 0; \ + \ + return _list_->buffer[index]; \ + } \ + \ + FMOD T PFX##_back(SNAME *_list_) \ + { \ + if (PFX##_empty(_list_)) \ + return 0; \ + \ + return _list_->buffer[_list_->count - 1]; \ + } \ + \ + FMOD bool PFX##_empty(SNAME *_list_) \ + { \ + return _list_->count == 0; \ + } \ + \ + FMOD bool PFX##_full(SNAME *_list_) \ + { \ + return _list_->count >= _list_->capacity; \ + } \ + \ + FMOD size_t PFX##_count(SNAME *_list_) \ + { \ + return _list_->count; \ + } \ + \ + FMOD size_t PFX##_capacity(SNAME *_list_) \ + { \ + return _list_->capacity; \ + } \ + \ + FMOD bool PFX##_grow(SNAME *_list_) \ + { \ + size_t new_capacity = _list_->capacity * 2; \ + \ + T *new_buffer = realloc(_list_->buffer, sizeof(T) * new_capacity); \ + \ + if (!new_buffer) \ + return false; \ + \ + _list_->buffer = new_buffer; \ + _list_->capacity = new_capacity; \ + \ + return true; \ + } \ + \ + FMOD void PFX##_iter(SNAME##_iter *iter, SNAME *target) \ + { \ + iter->target = target; \ + iter->cursor = 0; \ + } \ + \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter, T *result, size_t *index) \ + { \ + if (iter->cursor < iter->target->count) \ + { \ + *index = iter->cursor; \ + *result = iter->target->buffer[iter->cursor++]; \ + return true; \ + } \ + \ + return false; \ + } + +#endif /* CMC_LIST_H */ diff --git a/src/macro_containers.h b/src/macro_containers.h new file mode 100644 index 0000000..b9c42a7 --- /dev/null +++ b/src/macro_containers.h @@ -0,0 +1,41 @@ +/** + * @file macro_containers.h + * + * @author Leonardo Vencovsky (https://github.com/LeoVen) + * @date 11/02/2019 + * + * Macro based generic containers. + * + */ + +#ifndef MACRO_CONTAINERS +#define MACRO_CONTAINERS + +#include +#include + +#define CONCATH_(C, P) C##_GENERATE_HEADER##_##P +#define CONCATC_(C, P) C##_GENERATE_SOURCE##_##P + +#define CONCATH(C, P) CONCATH_(C, P) +#define CONCATC(C, P) CONCATC_(C, P) + +#define CONTAINER_GENERATE(C, P, PFX, SNAME, FMOD, K, V) \ + CONTAINER_GENERATE_HEADER(C, P, PFX, SNAME, FMOD, K, V) \ + CONTAINER_GENERATE_SOURCE(C, P, PFX, SNAME, FMOD, K, V) + +#define CONTAINER_GENERATE_HEADER(C, P, PFX, SNAME, FMOD, K, V) \ + CONCATH(C, P) \ + (PFX, SNAME, FMOD, K, V) + +#define CONTAINER_GENERATE_SOURCE(C, P, PFX, SNAME, FMOD, K, V) \ + CONCATC(C, P) \ + (PFX, SNAME, FMOD, K, V) + +#include "list.h" +#include "stack.h" +#include "queue.h" +#include "deque.h" +#include "foreach.h" + +#endif /* MACRO_CONTAINERS */ \ No newline at end of file diff --git a/src/queue.h b/src/queue.h new file mode 100644 index 0000000..1b20079 --- /dev/null +++ b/src/queue.h @@ -0,0 +1,231 @@ +/** + * @file queue.h + * + * Last Update: 22/03/2019 + * + * Authors: + * Leonardo Vencovsky (https://github.com/LeoVen) + * + */ + +/*****************************************************************************/ +/********************************************************************* QUEUE */ +/*****************************************************************************/ + +#ifndef CMC_QUEUE_H +#define CMC_QUEUE_H + +/* PRIVATE *******************************************************************/ +#define QUEUE_GENERATE_HEADER_PRIVATE(PFX, SNAME, FMOD, K, T) \ + QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, K, T) +#define QUEUE_GENERATE_SOURCE_PRIVATE(PFX, SNAME, FMOD, K, T) \ + QUEUE_GENERATE_STRUCT(PFX, SNAME, FMOD, K, T) \ + QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, K, T) +/* PUBLIC ********************************************************************/ +#define QUEUE_GENERATE_HEADER_PUBLIC(PFX, SNAME, FMOD, K, T) \ + QUEUE_GENERATE_STRUCT(PFX, SNAME, FMOD, K, T) \ + QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, K, T) +#define QUEUE_GENERATE_SOURCE_PUBLIC(PFX, SNAME, FMOD, K, T) \ + QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, K, T) +/* STRUCT ********************************************************************/ +#define QUEUE_GENERATE_STRUCT(PFX, SNAME, FMOD, K, T) \ + \ + struct SNAME##_s \ + { \ + T *buffer; \ + size_t capacity; \ + size_t count; \ + size_t front; \ + size_t rear; \ + }; \ + \ + struct SNAME##_iter_s \ + { \ + struct SNAME##_s *target; \ + size_t cursor; \ + size_t count; \ + }; \ + \ +/* HEADER ********************************************************************/ +#define QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, K, T) \ + \ + typedef struct SNAME##_s SNAME; \ + typedef struct SNAME##_iter_s SNAME##_iter; \ + \ + FMOD SNAME *PFX##_new(size_t size); \ + FMOD void PFX##_free(SNAME *_queue_); \ + FMOD bool PFX##_enqueue(SNAME *_queue_, T element); \ + FMOD bool PFX##_dequeue(SNAME *_queue_); \ + FMOD T PFX##_peek(SNAME *_queue_); \ + FMOD bool PFX##_enqueue_if(SNAME *_queue_, T element, bool condition); \ + FMOD bool PFX##_dequeue_if(SNAME *_queue_, bool condition); \ + FMOD bool PFX##_empty(SNAME *_queue_); \ + FMOD bool PFX##_full(SNAME *_queue_); \ + FMOD size_t PFX##_count(SNAME *_queue_); \ + FMOD size_t PFX##_capacity(SNAME *_queue_); \ + \ + FMOD void PFX##_iter(SNAME##_iter *iter, SNAME *target); \ + FMOD bool PFX##_iter_next(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; \ + } + +#endif /* CMC_QUEUE_H */ diff --git a/src/stack.h b/src/stack.h new file mode 100644 index 0000000..415f195 --- /dev/null +++ b/src/stack.h @@ -0,0 +1,207 @@ +/** + * @file stack.h + * + * Last Update: 22/03/2019 + * + * Authors: + * Leonardo Vencovsky (https://github.com/LeoVen) + * + */ + +/*****************************************************************************/ +/********************************************************************* STACK */ +/*****************************************************************************/ + +#ifndef CMC_STACK_H +#define CMC_STACK_H + +/* PRIVATE *******************************************************************/ +#define STACK_GENERATE_HEADER_PRIVATE(PFX, SNAME, FMOD, K, T) \ + STACK_GENERATE_HEADER(PFX, SNAME, FMOD, K, T) +#define STACK_GENERATE_SOURCE_PRIVATE(PFX, SNAME, FMOD, K, T) \ + STACK_GENERATE_STRUCT(PFX, SNAME, FMOD, K, T) \ + STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, K, T) +/* PUBLIC ********************************************************************/ +#define STACK_GENERATE_HEADER_PUBLIC(PFX, SNAME, FMOD, K, T) \ + STACK_GENERATE_STRUCT(PFX, SNAME, FMOD, K, T) \ + STACK_GENERATE_HEADER(PFX, SNAME, FMOD, K, T) +#define STACK_GENERATE_SOURCE_PUBLIC(PFX, SNAME, FMOD, K, T) \ + STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, K, T) +/* STRUCT ********************************************************************/ +#define STACK_GENERATE_STRUCT(PFX, SNAME, FMOD, K, T) \ + \ + struct SNAME##_s \ + { \ + T *buffer; \ + size_t capacity; \ + size_t count; \ + }; \ + \ + struct SNAME##_iter_s \ + { \ + struct SNAME##_s *target; \ + size_t cursor; \ + }; \ + \ +/* HEADER ********************************************************************/ +#define STACK_GENERATE_HEADER(PFX, SNAME, FMOD, K, T) \ + \ + typedef struct SNAME##_s SNAME; \ + typedef struct SNAME##_iter_s SNAME##_iter; \ + \ + FMOD SNAME *PFX##_new(size_t size); \ + FMOD void PFX##_free(SNAME *_stack_); \ + FMOD bool PFX##_push(SNAME *_stack_, T element); \ + FMOD bool PFX##_pop(SNAME *_stack_); \ + FMOD T PFX##_top(SNAME *_stack_); \ + FMOD bool PFX##_push_if(SNAME *_stack_, T element, bool condition); \ + FMOD bool PFX##_pop_if(SNAME *_stack_, bool condition); \ + FMOD bool PFX##_empty(SNAME *_stack_); \ + FMOD bool PFX##_full(SNAME *_stack_); \ + FMOD size_t PFX##_count(SNAME *_stack_); \ + FMOD size_t PFX##_capacity(SNAME *_stack_); \ + \ + FMOD void PFX##_iter(SNAME##_iter *iter, SNAME *target); \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter, T *result, size_t *index); \ + \ +/* SOURCE ********************************************************************/ +#define STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, K, T) \ + \ + FMOD bool PFX##_grow(SNAME *_stack_); \ + \ + FMOD SNAME *PFX##_new(size_t size) \ + { \ + if (size < 1) \ + return NULL; \ + \ + SNAME *_stack_ = malloc(sizeof(SNAME)); \ + \ + if (!_stack_) \ + return NULL; \ + \ + _stack_->buffer = malloc(sizeof(T) * size); \ + \ + if (!_stack_->buffer) \ + { \ + free(_stack_); \ + return NULL; \ + } \ + \ + for (size_t i = 0; i < size; i++) \ + { \ + _stack_->buffer[i] = 0; \ + } \ + \ + _stack_->capacity = size; \ + _stack_->count = 0; \ + \ + return _stack_; \ + } \ + \ + FMOD void PFX##_free(SNAME *_stack_) \ + { \ + free(_stack_->buffer); \ + free(_stack_); \ + } \ + \ + FMOD bool PFX##_push(SNAME *_stack_, T element) \ + { \ + if (PFX##_full(_stack_)) \ + { \ + if (!PFX##_grow(_stack_)) \ + return false; \ + } \ + \ + _stack_->buffer[_stack_->count++] = element; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_pop(SNAME *_stack_) \ + { \ + if (PFX##_empty(_stack_)) \ + return false; \ + \ + _stack_->buffer[--_stack_->count] = 0; \ + \ + return true; \ + } \ + \ + FMOD T PFX##_top(SNAME *_stack_) \ + { \ + if (PFX##_empty(_stack_)) \ + return 0; \ + \ + return _stack_->buffer[_stack_->count - 1]; \ + } \ + \ + FMOD bool PFX##_push_if(SNAME *_stack_, T element, bool condition) \ + { \ + if (condition) \ + return PFX##_push(_stack_, element); \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_pop_if(SNAME *_stack_, bool condition) \ + { \ + if (condition) \ + return PFX##_pop(_stack_); \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_empty(SNAME *_stack_) \ + { \ + return _stack_->count == 0; \ + } \ + \ + FMOD bool PFX##_full(SNAME *_stack_) \ + { \ + return _stack_->count >= _stack_->capacity; \ + } \ + \ + FMOD size_t PFX##_count(SNAME *_stack_) \ + { \ + return _stack_->count; \ + } \ + \ + FMOD size_t PFX##_capacity(SNAME *_stack_) \ + { \ + return _stack_->capacity; \ + } \ + \ + FMOD bool PFX##_grow(SNAME *_stack_) \ + { \ + size_t new_capacity = _stack_->capacity * 2; \ + \ + T *new_buffer = realloc(_stack_->buffer, sizeof(T) * new_capacity); \ + \ + if (!new_buffer) \ + return false; \ + \ + _stack_->buffer = new_buffer; \ + _stack_->capacity = new_capacity; \ + \ + return true; \ + } \ + \ + FMOD void PFX##_iter(SNAME##_iter *iter, SNAME *target) \ + { \ + iter->target = target; \ + iter->cursor = 0; \ + } \ + \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter, T *result, size_t *index) \ + { \ + if (iter->cursor < iter->target->count) \ + { \ + *index = iter->cursor; \ + *result = iter->target->buffer[iter->cursor++]; \ + return true; \ + } \ + \ + return false; \ + } + +#endif /* CMC_STACK_H */ diff --git a/tests/foreach.c b/tests/foreach.c new file mode 100644 index 0000000..d0f4e7e --- /dev/null +++ b/tests/foreach.c @@ -0,0 +1,67 @@ +#include +#include +#include "../src/macro_containers.h" + +CONTAINER_GENERATE(LIST, PUBLIC, l, list, /**/, /**/, int) +CONTAINER_GENERATE(STACK, PUBLIC, s, stack, /**/, /**/, int) +CONTAINER_GENERATE(QUEUE, PUBLIC, q, queue, /**/, /**/, int) +CONTAINER_GENERATE(DEQUE, PUBLIC, d, deque, /**/, /**/, int) + +int main(int argc, char const *argv[]) +{ + list *l = l_new(1000); + stack *s = s_new(1000); + queue *q = q_new(1000); + deque *d = d_new(1000); + + for (int i = 1; i < 10001; i++) + { + if (i % 2 == 0) + { + d_push_front(d, i); + l_push_front(l, i); + } + else + { + d_push_back(d, i); + l_push_back(l, i); + } + + s_push(s, i); + q_enqueue(q, i); + } + + int sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0; + + FOR_EACH(l, list, , int, l, { + sum0 += var; + }) + + FOR_EACH(s, stack, , int, s, { + sum1 += var; + }) + + FOR_EACH(q, queue, , int, q, { + sum2 += var; + }) + + FOR_EACH(d, deque, , int, d, { + sum3 += var; + }) + + if (sum0 == 50005000) + printf("%10s PASSED\n", "LIST"); + if (sum1 == 50005000) + printf("%10s PASSED\n", "STACK"); + if (sum2 == 50005000) + printf("%10s PASSED\n", "QUEUE"); + if (sum3 == 50005000) + printf("%10s PASSED\n", "DEQUE"); + + l_free(l); + s_free(s); + q_free(q); + d_free(d); + + return 0; +}