Initial files, tests and examples
This commit is contained in:
1 parent
a719719f0b
commit
e17e1ba240
14 files changed
+1577
-3
No files matched your search
@@ -50,3 +50,6 @@ modules.order
|
||||
Module.symvers
|
||||
Mkfile.old
|
||||
dkms.conf
|
||||
|
||||
# vscode folder
|
||||
.vscode
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -0,0 +1,9 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#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)
|
||||
@@ -0,0 +1,265 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#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;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#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;
|
||||
}
|
||||
+291
@@ -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 */
|
||||
@@ -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);
|
||||
+326
@@ -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 */
|
||||
@@ -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 <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#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 */
|
||||
+231
@@ -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 */
|
||||
+207
@@ -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 */
|
||||
@@ -0,0 +1,67 @@
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#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;
|
||||
}
|
||||
Reference in new issue
Block a user