Restructuring project
View CHANGELOG on v1.5.0 for more information
This commit is contained in:
1 parent
dad9b7a81f
commit
8010cce8c7
57 files changed
+1820
-206
No files matched your search
+1
-1
@@ -55,4 +55,4 @@ dkms.conf
|
||||
.vscode
|
||||
|
||||
# Experimental folder
|
||||
dev/
|
||||
experimental/
|
||||
+2
-12
@@ -8,19 +8,9 @@ addons:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- gcc-7
|
||||
- cmake
|
||||
script:
|
||||
- sudo ln -s /usr/bin/gcc-6 /usr/local/bin/gcc
|
||||
- export CC=gcc-7
|
||||
- cd ./tests
|
||||
- gcc foreach.c -Wall -Wextra -o foreach -std=c11
|
||||
- ./foreach
|
||||
- gcc iterators.c -Wall -Wextra -o iterators -std=c11
|
||||
- ./iterators
|
||||
- gcc contains.c -Wall -Wextra -o contains -std=c11
|
||||
- ./contains
|
||||
- gcc types.c -Wall -Wextra -o types -std=c11
|
||||
- ./types
|
||||
- gcc -c ./sep/sep.c -Wall -Wextra -o ./sep/sep.o -std=c11
|
||||
- gcc -c ./sep/main.c -Wall -Wextra -o ./sep/main.o -std=c11
|
||||
- gcc ./sep/sep.o ./sep/main.o -o ./sep/sep
|
||||
- ./sep/sep
|
||||
- make
|
||||
@@ -1,5 +1,19 @@
|
||||
# MAJOR.MINOR.ADJUSTMENTS
|
||||
|
||||
1.5.0
|
||||
Changed tests compilation and execution to a single Makefile
|
||||
Changed project structure
|
||||
./src/
|
||||
./cmc/ - Main C Macro Collections Library
|
||||
./dev/ - A copy of ./cmc/ used for development (logging utility)
|
||||
./ext/ - Extra collections
|
||||
./sac/ - Stack Allocated Collections
|
||||
./utl/ - Utility like ForEach, logging, etc
|
||||
Added ./utl/log.h a logging utility
|
||||
Added ./dev/deque.h - A mirror of ./cmc/deque.h but with logging utility
|
||||
Added ./ext/linkedqueue.h - A singly-linked list based queue
|
||||
Added ./sac/stack.h - A Stack purely allocated on the stack
|
||||
|
||||
1.4.3
|
||||
Fixed some functions names
|
||||
Added set functions for both Tree and Hash Set
|
||||
|
||||
@@ -8,26 +8,65 @@ Generate Simple Data Structures of any type in C for you to use in your projects
|
||||
|
||||
## Available Collections
|
||||
|
||||
* List
|
||||
* LinkedList
|
||||
* Stack
|
||||
* Queue
|
||||
* Deque
|
||||
* Heap
|
||||
* TreeSet
|
||||
* TreeMap
|
||||
* HashSet
|
||||
* HashMap
|
||||
* HashSet
|
||||
* Heap
|
||||
* LinkedList
|
||||
* List
|
||||
* Queue
|
||||
* Stack
|
||||
* TreeMap
|
||||
* TreeSet
|
||||
|
||||
## Available Collections in future updates
|
||||
### Available Collections in future updates
|
||||
|
||||
* Multimap
|
||||
* Multiset
|
||||
* Treehashmap
|
||||
* Heap will be a MinMaxHeap
|
||||
* MultiMap
|
||||
* MultiSet
|
||||
* TreeHashMap
|
||||
* Heap will be an IntervalHeap
|
||||
* Stack Allocated Collections
|
||||
|
||||
Check out **Documentation.md** for more information about each collection.
|
||||
|
||||
## Project Structure
|
||||
|
||||
* __benchmarks__ - Where all benchmarks are hosted
|
||||
* __src__ - All headers part of the C Macro Collections Library
|
||||
* __cmc__ - The main C Macro Collections Library
|
||||
* __dev__ - The main C Macro Collections Library for development (containing logging)
|
||||
* __ext__ - Extra collections
|
||||
* __sac__ - Stack Allocated Collections
|
||||
* __utl__ - Utility like ForEach macros, logging, etc
|
||||
* __macro\_collections.h__ - Master header containing all collections and utilities
|
||||
* __tests__ - Where all tests are hosted
|
||||
|
||||
Only Collections located in __cmc__ are to be documented at Documentation.md.
|
||||
|
||||
## Design Decisions
|
||||
|
||||
### Stack vs Heap Allocation
|
||||
|
||||
Currently all collections need to be allocated on the heap. Iterators have both options but it is encouraged to allocate them on the stack since they don't require dynamic memory.
|
||||
|
||||
### Some collections overlap others in terms of functionality
|
||||
|
||||
Yes, you can use a Deque as a Queue or a List as a Stack without any major cost, but the idea is to have the least amount of code to fulfill the needs of a collection.
|
||||
|
||||
Take for example the Stack. It is simple, small and doesn't have many functions. If you generate a List to be used (only) as a Stack (which is one of the bulkiest collections) you'll end up with a lot of code generated and compiled for nothing.
|
||||
|
||||
The Deque versus Queue situation is a little less problematic, but again, you need to be careful when generating a lot of code as compilation times might go up to 15 seconds even with modern ultra-fast compilers.
|
||||
|
||||
Another example is using a HashMap/TreeMap as a HashSet/TreeSet (with a dummy value that is never used), but I just think that this is a bad thing to do and you would be wasting some memory. Also, the sets generate a lot of code related to set theory, whereas maps don't.
|
||||
|
||||
### But what about the LinkedList ?
|
||||
|
||||
You can use them as Stacks, Queues and Deques, but with modern memory hierarchy models, array-based data structures have a significantly faster runtime due to caching, so I didn't bother to have specific implementations of those aforementioned collections.
|
||||
|
||||
### You can't structurally modify a collection when iterating over it
|
||||
|
||||
Modifying a collection will possibly invalidate all iterators currently initialized by it. Currently, the only collection that allows this is the LinkedList (using the node-based functions, not the iterator).
|
||||
|
||||
## What to use
|
||||
|
||||
The following table shows how each collection is implemented and how well they do when using as common [abstract data types](https://en.wikipedia.org/wiki/Abstract_data_type).
|
||||
@@ -104,27 +143,3 @@ When including `foreach.h` in your source code you gain access to all for-each m
|
||||
* __BODY__ - Block of code.
|
||||
|
||||
Inside body you will have access to the iterator variable. With it you can use functions to access the key, value or index from the iterator. Checkout the documentation for more details.
|
||||
|
||||
## Design Decisions
|
||||
|
||||
### Stack vs Heap Allocation
|
||||
|
||||
Currently all collections need to be allocated on the heap. Iterators have both options but it is encouraged to allocate them on the stack since they don't require dynamic memory.
|
||||
|
||||
### Some collections overlap others in terms of functionality
|
||||
|
||||
Yes, you can use a Deque as a Queue or a List as a Stack without any major cost, but the idea is to have the least amount of code to fulfill the needs of a collection.
|
||||
|
||||
Take for example the Stack. It is simple, small and doesn't have many functions. If you generate a List to be used (only) as a Stack (which is one of the bulkiest collections) you'll end up with a lot of code generated and compiled for nothing.
|
||||
|
||||
The Deque versus Queue situation is a little less problematic, but again, you need to be careful when generating a lot of code as compilation times might go up to 15 seconds even with modern ultra-fast compilers.
|
||||
|
||||
Another example is using a HashMap/TreeMap as a HashSet/TreeSet (with a dummy value that is never used), but I just think that this is a bad thing to do and you would be wasting some memory. Also, the sets generate a lot of code related to set theory, whereas maps don't.
|
||||
|
||||
### But what about the LinkedList ?
|
||||
|
||||
You can use them as Stacks, Queues and Deques, but with modern memory hierarchy models, array-based data structures have a significantly faster runtime due to caching, so I didn't bother to have specific implementations of those aforementioned collections.
|
||||
|
||||
### You can't structurally modify a collection when iterating over it
|
||||
|
||||
Modifying a collection will possibly invalidate all iterators currently initialized by it. Currently, the only collection that allows this is the LinkedList (using the node-based functions, not the iterator).
|
||||
@@ -4,10 +4,12 @@ TODO
|
||||
[X] Remove PUBLIC and PRIVATE
|
||||
[ ] Add multiset
|
||||
[ ] Add multimap
|
||||
[ ] Upgrade heap to a min-max heap
|
||||
[ ] Upgrade heap to an interval heap
|
||||
[ ] Add dispose function
|
||||
[ ] Serialization
|
||||
[ ] Iterator based functions (like C++ collections)
|
||||
[ ] Add Stack Allocated Collections
|
||||
[ ] Finish all Dev Collections
|
||||
|
||||
|
||||
MAYBE
|
||||
@@ -20,13 +22,8 @@ PLANNED
|
||||
Before 2.0
|
||||
Get Documentation fixed and completed
|
||||
|
||||
1.5
|
||||
OK - Remove PUBLIC and PRIVATE
|
||||
OK - Allow for struct to be a possible data type (instead of just pointer to struct)
|
||||
OK - Set functions: is_subset, is_proper_subset, is_superset, is_proper_superset, is_disjointset
|
||||
Iterator move and move_to
|
||||
|
||||
1.6
|
||||
Iterator move and move_to
|
||||
from_array - Creates a collection with all the elements in a specified array
|
||||
to_array - Creates an array with all the elements inside the collection
|
||||
LinkedList - Insert/Remove/Append/Prepend/Extract
|
||||
@@ -36,7 +33,7 @@ Before 2.0
|
||||
|
||||
2.0
|
||||
Add new heap collection implementation
|
||||
Add stack based collections
|
||||
Add all stack based collections
|
||||
|
||||
2.1
|
||||
Add variadic macros (generate only the necessary functions)
|
||||
@@ -49,4 +46,4 @@ Before 2.0
|
||||
|
||||
SOMETIME
|
||||
|
||||
Add treehashmap
|
||||
Add TreeHashMap
|
||||
@@ -7,10 +7,10 @@
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
#include "cmc/deque.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "deque.h"
|
||||
|
||||
DEQUE_GENERATE(d, deque, /* static */, size_t)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Iterator Example
|
||||
*/
|
||||
#include "deque.h"
|
||||
#include "cmc/deque.h"
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "hashmap.h"
|
||||
#include "cmc/hashmap.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
*
|
||||
* Foreach macro example
|
||||
*/
|
||||
#include "hashmap.h"
|
||||
#include "foreach.h"
|
||||
#include "cmc/hashmap.h"
|
||||
#include "utl/foreach.h"
|
||||
#include <stdio.h>
|
||||
|
||||
// Int hash function
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Iterator Example
|
||||
*/
|
||||
#include "hashmap.h"
|
||||
#include "cmc/hashmap.h"
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Iterator Example
|
||||
*/
|
||||
#include "hashset.h"
|
||||
#include "cmc/hashset.h"
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
// - Difference
|
||||
// - Symmetric Difference
|
||||
|
||||
#include "cmc/hashset.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "hashset.h"
|
||||
|
||||
HASHSET_GENERATE(set, set, /* static */, int)
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
#include "cmc/heap.h"
|
||||
#include <stdio.h>
|
||||
#include "heap.h"
|
||||
|
||||
static int intcmp(int a, int b)
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Iterator Example
|
||||
*/
|
||||
#include "heap.h"
|
||||
#include "cmc/heap.h"
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
#include "deque.h"
|
||||
#include "cmc/deque.h"
|
||||
#include <stdio.h>
|
||||
|
||||
DEQUE_GENERATE(d, deque, static, int)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
#include "hashmap.h"
|
||||
#include "cmc/hashmap.h"
|
||||
#include <stdio.h>
|
||||
|
||||
HASHMAP_GENERATE(hm, hmap, static, int, double)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
#include "hashset.h"
|
||||
#include "cmc/hashset.h"
|
||||
#include <stdio.h>
|
||||
|
||||
HASHSET_GENERATE(hs, hset, static, int)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
#include "heap.h"
|
||||
#include "cmc/heap.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int intcmp(int a, int b)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
#include "linkedlist.h"
|
||||
#include "cmc/linkedlist.h"
|
||||
#include <stdio.h>
|
||||
|
||||
LINKEDLIST_GENERATE(ll, linkedlist, static, int)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
#include "list.h"
|
||||
#include "cmc/list.h"
|
||||
#include <stdio.h>
|
||||
|
||||
LIST_GENERATE(l, list, static, int)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
#include "queue.h"
|
||||
#include "cmc/queue.h"
|
||||
#include <stdio.h>
|
||||
|
||||
QUEUE_GENERATE(q, queue, static, int)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
#include "stack.h"
|
||||
#include "cmc/stack.h"
|
||||
#include <stdio.h>
|
||||
|
||||
STACK_GENERATE(s, stack, static, int)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
#include "treemap.h"
|
||||
#include "cmc/treemap.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int intcmp(int a, int b)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
#include "treeset.h"
|
||||
#include "cmc/treeset.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int intcmp(int a, int b)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Iterator Example
|
||||
*/
|
||||
#include "linkedlist.h"
|
||||
#include "cmc/linkedlist.h"
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
#include "linkedlist.h"
|
||||
#include "cmc/linkedlist.h"
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Iterator Example
|
||||
*/
|
||||
#include "list.h"
|
||||
#include "cmc/list.h"
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
#include "list.h"
|
||||
#include "cmc/list.h"
|
||||
#include <stdio.h>
|
||||
|
||||
LIST_GENERATE(l, list, /* FMOD */, int)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
#include "list.h"
|
||||
#include "cmc/list.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "macro_collections.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "macro_collections.h"
|
||||
|
||||
// Create containers to use only in this file
|
||||
COLLECTION_GENERATE(LIST, l, list, static, , int)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
#include "queue.h"
|
||||
#include "cmc/queue.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Iterator Example
|
||||
*/
|
||||
#include "queue.h"
|
||||
#include "cmc/queue.h"
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
#include "cmc/stack.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "stack.h"
|
||||
|
||||
STACK_GENERATE(s, stack, /* static */, int)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Iterator Example
|
||||
*/
|
||||
#include "stack.h"
|
||||
#include "cmc/stack.h"
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Iterator Example
|
||||
*/
|
||||
#include "treemap.h"
|
||||
#include "cmc/treemap.h"
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
// How to make a multiset using a map
|
||||
|
||||
#include "treemap.h"
|
||||
#include "cmc/treemap.h"
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Iterator Example
|
||||
*/
|
||||
#include "treeset.h"
|
||||
#include "cmc/treeset.h"
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
// - Difference
|
||||
// - Symmetric Difference
|
||||
|
||||
#include "cmc/treeset.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "treeset.h"
|
||||
|
||||
TREESET_GENERATE(set, set, /* static */, int)
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
#include "cmc/treeset.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "treeset.h"
|
||||
|
||||
TREESET_GENERATE(set, set, , int)
|
||||
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LINKEDLIST_GENERATE(PFX, SNAME, FMOD, V) \
|
||||
LINKEDLIST_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
|
||||
File renamed without changes.
@@ -131,7 +131,7 @@
|
||||
#define QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \
|
||||
\
|
||||
/* Implementation Detail Functions */ \
|
||||
static FMOD bool PFX##_impl_grow(SNAME *_queue_); \
|
||||
static bool PFX##_impl_grow(SNAME *_queue_); \
|
||||
static SNAME##_iter PFX##_impl_it_start(SNAME *_queue_); \
|
||||
static SNAME##_iter PFX##_impl_it_end(SNAME *_queue_); \
|
||||
\
|
||||
File renamed without changes.
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#define TREEMAP_GENERATE(PFX, SNAME, FMOD, K, V) \
|
||||
TREEMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#define TREESET_GENERATE(PFX, SNAME, FMOD, V) \
|
||||
TREESET_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
|
||||
+654
@@ -0,0 +1,654 @@
|
||||
/**
|
||||
* deque.h
|
||||
*
|
||||
* Creation Date: 21/06/2019
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
/********************************************************************* DEQUE */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef CMC_DEQUE_H
|
||||
#define CMC_DEQUE_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include "utl/log.h"
|
||||
|
||||
#define DEQUE_GENERATE(PFX, SNAME, FMOD, V) \
|
||||
DEQUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
|
||||
DEQUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
|
||||
|
||||
#define DEQUE_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \
|
||||
DEQUE_GENERATE_HEADER(PFX, SNAME, FMOD, V)
|
||||
|
||||
#define DEQUE_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \
|
||||
DEQUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
|
||||
|
||||
/* HEADER ********************************************************************/
|
||||
#define DEQUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
|
||||
\
|
||||
/* Deque Structure */ \
|
||||
typedef struct SNAME##_s \
|
||||
{ \
|
||||
/* Dynamic circular array of elements */ \
|
||||
V *buffer; \
|
||||
\
|
||||
/* Current circular array capacity */ \
|
||||
size_t capacity; \
|
||||
\
|
||||
/* Current amount of elements */ \
|
||||
size_t count; \
|
||||
\
|
||||
/* Index representing the front of the deque */ \
|
||||
size_t front; \
|
||||
\
|
||||
/* Index representing the back of the deque */ \
|
||||
size_t back; \
|
||||
\
|
||||
/* Function that returns an iterator to the start of the deque */ \
|
||||
struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
|
||||
\
|
||||
/* Function that returns an iterator to the end of the deque */ \
|
||||
struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
|
||||
\
|
||||
} SNAME, *SNAME##_ptr; \
|
||||
\
|
||||
/* Deque Iterator */ \
|
||||
typedef struct SNAME##_iter_s \
|
||||
{ \
|
||||
/* Target deque */ \
|
||||
struct SNAME##_s *target; \
|
||||
\
|
||||
/* Cursor's position (index) */ \
|
||||
size_t cursor; \
|
||||
\
|
||||
/* Keeps track of relative index to the iteration of elements */ \
|
||||
size_t index; \
|
||||
\
|
||||
/* If the iterator has reached the start of the iteration */ \
|
||||
bool start; \
|
||||
\
|
||||
/* If the iterator has reached the end of the iteration */ \
|
||||
bool end; \
|
||||
\
|
||||
} SNAME##_iter, *SNAME##_iter_ptr; \
|
||||
\
|
||||
/* Collection Functions */ \
|
||||
/* Collection Allocation and Deallocation */ \
|
||||
FMOD SNAME *PFX##_new(size_t capacity); \
|
||||
FMOD void PFX##_clear(SNAME *_deque_); \
|
||||
FMOD void PFX##_free(SNAME *_deque_); \
|
||||
/* Collection Input and Output */ \
|
||||
FMOD bool PFX##_push_front(SNAME *_deque_, V element); \
|
||||
FMOD bool PFX##_push_back(SNAME *_deque_, V element); \
|
||||
FMOD bool PFX##_pop_front(SNAME *_deque_); \
|
||||
FMOD bool PFX##_pop_back(SNAME *_deque_); \
|
||||
/* Conditional Input and Output */ \
|
||||
FMOD bool PFX##_push_front_if(SNAME *_deque_, V element, bool condition); \
|
||||
FMOD bool PFX##_push_back_if(SNAME *_deque_, V element, bool condition); \
|
||||
FMOD bool PFX##_pop_front_if(SNAME *_deque_, bool condition); \
|
||||
FMOD bool PFX##_pop_back_if(SNAME *_deque_, bool condition); \
|
||||
/* Element Access */ \
|
||||
FMOD V PFX##_front(SNAME *_deque_); \
|
||||
FMOD V PFX##_back(SNAME *_deque_); \
|
||||
/* Collection State */ \
|
||||
FMOD bool PFX##_contains(SNAME *_deque_, V element, int (*comparator)(V, V)); \
|
||||
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_); \
|
||||
\
|
||||
/* Iterator Functions */ \
|
||||
/* Iterator Allocation and Deallocation */ \
|
||||
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \
|
||||
FMOD void PFX##_iter_free(SNAME##_iter *iter); \
|
||||
/* Iterator Initialization */ \
|
||||
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \
|
||||
/* Iterator State */ \
|
||||
FMOD bool PFX##_iter_start(SNAME##_iter *iter); \
|
||||
FMOD bool PFX##_iter_end(SNAME##_iter *iter); \
|
||||
/* Iterator Movement */ \
|
||||
FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \
|
||||
FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \
|
||||
FMOD bool PFX##_iter_next(SNAME##_iter *iter); \
|
||||
FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \
|
||||
/* Iterator Access */ \
|
||||
FMOD V PFX##_iter_value(SNAME##_iter *iter); \
|
||||
FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \
|
||||
FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \
|
||||
\
|
||||
/* Default Value */ \
|
||||
static inline V PFX##_impl_default_value(void) \
|
||||
{ \
|
||||
V _empty_value_; \
|
||||
\
|
||||
memset(&_empty_value_, 0, sizeof(V)); \
|
||||
\
|
||||
return _empty_value_; \
|
||||
} \
|
||||
\
|
||||
/* SOURCE ********************************************************************/
|
||||
#define DEQUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \
|
||||
\
|
||||
/* Implementation Detail Functions */ \
|
||||
static bool PFX##_impl_grow(SNAME *_deque_); \
|
||||
static SNAME##_iter PFX##_impl_it_start(SNAME *_deque_); \
|
||||
static SNAME##_iter PFX##_impl_it_end(SNAME *_deque_); \
|
||||
\
|
||||
FMOD SNAME *PFX##_new(size_t capacity) \
|
||||
{ \
|
||||
if (capacity < 1) \
|
||||
{ \
|
||||
log_warn("Invalid capacity for %s given: %s", "Heap", capacity); \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
SNAME *_deque_ = malloc(sizeof(SNAME)); \
|
||||
\
|
||||
if (!_deque_) \
|
||||
{ \
|
||||
log_info("%s allocation failed", "Deque"); \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
_deque_->buffer = malloc(sizeof(V) * capacity); \
|
||||
\
|
||||
if (!_deque_->buffer) \
|
||||
{ \
|
||||
log_info("%s allocation failed", "Deque buffer"); \
|
||||
free(_deque_); \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
memset(_deque_->buffer, 0, sizeof(V) * capacity); \
|
||||
\
|
||||
_deque_->capacity = capacity; \
|
||||
_deque_->count = 0; \
|
||||
_deque_->front = 0; \
|
||||
_deque_->back = 0; \
|
||||
\
|
||||
_deque_->it_start = PFX##_impl_it_start; \
|
||||
_deque_->it_end = PFX##_impl_it_end; \
|
||||
\
|
||||
log_info("Deque at %p successfully allocated", _deque_); \
|
||||
\
|
||||
return _deque_; \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_clear(SNAME *_deque_) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
\
|
||||
memset(_deque_->buffer, 0, sizeof(V) * _deque_->capacity); \
|
||||
\
|
||||
_deque_->count = 0; \
|
||||
_deque_->front = 0; \
|
||||
_deque_->back = 0; \
|
||||
\
|
||||
log_trace("Deque at %p cleared", _deque_); \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_free(SNAME *_deque_) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
\
|
||||
free(_deque_->buffer); \
|
||||
\
|
||||
uintptr_t address = (uintptr_t)(void *)_deque_; \
|
||||
\
|
||||
free(_deque_); \
|
||||
\
|
||||
log_info("Heap at %p successfully deallocated", address); \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_push_front(SNAME *_deque_, V element) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
\
|
||||
if (PFX##_full(_deque_)) \
|
||||
{ \
|
||||
if (!PFX##_impl_grow(_deque_)) \
|
||||
{ \
|
||||
log_info("Deque at %p failed to be reallocated", _deque_); \
|
||||
return false; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
_deque_->front = (_deque_->front == 0) ? _deque_->capacity - 1 : _deque_->front - 1; \
|
||||
\
|
||||
_deque_->buffer[_deque_->front] = element; \
|
||||
\
|
||||
log_trace("Element added at %" PRIuMAX " to Deque at %p", _deque_->front, _deque_); \
|
||||
\
|
||||
_deque_->count++; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_push_back(SNAME *_deque_, V element) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
\
|
||||
if (PFX##_full(_deque_)) \
|
||||
{ \
|
||||
if (!PFX##_impl_grow(_deque_)) \
|
||||
{ \
|
||||
log_info("Deque at %p failed to be reallocated", _deque_); \
|
||||
return false; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
_deque_->buffer[_deque_->back] = element; \
|
||||
\
|
||||
log_trace("Element added at %" PRIuMAX " to Deque at %p", _deque_->back, _deque_); \
|
||||
\
|
||||
_deque_->back = (_deque_->back == _deque_->capacity - 1) ? 0 : _deque_->back + 1; \
|
||||
\
|
||||
_deque_->count++; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_pop_front(SNAME *_deque_) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
\
|
||||
if (PFX##_empty(_deque_)) \
|
||||
{ \
|
||||
log_debug("Attempt of removing an element from empty Deque at %p", _deque_); \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
_deque_->buffer[_deque_->front] = PFX##_impl_default_value(); \
|
||||
\
|
||||
log_trace("Element removed from %" PRIuMAX " to Deque at %p", _deque_->front, _deque_); \
|
||||
\
|
||||
_deque_->front = (_deque_->front == _deque_->capacity - 1) ? 0 : _deque_->front + 1; \
|
||||
\
|
||||
_deque_->count--; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_pop_back(SNAME *_deque_) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
{ \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
} \
|
||||
\
|
||||
if (PFX##_empty(_deque_)) \
|
||||
{ \
|
||||
log_debug("Attempt of removing an element from empty Deque at %p", _deque_); \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
_deque_->back = (_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1; \
|
||||
\
|
||||
_deque_->buffer[_deque_->back] = PFX##_impl_default_value(); \
|
||||
\
|
||||
log_trace("Element removed from %" PRIuMAX " to Deque at %p", _deque_->back, _deque_); \
|
||||
\
|
||||
_deque_->count--; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_push_front_if(SNAME *_deque_, V element, bool condition) \
|
||||
{ \
|
||||
if (condition) \
|
||||
return PFX##_push_front(_deque_, element); \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_push_back_if(SNAME *_deque_, V 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 V PFX##_front(SNAME *_deque_) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
\
|
||||
if (PFX##_empty(_deque_)) \
|
||||
{ \
|
||||
log_debug("Attempt to access element from empty Deque at %p", _deque_); \
|
||||
\
|
||||
PFX##_impl_default_value(); \
|
||||
} \
|
||||
\
|
||||
log_trace("Element access at %" PRIuMAX "", _deque_->front); \
|
||||
\
|
||||
return _deque_->buffer[_deque_->front]; \
|
||||
} \
|
||||
\
|
||||
FMOD V PFX##_back(SNAME *_deque_) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
\
|
||||
if (PFX##_empty(_deque_)) \
|
||||
{ \
|
||||
log_debug("Attempt to access element from empty Deque at %p", _deque_); \
|
||||
\
|
||||
PFX##_impl_default_value(); \
|
||||
} \
|
||||
\
|
||||
size_t index = (_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1; \
|
||||
\
|
||||
log_trace("Element access at %" PRIuMAX "", index); \
|
||||
\
|
||||
return _deque_->buffer[index]; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_contains(SNAME *_deque_, V element, int (*comparator)(V, V)) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
\
|
||||
if (comparator == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "comparator"); \
|
||||
\
|
||||
for (size_t i = _deque_->front, j = 0; j < _deque_->count; i = (i + 1) % _deque_->count, j++) \
|
||||
{ \
|
||||
if (comparator(_deque_->buffer[i], element) == 0) \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_empty(SNAME *_deque_) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
\
|
||||
return _deque_->count == 0; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_full(SNAME *_deque_) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
\
|
||||
return _deque_->count >= _deque_->capacity; \
|
||||
} \
|
||||
\
|
||||
FMOD size_t PFX##_count(SNAME *_deque_) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
\
|
||||
return _deque_->count; \
|
||||
} \
|
||||
\
|
||||
FMOD size_t PFX##_capacity(SNAME *_deque_) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
\
|
||||
return _deque_->capacity; \
|
||||
} \
|
||||
\
|
||||
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \
|
||||
{ \
|
||||
SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \
|
||||
\
|
||||
if (!iter) \
|
||||
{ \
|
||||
log_info("%s allocation failed", "Deque Iterator"); \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
PFX##_iter_init(iter, target); \
|
||||
\
|
||||
log_info("Deque Iterator allocated at %p referencing Heap at %p", iter, target); \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_iter_free(SNAME##_iter *iter) \
|
||||
{ \
|
||||
uintptr_t address = (uintptr_t)(void *)iter; \
|
||||
\
|
||||
free(iter); \
|
||||
\
|
||||
log_info("Deque Iterator deallocated at %" PRIxPTR "", address); \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \
|
||||
{ \
|
||||
if (target == NULL) \
|
||||
log_fatal("Heap Iterator at %p initialized with null pointer target", iter); \
|
||||
\
|
||||
if (PFX##_empty(target)) \
|
||||
log_warn("Deque Iterator at %p initialized with empty target", iter); \
|
||||
\
|
||||
iter->target = target; \
|
||||
iter->cursor = target->front; \
|
||||
iter->index = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = PFX##_empty(target); \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_iter_start(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "iter"); \
|
||||
\
|
||||
return PFX##_empty(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_iter_end(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "iter"); \
|
||||
\
|
||||
return PFX##_empty(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "iter"); \
|
||||
\
|
||||
iter->cursor = iter->target->front; \
|
||||
iter->index = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = PFX##_empty(iter->target); \
|
||||
\
|
||||
log_trace("Deque Iterator at %p with cursor at %" PRIuMAX "", iter, iter->cursor); \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "iter"); \
|
||||
\
|
||||
if (PFX##_empty(iter->target)) \
|
||||
iter->cursor = 0; \
|
||||
else \
|
||||
iter->cursor = (iter->target->back == 0) ? iter->target->capacity - 1 : iter->target->back - 1; \
|
||||
\
|
||||
iter->index = iter->target->count - 1; \
|
||||
iter->start = PFX##_empty(iter->target); \
|
||||
iter->end = true; \
|
||||
\
|
||||
log_trace("Deque Iterator at %p with cursor at %" PRIuMAX "", iter, iter->cursor); \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_iter_next(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "iter"); \
|
||||
\
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
iter->start = PFX##_empty(iter->target); \
|
||||
\
|
||||
if (iter->index == iter->target->count - 1) \
|
||||
{ \
|
||||
log_trace("Deque Iterator at %p reached the end of Deque %p", iter, iter->target); \
|
||||
iter->end = true; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
iter->cursor = (iter->cursor + 1) % (iter->target->capacity); \
|
||||
iter->index++; \
|
||||
\
|
||||
log_trace("Deque Iterator at %p moved to %" PRIuMAX "", iter, iter->cursor); \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "iter"); \
|
||||
\
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
iter->end = PFX##_empty(iter->target); \
|
||||
\
|
||||
if (iter->index == 0) \
|
||||
{ \
|
||||
log_trace("Deque Iterator at %p reached the start of Deque %p", iter, iter->target); \
|
||||
iter->start = true; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; \
|
||||
iter->index--; \
|
||||
\
|
||||
log_trace("Deque Iterator at %p moved to %" PRIuMAX "", iter, iter->cursor); \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "iter"); \
|
||||
\
|
||||
if (PFX##_empty(iter->target)) \
|
||||
{ \
|
||||
log_debug("Attempt to access element from iterator %p with empty target %p", iter, iter->target); \
|
||||
PFX##_impl_default_value(); \
|
||||
} \
|
||||
\
|
||||
log_trace("Element access at %" PRIuMAX "", iter->cursor); \
|
||||
\
|
||||
return iter->target->buffer[iter->cursor]; \
|
||||
} \
|
||||
\
|
||||
FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "iter"); \
|
||||
\
|
||||
if (PFX##_empty(iter->target)) \
|
||||
{ \
|
||||
log_debug("Attempt to access element from iterator %p with empty target %p", iter, iter->target); \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
log_trace("Element access at %" PRIuMAX "", iter->cursor); \
|
||||
\
|
||||
return &(iter->target->buffer[iter->cursor]); \
|
||||
} \
|
||||
\
|
||||
FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "iter"); \
|
||||
\
|
||||
return iter->index; \
|
||||
} \
|
||||
\
|
||||
static bool PFX##_impl_grow(SNAME *_deque_) \
|
||||
{ \
|
||||
size_t new_capacity = _deque_->capacity * 2; \
|
||||
\
|
||||
V *new_buffer = malloc(sizeof(V) * new_capacity); \
|
||||
\
|
||||
if (!new_buffer) \
|
||||
{ \
|
||||
log_info("%s reallocation failed", "Deque 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_->back = _deque_->count; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
static SNAME##_iter PFX##_impl_it_start(SNAME *_deque_) \
|
||||
{ \
|
||||
SNAME##_iter iter; \
|
||||
\
|
||||
PFX##_iter_init(&iter, _deque_); \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
static SNAME##_iter PFX##_impl_it_end(SNAME *_deque_) \
|
||||
{ \
|
||||
SNAME##_iter iter; \
|
||||
\
|
||||
PFX##_iter_init(&iter, _deque_); \
|
||||
PFX##_iter_to_end(&iter); \
|
||||
\
|
||||
return iter; \
|
||||
}
|
||||
|
||||
#endif /* CMC_DEQUE_H */
|
||||
@@ -0,0 +1,384 @@
|
||||
/**
|
||||
* linkedqueue.h
|
||||
*
|
||||
* Creation Date: 21/06/2019
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* A node-based Queue using a Singly Linked List
|
||||
*
|
||||
* enqueue : is equivalent to a push_back from a LinkedList
|
||||
* dequeue : is equivalent to a pop_peek from a LinkedList
|
||||
*
|
||||
* This Queue has a one-way iterator
|
||||
*/
|
||||
|
||||
#ifndef CMC_LINKEDQUEUE_H
|
||||
#define CMC_LINKEDQUEUE_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LINKEDQUEUE_GENERATE(PFX, SNAME, FMOD, V) \
|
||||
LINKEDQUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
|
||||
LINKEDQUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
|
||||
|
||||
#define LINKEDQUEUE_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \
|
||||
LINKEDQUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V)
|
||||
|
||||
#define LINKEDQUEUE_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \
|
||||
LINKEDQUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
|
||||
|
||||
/* HEADER ********************************************************************/
|
||||
#define LINKEDQUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
|
||||
\
|
||||
/* Linked Queue Structure */ \
|
||||
typedef struct SNAME##_s \
|
||||
{ \
|
||||
/* First node in the list */ \
|
||||
struct SNAME##_node_s *head; \
|
||||
\
|
||||
/* Last node in the list */ \
|
||||
struct SNAME##_node_s *tail; \
|
||||
\
|
||||
/* Current amount of elements in the list */ \
|
||||
size_t count; \
|
||||
\
|
||||
/* Function that returns an iterator to the start of the list */ \
|
||||
struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
|
||||
\
|
||||
} SNAME, *SNAME##_ptr; \
|
||||
\
|
||||
/* Singly-linked list node */ \
|
||||
typedef struct SNAME##_node_s \
|
||||
{ \
|
||||
/* Node's data */ \
|
||||
V data; \
|
||||
\
|
||||
/* Pointer to the next node on the linked list */ \
|
||||
struct SNAME##_node_s *next; \
|
||||
\
|
||||
} SNAME##_node, *SNAME##_node_ptr; \
|
||||
\
|
||||
/* Linked Queue Iterator */ \
|
||||
typedef struct SNAME##_iter_s \
|
||||
{ \
|
||||
/* Target Linked Queue */ \
|
||||
struct SNAME##_s *target; \
|
||||
\
|
||||
/* Cursor's current node */ \
|
||||
struct SNAME##_node_s *cursor; \
|
||||
\
|
||||
/* Keeps track of relative index to the iteration of elements */ \
|
||||
size_t index; \
|
||||
\
|
||||
/* If the iterator is at the start of the iteration */ \
|
||||
bool start; \
|
||||
\
|
||||
/* If the iterator has reached the end of the iteration */ \
|
||||
bool end; \
|
||||
\
|
||||
} SNAME##_iter, *SNAME##_iter_ptr; \
|
||||
\
|
||||
/* Collection Functions */ \
|
||||
/* Collection Allocation and Deallocation */ \
|
||||
FMOD SNAME *PFX##_new(void); \
|
||||
FMOD void PFX##_clear(SNAME *_lqueue_); \
|
||||
FMOD void PFX##_free(SNAME *_lqueue_); \
|
||||
/* Collection Input and Output */ \
|
||||
FMOD bool PFX##_enqueue(SNAME *_lqueue_, V element); \
|
||||
FMOD bool PFX##_dequeue(SNAME *_lqueue_); \
|
||||
/* Conditional Input and Output */ \
|
||||
FMOD bool PFX##_enqueue_if(SNAME *_lqueue_, V element, bool condition); \
|
||||
FMOD bool PFX##_dequeue_if(SNAME *_lqueue_, bool condition); \
|
||||
/* Element Access */ \
|
||||
FMOD V PFX##_peek(SNAME *_lqueue_); \
|
||||
/* Collection State */ \
|
||||
FMOD bool PFX##_contains(SNAME *_lqueue_, V element, int (*comparator)(V, V)); \
|
||||
FMOD bool PFX##_empty(SNAME *_lqueue_); \
|
||||
FMOD size_t PFX##_count(SNAME *_lqueue_); \
|
||||
\
|
||||
/* Iterator Functions */ \
|
||||
/* Iterator Allocation and Deallocation */ \
|
||||
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \
|
||||
FMOD void PFX##_iter_free(SNAME##_iter *iter); \
|
||||
/* Iterator Initialization */ \
|
||||
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \
|
||||
/* Iterator State */ \
|
||||
FMOD bool PFX##_iter_start(SNAME##_iter *iter); \
|
||||
FMOD bool PFX##_iter_end(SNAME##_iter *iter); \
|
||||
/* Iterator Movement */ \
|
||||
FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \
|
||||
FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \
|
||||
FMOD bool PFX##_iter_next(SNAME##_iter *iter); \
|
||||
/* Iterator Access */ \
|
||||
FMOD V PFX##_iter_value(SNAME##_iter *iter); \
|
||||
FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \
|
||||
FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \
|
||||
\
|
||||
/* Default Value */ \
|
||||
static inline V PFX##_impl_default_value(void) \
|
||||
{ \
|
||||
V _empty_value_; \
|
||||
\
|
||||
memset(&_empty_value_, 0, sizeof(V)); \
|
||||
\
|
||||
return _empty_value_; \
|
||||
} \
|
||||
\
|
||||
/* SOURCE ********************************************************************/
|
||||
#define LINKEDQUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \
|
||||
\
|
||||
/* Implementation Detail Functions */ \
|
||||
FMOD SNAME##_node *PFX##_impl_new_node(V element); \
|
||||
static SNAME##_iter PFX##_impl_it_start(SNAME *_lqueue_); \
|
||||
\
|
||||
FMOD SNAME *PFX##_new(void) \
|
||||
{ \
|
||||
SNAME *_lqueue_ = malloc(sizeof(SNAME)); \
|
||||
\
|
||||
if (!_lqueue_) \
|
||||
return NULL; \
|
||||
\
|
||||
_lqueue_->count = 0; \
|
||||
_lqueue_->head = NULL; \
|
||||
_lqueue_->tail = NULL; \
|
||||
\
|
||||
_lqueue_->it_start = PFX##_impl_it_start; \
|
||||
\
|
||||
return _lqueue_; \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_clear(SNAME *_lqueue_) \
|
||||
{ \
|
||||
SNAME##_node *scan = _lqueue_->head; \
|
||||
\
|
||||
while (_lqueue_->head != NULL) \
|
||||
{ \
|
||||
_lqueue_->head = _lqueue_->head->next; \
|
||||
free(scan); \
|
||||
scan = _lqueue_->head; \
|
||||
} \
|
||||
\
|
||||
_lqueue_->count = 0; \
|
||||
_lqueue_->head = NULL; \
|
||||
_lqueue_->tail = NULL; \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_free(SNAME *_lqueue_) \
|
||||
{ \
|
||||
PFX##_clear(_lqueue_); \
|
||||
\
|
||||
free(_lqueue_); \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_enqueue(SNAME *_lqueue_, V element) \
|
||||
{ \
|
||||
SNAME##_node *_node_ = PFX##_impl_new_node(element); \
|
||||
\
|
||||
if (!_node_) \
|
||||
return false; \
|
||||
\
|
||||
if (PFX##_empty(_lqueue_)) \
|
||||
{ \
|
||||
_lqueue_->head = _node_; \
|
||||
_lqueue_->tail = _node_; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
_lqueue_->tail->next = _node_; \
|
||||
_lqueue_->tail = _node_; \
|
||||
} \
|
||||
\
|
||||
_lqueue_->count++; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_dequeue(SNAME *_lqueue_) \
|
||||
{ \
|
||||
if (PFX##_empty(_lqueue_)) \
|
||||
return false; \
|
||||
\
|
||||
SNAME##_node *_node_ = _lqueue_->head; \
|
||||
_lqueue_->head = _lqueue_->head->next; \
|
||||
\
|
||||
free(_node_); \
|
||||
\
|
||||
if (_lqueue_->head == NULL) \
|
||||
_lqueue_->tail = NULL; \
|
||||
\
|
||||
_lqueue_->count--; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_enqueue_if(SNAME *_lqueue_, V element, bool condition) \
|
||||
{ \
|
||||
if (condition) \
|
||||
return PFX##_enqueue(_lqueue_, element); \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_dequeue_if(SNAME *_lqueue_, bool condition) \
|
||||
{ \
|
||||
if (condition) \
|
||||
return PFX##_dequeue(_lqueue_); \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
FMOD V PFX##_peek(SNAME *_lqueue_) \
|
||||
{ \
|
||||
if (PFX##_empty(_lqueue_)) \
|
||||
PFX##_impl_default_value(); \
|
||||
\
|
||||
return _lqueue_->head->data; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_contains(SNAME *_lqueue_, V element, int (*comparator)(V, V)) \
|
||||
{ \
|
||||
SNAME##_node *scan = _lqueue_->head; \
|
||||
\
|
||||
while (scan != NULL) \
|
||||
{ \
|
||||
if (comparator(scan->data, element) == 0) \
|
||||
return true; \
|
||||
\
|
||||
scan = scan->next; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_empty(SNAME *_lqueue_) \
|
||||
{ \
|
||||
return _lqueue_->count == 0; \
|
||||
} \
|
||||
\
|
||||
FMOD size_t PFX##_count(SNAME *_lqueue_) \
|
||||
{ \
|
||||
return _lqueue_->count; \
|
||||
} \
|
||||
\
|
||||
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \
|
||||
{ \
|
||||
SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \
|
||||
\
|
||||
if (!iter) \
|
||||
return NULL; \
|
||||
\
|
||||
PFX##_iter_init(iter, target); \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_iter_free(SNAME##_iter *iter) \
|
||||
{ \
|
||||
free(iter); \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \
|
||||
{ \
|
||||
iter->target = target; \
|
||||
iter->cursor = target->head; \
|
||||
iter->index = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = PFX##_empty(target); \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_iter_start(SNAME##_iter *iter) \
|
||||
{ \
|
||||
return PFX##_empty(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_iter_end(SNAME##_iter *iter) \
|
||||
{ \
|
||||
return PFX##_empty(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \
|
||||
{ \
|
||||
iter->cursor = iter->target->head; \
|
||||
iter->index = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = PFX##_empty(iter->target); \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \
|
||||
{ \
|
||||
iter->cursor = iter->target->tail; \
|
||||
iter->index = iter->target->count - 1; \
|
||||
iter->start = PFX##_empty(iter->target); \
|
||||
iter->end = true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_iter_next(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
iter->start = PFX##_empty(iter->target); \
|
||||
\
|
||||
if (iter->cursor->next == NULL) \
|
||||
iter->end = true; \
|
||||
else \
|
||||
{ \
|
||||
iter->cursor = iter->cursor->next; \
|
||||
iter->index++; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (PFX##_empty(iter->target)) \
|
||||
return PFX##_impl_default_value(); \
|
||||
\
|
||||
return iter->cursor->data; \
|
||||
} \
|
||||
\
|
||||
FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (PFX##_empty(iter->target)) \
|
||||
NULL; \
|
||||
\
|
||||
return &(iter->cursor->data); \
|
||||
} \
|
||||
\
|
||||
FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \
|
||||
{ \
|
||||
return iter->index; \
|
||||
} \
|
||||
\
|
||||
FMOD SNAME##_node *PFX##_impl_new_node(V element) \
|
||||
{ \
|
||||
SNAME##_node *_node_ = malloc(sizeof(SNAME##_node)); \
|
||||
\
|
||||
if (!_node_) \
|
||||
return NULL; \
|
||||
\
|
||||
_node_->data = element; \
|
||||
_node_->next = NULL; \
|
||||
\
|
||||
return _node_; \
|
||||
} \
|
||||
\
|
||||
static SNAME##_iter PFX##_impl_it_start(SNAME *_lqueue_) \
|
||||
{ \
|
||||
SNAME##_iter iter; \
|
||||
\
|
||||
PFX##_iter_init(&iter, _lqueue_); \
|
||||
PFX##_iter_to_start(&iter); \
|
||||
\
|
||||
return iter; \
|
||||
}
|
||||
|
||||
#endif /* CMC_LINKEDQUEUE_H */
|
||||
+16
-11
@@ -32,17 +32,22 @@
|
||||
CONCATC(C) \
|
||||
(PFX, SNAME, FMOD, K, V)
|
||||
|
||||
#include "list.h"
|
||||
#include "linkedlist.h"
|
||||
#include "stack.h"
|
||||
#include "queue.h"
|
||||
#include "deque.h"
|
||||
#include "heap.h"
|
||||
#include "treeset.h"
|
||||
#include "treemap.h"
|
||||
#include "hashset.h"
|
||||
#include "hashmap.h"
|
||||
#include "cmc/list.h"
|
||||
#include "cmc/linkedlist.h"
|
||||
#include "cmc/stack.h"
|
||||
#include "cmc/queue.h"
|
||||
#include "cmc/deque.h"
|
||||
#include "cmc/heap.h"
|
||||
#include "cmc/treeset.h"
|
||||
#include "cmc/treemap.h"
|
||||
#include "cmc/hashset.h"
|
||||
#include "cmc/hashmap.h"
|
||||
|
||||
#include "foreach.h"
|
||||
#include "ext/linkedqueue.h"
|
||||
|
||||
#include "sac/stack.h"
|
||||
|
||||
#include "utl/foreach.h"
|
||||
#include "utl/log.h"
|
||||
|
||||
#endif /* CMC_MACRO_COLLECTIONS */
|
||||
+334
@@ -0,0 +1,334 @@
|
||||
/**
|
||||
* stack.h
|
||||
*
|
||||
* Creation Date: 21/06/2019
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* A Purely Stack Allocated Stack
|
||||
*
|
||||
* This means that the Stack has a fixed size, but it also has the advantage of
|
||||
* not requiring for manually allocating and deallocating the struct.
|
||||
*
|
||||
* Generating a collection with too big of a storage can be dangerous and might
|
||||
* quickly cause a stack overflow.
|
||||
*
|
||||
* It is recommended to not generate any Stack Allocated Collection with less
|
||||
* than 1000 internal storage.
|
||||
*/
|
||||
|
||||
#ifndef CMC_SAC_STACK_H
|
||||
#define CMC_SAC_STACK_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#define SAC_STACK_GENERATE(PFX, SNAME, FMOD, V, SIZE) \
|
||||
SAC_STACK_GENERATE_HEADER(PFX, SNAME, FMOD, V, SIZE) \
|
||||
SAC_STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, V, SIZE)
|
||||
|
||||
#define SAC_STACK_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V, SIZE) \
|
||||
SAC_STACK_GENERATE_HEADER(PFX, SNAME, FMOD, V, SIZE)
|
||||
|
||||
#define SAC_STACK_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V, SIZE) \
|
||||
SAC_STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, V, SIZE)
|
||||
|
||||
/* HEADER ********************************************************************/
|
||||
#define SAC_STACK_GENERATE_HEADER(PFX, SNAME, FMOD, V, SIZE) \
|
||||
\
|
||||
/* Stack Structure */ \
|
||||
typedef struct SNAME##_s \
|
||||
{ \
|
||||
/* Internal Storage */ \
|
||||
V buffer[SIZE]; \
|
||||
\
|
||||
/* Current amount of elements */ \
|
||||
size_t count; \
|
||||
\
|
||||
/* Function that returns an iterator to the start of the stack */ \
|
||||
struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
|
||||
\
|
||||
/* Function that returns an iterator to the end of the stack */ \
|
||||
struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
|
||||
\
|
||||
} SNAME, *SNAME##_ptr; \
|
||||
\
|
||||
/* Stack Iterator */ \
|
||||
typedef struct SNAME##_iter_s \
|
||||
{ \
|
||||
/* Target stack */ \
|
||||
struct SNAME##_s *target; \
|
||||
\
|
||||
/* Cursor's position (index) */ \
|
||||
size_t cursor; \
|
||||
\
|
||||
/* If the iterator has reached the start of the iteration */ \
|
||||
bool start; \
|
||||
\
|
||||
/* If the iterator has reached the end of the iteration */ \
|
||||
bool end; \
|
||||
\
|
||||
} SNAME##_iter, *SNAME##_iter_ptr; \
|
||||
\
|
||||
/* Collection Functions */ \
|
||||
/* Collection Allocation and Deallocation */ \
|
||||
FMOD SNAME PFX##_new(void); \
|
||||
FMOD void PFX##_clear(SNAME *_stack_); \
|
||||
FMOD void PFX##_free(SNAME *_stack_); \
|
||||
/* Collection Input and Output */ \
|
||||
FMOD bool PFX##_push(SNAME *_stack_, V element); \
|
||||
FMOD bool PFX##_pop(SNAME *_stack_); \
|
||||
/* Conditional Input and Output */ \
|
||||
FMOD bool PFX##_push_if(SNAME *_stack_, V element, bool condition); \
|
||||
FMOD bool PFX##_pop_if(SNAME *_stack_, bool condition); \
|
||||
/* Element Access */ \
|
||||
FMOD V PFX##_top(SNAME *_stack_); \
|
||||
/* Collection State */ \
|
||||
FMOD bool PFX##_contains(SNAME *_stack_, V element, int (*comparator)(V, V)); \
|
||||
FMOD bool PFX##_empty(SNAME *_stack_); \
|
||||
FMOD bool PFX##_full(SNAME *_stack_); \
|
||||
FMOD size_t PFX##_count(SNAME *_stack_); \
|
||||
FMOD size_t PFX##_capacity(void); \
|
||||
\
|
||||
/* Iterator Functions */ \
|
||||
/* Iterator Initialization */ \
|
||||
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \
|
||||
/* Iterator State */ \
|
||||
FMOD bool PFX##_iter_start(SNAME##_iter *iter); \
|
||||
FMOD bool PFX##_iter_end(SNAME##_iter *iter); \
|
||||
/* Iterator Movement */ \
|
||||
FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \
|
||||
FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \
|
||||
FMOD bool PFX##_iter_next(SNAME##_iter *iter); \
|
||||
FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \
|
||||
/* Iterator Access */ \
|
||||
FMOD V PFX##_iter_value(SNAME##_iter *iter); \
|
||||
FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \
|
||||
FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \
|
||||
\
|
||||
/* Default Value */ \
|
||||
static inline V PFX##_impl_default_value(void) \
|
||||
{ \
|
||||
V _empty_value_; \
|
||||
\
|
||||
memset(&_empty_value_, 0, sizeof(V)); \
|
||||
\
|
||||
return _empty_value_; \
|
||||
} \
|
||||
\
|
||||
/* SOURCE ********************************************************************/
|
||||
#define SAC_STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, V, SIZE) \
|
||||
\
|
||||
/* Implementation Detail Functions */ \
|
||||
static SNAME##_iter PFX##_impl_it_start(SNAME *_stack_); \
|
||||
static SNAME##_iter PFX##_impl_it_end(SNAME *_stack_); \
|
||||
\
|
||||
FMOD SNAME PFX##_new(void) \
|
||||
{ \
|
||||
SNAME result; \
|
||||
\
|
||||
memset(&result, 0, sizeof(SNAME)); \
|
||||
\
|
||||
result.it_start = PFX##_impl_it_start; \
|
||||
result.it_end = PFX##_impl_it_end; \
|
||||
\
|
||||
return result; \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_clear(SNAME *_stack_) \
|
||||
{ \
|
||||
memset(_stack_->buffer, 0, sizeof(V) * SIZE); \
|
||||
\
|
||||
_stack_->count = 0; \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_free(SNAME *_stack_) \
|
||||
{ \
|
||||
free(_stack_->buffer); \
|
||||
free(_stack_); \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_push(SNAME *_stack_, V element) \
|
||||
{ \
|
||||
if (PFX##_full(_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] = PFX##_impl_default_value(); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_push_if(SNAME *_stack_, V 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 V PFX##_top(SNAME *_stack_) \
|
||||
{ \
|
||||
if (PFX##_empty(_stack_)) \
|
||||
PFX##_impl_default_value(); \
|
||||
\
|
||||
return _stack_->buffer[_stack_->count - 1]; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_contains(SNAME *_stack_, V element, int (*comparator)(V, V)) \
|
||||
{ \
|
||||
for (size_t i = 0; i < _stack_->count; i++) \
|
||||
{ \
|
||||
if (comparator(_stack_->buffer[i], element) == 0) \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_empty(SNAME *_stack_) \
|
||||
{ \
|
||||
return _stack_->count == 0; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_full(SNAME *_stack_) \
|
||||
{ \
|
||||
return _stack_->count >= SIZE; \
|
||||
} \
|
||||
\
|
||||
FMOD size_t PFX##_count(SNAME *_stack_) \
|
||||
{ \
|
||||
return _stack_->count; \
|
||||
} \
|
||||
\
|
||||
FMOD size_t PFX##_capacity(void) \
|
||||
{ \
|
||||
return SIZE; \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \
|
||||
{ \
|
||||
iter->target = target; \
|
||||
iter->cursor = iter->target->count - 1; \
|
||||
iter->start = true; \
|
||||
iter->end = PFX##_empty(target); \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_iter_start(SNAME##_iter *iter) \
|
||||
{ \
|
||||
return PFX##_empty(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_iter_end(SNAME##_iter *iter) \
|
||||
{ \
|
||||
return PFX##_empty(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \
|
||||
{ \
|
||||
iter->cursor = iter->target->count - 1; \
|
||||
iter->start = true; \
|
||||
iter->end = PFX##_empty(iter->target); \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \
|
||||
{ \
|
||||
iter->cursor = 0; \
|
||||
iter->start = PFX##_empty(iter->target); \
|
||||
iter->end = true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_iter_next(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
iter->start = PFX##_empty(iter->target); \
|
||||
\
|
||||
if (iter->cursor == 0) \
|
||||
iter->end = true; \
|
||||
else \
|
||||
iter->cursor--; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
iter->end = PFX##_empty(iter->target); \
|
||||
\
|
||||
if (iter->cursor == iter->target->count - 1) \
|
||||
iter->start = true; \
|
||||
else \
|
||||
iter->cursor++; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (PFX##_empty(iter->target)) \
|
||||
PFX##_impl_default_value(); \
|
||||
\
|
||||
return iter->target->buffer[iter->cursor]; \
|
||||
} \
|
||||
\
|
||||
FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (PFX##_empty(iter->target)) \
|
||||
return NULL; \
|
||||
\
|
||||
return &(iter->target->buffer[iter->cursor]); \
|
||||
} \
|
||||
\
|
||||
FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \
|
||||
{ \
|
||||
return iter->target->count - 1 - iter->cursor; \
|
||||
} \
|
||||
\
|
||||
static SNAME##_iter PFX##_impl_it_start(SNAME *_stack_) \
|
||||
{ \
|
||||
SNAME##_iter iter; \
|
||||
\
|
||||
PFX##_iter_init(&iter, _stack_); \
|
||||
PFX##_iter_to_start(&iter); \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
static SNAME##_iter PFX##_impl_it_end(SNAME *_stack_) \
|
||||
{ \
|
||||
SNAME##_iter iter; \
|
||||
\
|
||||
PFX##_iter_init(&iter, _stack_); \
|
||||
PFX##_iter_to_end(&iter); \
|
||||
\
|
||||
return iter; \
|
||||
}
|
||||
|
||||
#endif /* CMC_SAC_STACK_H */
|
||||
File renamed without changes.
+203
@@ -0,0 +1,203 @@
|
||||
/**
|
||||
* log.h
|
||||
*
|
||||
* Creation Date: 21/06/2019
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
/* Simple logging macros */
|
||||
/* You can toggle colors defining the macro CMC_LOG_COLOR but be sure that */
|
||||
/* your terminal supports ANSI color escape codes */
|
||||
|
||||
/**
|
||||
* What each error code means
|
||||
*
|
||||
* TRACE - Trace is used to describe the inner workings of the function or an
|
||||
* algorithm. It can be useful when trying to find for an error in the
|
||||
* algorithm or an untreated case.
|
||||
* DEBUG - Mainly used for debugging, tracking certain variables or anything
|
||||
* useful to help visualizing what your program is doing.
|
||||
* INFO - Info can be used as a heads up. It is also used to track the main
|
||||
* collection's allocation and deallocation.
|
||||
* WARN - Warnings are attributed to all cases where the function can recover
|
||||
* from and they are usually treated by it. In most cases the user can
|
||||
* treat these warnings himself.
|
||||
* ERROR - Something really bad happened. Your program will not crash yet but
|
||||
* depending on what comes next, it might crash indeed.
|
||||
* FATAL - This will probably be the last logging message before your program
|
||||
* crashes or goes into madness. Fatal errors are commonly attributed
|
||||
* to dereferencing NULL pointers.
|
||||
*
|
||||
* Log Level
|
||||
*
|
||||
* TRACE - 1
|
||||
* DEBUG - 2
|
||||
* INFO - 3
|
||||
* WARN - 4
|
||||
* ERROR - 5
|
||||
* FATAL - 6
|
||||
*
|
||||
* Functions API
|
||||
*
|
||||
* void cmc_log_tlevel(int level)
|
||||
* Set level for the Terminal Output to stderr.
|
||||
* void cmc_log_flevel(int level)
|
||||
* Set level for the File Output to FILE pointer.
|
||||
* void cmc_log_tenable(bool enabled)
|
||||
* Enables or disables Terminal Output to stderr.
|
||||
* void cmc_log_fenable(bool enabled)
|
||||
* Enables or disables File Output.
|
||||
* void cmc_log_file(FILE *file)
|
||||
* Set a file for writing the logging messages to it.
|
||||
* void cmc_log_set(bool enabled)
|
||||
* Sets on or off all the logging messages.
|
||||
*
|
||||
* How the Log Level is calculated
|
||||
*
|
||||
* - If the log level is 0 all logs are enabled.
|
||||
* - If the log level (X) is positive:
|
||||
* - All levels less than X will be disabled
|
||||
* - If X is greater than the level of FATAL, all logs are disabled
|
||||
* - If the log level (X) is negative:
|
||||
* - ALl levels greater than X are enabled
|
||||
* - If X is less than the level of FATAL, all logs are enabled
|
||||
*/
|
||||
|
||||
#ifndef CMC_LOG_H
|
||||
#define CMC_LOG_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
static const char *names[] = {"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"};
|
||||
static const char *color[] = {"\x1b[94m", "\x1b[36m", "\x1b[32m", "\x1b[33m", "\x1b[31m", "\x1b[35m"};
|
||||
|
||||
static struct
|
||||
{
|
||||
int tlevel; /* Terminal Level */
|
||||
int flevel; /* File Level */
|
||||
bool tenabled; /* Terminal Output Enabled */
|
||||
bool fenabled; /* File Output Enabled */
|
||||
FILE *file; /* File for Output */
|
||||
bool enabled; /* Logging enabled */
|
||||
} log_config = {0, 0, true, true, NULL, true};
|
||||
|
||||
typedef enum log_type_e
|
||||
{
|
||||
LOG_TRACE = 1,
|
||||
LOG_DEBUG = 2,
|
||||
LOG_INFO = 3,
|
||||
LOG_WARN = 4,
|
||||
LOG_ERROR = 5,
|
||||
LOG_FATAL = 6
|
||||
} log_type;
|
||||
|
||||
#define log_trace(fmt, ...) cmc_log(LOG_TRACE, __FILE__, __func__, __LINE__, fmt, __VA_ARGS__)
|
||||
#define log_debug(fmt, ...) cmc_log(LOG_DEBUG, __FILE__, __func__, __LINE__, fmt, __VA_ARGS__)
|
||||
#define log_info(fmt, ...) cmc_log(LOG_INFO, __FILE__, __func__, __LINE__, fmt, __VA_ARGS__)
|
||||
#define log_warn(fmt, ...) cmc_log(LOG_WARN, __FILE__, __func__, __LINE__, fmt, __VA_ARGS__)
|
||||
#define log_error(fmt, ...) cmc_log(LOG_ERROR, __FILE__, __func__, __LINE__, fmt, __VA_ARGS__)
|
||||
#define log_fatal(fmt, ...) cmc_log(LOG_FATAL, __FILE__, __func__, __LINE__, fmt, __VA_ARGS__)
|
||||
|
||||
static void cmc_log_tlevel(int terminal_level)
|
||||
{
|
||||
log_config.tlevel = terminal_level;
|
||||
}
|
||||
|
||||
static void cmc_log_flevel(int file_level)
|
||||
{
|
||||
log_config.flevel = file_level;
|
||||
}
|
||||
|
||||
static void cmc_log_tenable(bool enabled)
|
||||
{
|
||||
log_config.tenabled = enabled;
|
||||
}
|
||||
|
||||
static void cmc_log_fenable(bool enabled)
|
||||
{
|
||||
log_config.fenabled = enabled;
|
||||
}
|
||||
|
||||
static void cmc_log_file(FILE *file)
|
||||
{
|
||||
log_config.file = file;
|
||||
}
|
||||
|
||||
static void cmc_log_set(bool enabled)
|
||||
{
|
||||
log_config.enabled = enabled;
|
||||
}
|
||||
|
||||
static void cmc_log(log_type log, const char *filename, const char *funcname, int line, const char *fmt, ...)
|
||||
{
|
||||
if (!log_config.enabled)
|
||||
return;
|
||||
|
||||
if (log_config.tenabled)
|
||||
{
|
||||
if (log_config.tlevel < 0 && ((int)log * -1) < log_config.tlevel)
|
||||
return;
|
||||
else if (log_config.tlevel > 0 && (int)log < log_config.tlevel)
|
||||
return;
|
||||
|
||||
int i = (int)log - 1;
|
||||
|
||||
time_t t = time(NULL);
|
||||
struct tm *lt = localtime(&t);
|
||||
|
||||
char time[16];
|
||||
time[strftime(time, sizeof(time), "%H:%M:%S", lt)] = '\0';
|
||||
|
||||
#if defined(CMC_LOG_COLOR)
|
||||
fprintf(stderr,
|
||||
"%s %s%5s\x1b[0m \x1b[90m%s at %s:%d:\x1b[0m ",
|
||||
time, color[i], names[i], filename, funcname, line);
|
||||
#else
|
||||
fprintf(stderr,
|
||||
"%s %5s %s at %s:%d: ",
|
||||
time, names[i], filename, funcname, line);
|
||||
#endif
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vfprintf(stderr, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
if (log_config.file && log_config.fenabled)
|
||||
{
|
||||
if (log_config.flevel < 0 && ((int)log * -1) < log_config.flevel)
|
||||
return;
|
||||
else if (log_config.flevel > 0 && (int)log < log_config.flevel)
|
||||
return;
|
||||
|
||||
int i = (int)log - 1;
|
||||
|
||||
time_t t = time(NULL);
|
||||
struct tm *lt = localtime(&t);
|
||||
|
||||
char time[32];
|
||||
time[strftime(time, sizeof(time), "%Y-%m-%d %H:%M:%S", lt)] = '\0';
|
||||
|
||||
fprintf(log_config.file, "%s %5s %s at %s:%d: ", time, names[i], filename, funcname, line);
|
||||
|
||||
va_list file_args;
|
||||
va_start(file_args, fmt);
|
||||
vfprintf(log_config.file, fmt, file_args);
|
||||
va_end(file_args);
|
||||
|
||||
fprintf(log_config.file, "\n");
|
||||
fflush(log_config.file);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CMC_LOG_H */
|
||||
@@ -0,0 +1,15 @@
|
||||
CFLAGS= -Wno-unused-function -Wno-unused-paramter -Wno-unused-variable -std=c11 -Wall -Wextra
|
||||
|
||||
main:
|
||||
gcc foreach.c -o foreach $(CFLAGS)
|
||||
./foreach
|
||||
gcc iterators.c -o iterators $(CFLAGS)
|
||||
./iterators
|
||||
gcc contains.c -o contains $(CFLAGS)
|
||||
./contains
|
||||
gcc types.c -o types $(CFLAGS)
|
||||
./types
|
||||
gcc -c ./sep/sep.c -o ./sep/sep.o $(CFLAGS)
|
||||
gcc -c ./sep/main.c -o ./sep/main.o $(CFLAGS)
|
||||
gcc ./sep/sep.o ./sep/main.o -o ./sep/sep
|
||||
./sep/sep
|
||||
+100
-100
@@ -26,115 +26,115 @@ typedef union union_u {
|
||||
|
||||
typedef int (*func_t)(int, double, char *);
|
||||
|
||||
COLLECTION_GENERATE(LIST, l0, list0, /* FMOD */, /* K */, struct_t *)
|
||||
COLLECTION_GENERATE(STACK, s0, stack0, /* FMOD */, /* K */, struct_t *)
|
||||
COLLECTION_GENERATE(QUEUE, q0, queue0, /* FMOD */, /* K */, struct_t *)
|
||||
COLLECTION_GENERATE(DEQUE, d0, deque0, /* FMOD */, /* K */, struct_t *)
|
||||
COLLECTION_GENERATE(LINKEDLIST, ll0, linked0, /* FMOD */, /* K */, struct_t *)
|
||||
COLLECTION_GENERATE(HEAP, h0, heap0, /* FMOD */, /* K */, struct_t *)
|
||||
COLLECTION_GENERATE(TREESET, ts0, tset0, /* FMOD */, /* K */, struct_t *)
|
||||
COLLECTION_GENERATE(TREEMAP, tm0, tmap0, /* FMOD */, struct_t *, struct_t *)
|
||||
COLLECTION_GENERATE(HASHSET, hs0, hset0, /* FMOD */, /* K */, struct_t *)
|
||||
COLLECTION_GENERATE(HASHMAP, hm0, hmap0, /* FMOD */, struct_t *, struct_t *)
|
||||
COLLECTION_GENERATE(LIST, l0, list0, static, /* K */, struct_t *)
|
||||
COLLECTION_GENERATE(STACK, s0, stack0, static, /* K */, struct_t *)
|
||||
COLLECTION_GENERATE(QUEUE, q0, queue0, static, /* K */, struct_t *)
|
||||
COLLECTION_GENERATE(DEQUE, d0, deque0, static, /* K */, struct_t *)
|
||||
COLLECTION_GENERATE(LINKEDLIST, ll0, linked0, static, /* K */, struct_t *)
|
||||
COLLECTION_GENERATE(HEAP, h0, heap0, static, /* K */, struct_t *)
|
||||
COLLECTION_GENERATE(TREESET, ts0, tset0, static, /* K */, struct_t *)
|
||||
COLLECTION_GENERATE(TREEMAP, tm0, tmap0, static, struct_t *, struct_t *)
|
||||
COLLECTION_GENERATE(HASHSET, hs0, hset0, static, /* K */, struct_t *)
|
||||
COLLECTION_GENERATE(HASHMAP, hm0, hmap0, static, struct_t *, struct_t *)
|
||||
|
||||
COLLECTION_GENERATE(LIST, l1, list1, /* FMOD */, /* K */, struct_t)
|
||||
COLLECTION_GENERATE(STACK, s1, stack1, /* FMOD */, /* K */, struct_t)
|
||||
COLLECTION_GENERATE(QUEUE, q1, queue1, /* FMOD */, /* K */, struct_t)
|
||||
COLLECTION_GENERATE(DEQUE, d1, deque1, /* FMOD */, /* K */, struct_t)
|
||||
COLLECTION_GENERATE(LINKEDLIST, ll1, linked1, /* FMOD */, /* K */, struct_t)
|
||||
COLLECTION_GENERATE(HEAP, h1, heap1, /* FMOD */, /* K */, struct_t)
|
||||
COLLECTION_GENERATE(TREESET, ts1, tset1, /* FMOD */, /* K */, struct_t)
|
||||
COLLECTION_GENERATE(TREEMAP, tm1, tmap1, /* FMOD */, struct_t, struct_t)
|
||||
COLLECTION_GENERATE(HASHSET, hs1, hset1, /* FMOD */, /* K */, struct_t)
|
||||
COLLECTION_GENERATE(HASHMAP, hm1, hmap1, /* FMOD */, struct_t, struct_t)
|
||||
COLLECTION_GENERATE(LIST, l1, list1, static, /* K */, struct_t)
|
||||
COLLECTION_GENERATE(STACK, s1, stack1, static, /* K */, struct_t)
|
||||
COLLECTION_GENERATE(QUEUE, q1, queue1, static, /* K */, struct_t)
|
||||
COLLECTION_GENERATE(DEQUE, d1, deque1, static, /* K */, struct_t)
|
||||
COLLECTION_GENERATE(LINKEDLIST, ll1, linked1, static, /* K */, struct_t)
|
||||
COLLECTION_GENERATE(HEAP, h1, heap1, static, /* K */, struct_t)
|
||||
COLLECTION_GENERATE(TREESET, ts1, tset1, static, /* K */, struct_t)
|
||||
COLLECTION_GENERATE(TREEMAP, tm1, tmap1, static, struct_t, struct_t)
|
||||
COLLECTION_GENERATE(HASHSET, hs1, hset1, static, /* K */, struct_t)
|
||||
COLLECTION_GENERATE(HASHMAP, hm1, hmap1, static, struct_t, struct_t)
|
||||
|
||||
COLLECTION_GENERATE(LIST, l2, list2, /* FMOD */, /* K */, int)
|
||||
COLLECTION_GENERATE(STACK, s2, stack2, /* FMOD */, /* K */, int)
|
||||
COLLECTION_GENERATE(QUEUE, q2, queue2, /* FMOD */, /* K */, int)
|
||||
COLLECTION_GENERATE(DEQUE, d2, deque2, /* FMOD */, /* K */, int)
|
||||
COLLECTION_GENERATE(LINKEDLIST, ll2, linked2, /* FMOD */, /* K */, int)
|
||||
COLLECTION_GENERATE(HEAP, h2, heap2, /* FMOD */, /* K */, int)
|
||||
COLLECTION_GENERATE(TREESET, ts2, tset2, /* FMOD */, /* K */, int)
|
||||
COLLECTION_GENERATE(TREEMAP, tm2, tmap2, /* FMOD */, int, int)
|
||||
COLLECTION_GENERATE(HASHSET, hs2, hset2, /* FMOD */, /* K */, int)
|
||||
COLLECTION_GENERATE(HASHMAP, hm2, hmap2, /* FMOD */, int, int)
|
||||
COLLECTION_GENERATE(LIST, l2, list2, static, /* K */, int)
|
||||
COLLECTION_GENERATE(STACK, s2, stack2, static, /* K */, int)
|
||||
COLLECTION_GENERATE(QUEUE, q2, queue2, static, /* K */, int)
|
||||
COLLECTION_GENERATE(DEQUE, d2, deque2, static, /* K */, int)
|
||||
COLLECTION_GENERATE(LINKEDLIST, ll2, linked2, static, /* K */, int)
|
||||
COLLECTION_GENERATE(HEAP, h2, heap2, static, /* K */, int)
|
||||
COLLECTION_GENERATE(TREESET, ts2, tset2, static, /* K */, int)
|
||||
COLLECTION_GENERATE(TREEMAP, tm2, tmap2, static, int, int)
|
||||
COLLECTION_GENERATE(HASHSET, hs2, hset2, static, /* K */, int)
|
||||
COLLECTION_GENERATE(HASHMAP, hm2, hmap2, static, int, int)
|
||||
|
||||
COLLECTION_GENERATE(LIST, l3, list3, /* FMOD */, /* K */, int *)
|
||||
COLLECTION_GENERATE(STACK, s3, stack3, /* FMOD */, /* K */, int *)
|
||||
COLLECTION_GENERATE(QUEUE, q3, queue3, /* FMOD */, /* K */, int *)
|
||||
COLLECTION_GENERATE(DEQUE, d3, deque3, /* FMOD */, /* K */, int *)
|
||||
COLLECTION_GENERATE(LINKEDLIST, ll3, linked3, /* FMOD */, /* K */, int *)
|
||||
COLLECTION_GENERATE(HEAP, h3, heap3, /* FMOD */, /* K */, int *)
|
||||
COLLECTION_GENERATE(TREESET, ts3, tset3, /* FMOD */, /* K */, int *)
|
||||
COLLECTION_GENERATE(TREEMAP, tm3, tmap3, /* FMOD */, int *, int *)
|
||||
COLLECTION_GENERATE(HASHSET, hs3, hset3, /* FMOD */, /* K */, int *)
|
||||
COLLECTION_GENERATE(HASHMAP, hm3, hmap3, /* FMOD */, int *, int *)
|
||||
COLLECTION_GENERATE(LIST, l3, list3, static, /* K */, int *)
|
||||
COLLECTION_GENERATE(STACK, s3, stack3, static, /* K */, int *)
|
||||
COLLECTION_GENERATE(QUEUE, q3, queue3, static, /* K */, int *)
|
||||
COLLECTION_GENERATE(DEQUE, d3, deque3, static, /* K */, int *)
|
||||
COLLECTION_GENERATE(LINKEDLIST, ll3, linked3, static, /* K */, int *)
|
||||
COLLECTION_GENERATE(HEAP, h3, heap3, static, /* K */, int *)
|
||||
COLLECTION_GENERATE(TREESET, ts3, tset3, static, /* K */, int *)
|
||||
COLLECTION_GENERATE(TREEMAP, tm3, tmap3, static, int *, int *)
|
||||
COLLECTION_GENERATE(HASHSET, hs3, hset3, static, /* K */, int *)
|
||||
COLLECTION_GENERATE(HASHMAP, hm3, hmap3, static, int *, int *)
|
||||
|
||||
COLLECTION_GENERATE(LIST, l4, list4, /* FMOD */, /* K */, enum_t *)
|
||||
COLLECTION_GENERATE(STACK, s4, stack4, /* FMOD */, /* K */, enum_t *)
|
||||
COLLECTION_GENERATE(QUEUE, q4, queue4, /* FMOD */, /* K */, enum_t *)
|
||||
COLLECTION_GENERATE(DEQUE, d4, deque4, /* FMOD */, /* K */, enum_t *)
|
||||
COLLECTION_GENERATE(LINKEDLIST, ll4, linked4, /* FMOD */, /* K */, enum_t *)
|
||||
COLLECTION_GENERATE(HEAP, h4, heap4, /* FMOD */, /* K */, enum_t *)
|
||||
COLLECTION_GENERATE(TREESET, ts4, tset4, /* FMOD */, /* K */, enum_t *)
|
||||
COLLECTION_GENERATE(TREEMAP, tm4, tmap4, /* FMOD */, enum_t *, enum_t *)
|
||||
COLLECTION_GENERATE(HASHSET, hs4, hset4, /* FMOD */, /* K */, enum_t *)
|
||||
COLLECTION_GENERATE(HASHMAP, hm4, hmap4, /* FMOD */, enum_t *, enum_t *)
|
||||
COLLECTION_GENERATE(LIST, l4, list4, static, /* K */, enum_t *)
|
||||
COLLECTION_GENERATE(STACK, s4, stack4, static, /* K */, enum_t *)
|
||||
COLLECTION_GENERATE(QUEUE, q4, queue4, static, /* K */, enum_t *)
|
||||
COLLECTION_GENERATE(DEQUE, d4, deque4, static, /* K */, enum_t *)
|
||||
COLLECTION_GENERATE(LINKEDLIST, ll4, linked4, static, /* K */, enum_t *)
|
||||
COLLECTION_GENERATE(HEAP, h4, heap4, static, /* K */, enum_t *)
|
||||
COLLECTION_GENERATE(TREESET, ts4, tset4, static, /* K */, enum_t *)
|
||||
COLLECTION_GENERATE(TREEMAP, tm4, tmap4, static, enum_t *, enum_t *)
|
||||
COLLECTION_GENERATE(HASHSET, hs4, hset4, static, /* K */, enum_t *)
|
||||
COLLECTION_GENERATE(HASHMAP, hm4, hmap4, static, enum_t *, enum_t *)
|
||||
|
||||
COLLECTION_GENERATE(LIST, l5, list5, /* FMOD */, /* K */, enum_t)
|
||||
COLLECTION_GENERATE(STACK, s5, stack5, /* FMOD */, /* K */, enum_t)
|
||||
COLLECTION_GENERATE(QUEUE, q5, queue5, /* FMOD */, /* K */, enum_t)
|
||||
COLLECTION_GENERATE(DEQUE, d5, deque5, /* FMOD */, /* K */, enum_t)
|
||||
COLLECTION_GENERATE(LINKEDLIST, ll5, linked5, /* FMOD */, /* K */, enum_t)
|
||||
COLLECTION_GENERATE(HEAP, h5, heap5, /* FMOD */, /* K */, enum_t)
|
||||
COLLECTION_GENERATE(TREESET, ts5, tset5, /* FMOD */, /* K */, enum_t)
|
||||
COLLECTION_GENERATE(TREEMAP, tm5, tmap5, /* FMOD */, enum_t, enum_t)
|
||||
COLLECTION_GENERATE(HASHSET, hs5, hset5, /* FMOD */, /* K */, enum_t)
|
||||
COLLECTION_GENERATE(HASHMAP, hm5, hmap5, /* FMOD */, enum_t, enum_t)
|
||||
COLLECTION_GENERATE(LIST, l5, list5, static, /* K */, enum_t)
|
||||
COLLECTION_GENERATE(STACK, s5, stack5, static, /* K */, enum_t)
|
||||
COLLECTION_GENERATE(QUEUE, q5, queue5, static, /* K */, enum_t)
|
||||
COLLECTION_GENERATE(DEQUE, d5, deque5, static, /* K */, enum_t)
|
||||
COLLECTION_GENERATE(LINKEDLIST, ll5, linked5, static, /* K */, enum_t)
|
||||
COLLECTION_GENERATE(HEAP, h5, heap5, static, /* K */, enum_t)
|
||||
COLLECTION_GENERATE(TREESET, ts5, tset5, static, /* K */, enum_t)
|
||||
COLLECTION_GENERATE(TREEMAP, tm5, tmap5, static, enum_t, enum_t)
|
||||
COLLECTION_GENERATE(HASHSET, hs5, hset5, static, /* K */, enum_t)
|
||||
COLLECTION_GENERATE(HASHMAP, hm5, hmap5, static, enum_t, enum_t)
|
||||
|
||||
COLLECTION_GENERATE(LIST, l6, list6, /* FMOD */, /* K */, union_t *)
|
||||
COLLECTION_GENERATE(STACK, s6, stack6, /* FMOD */, /* K */, union_t *)
|
||||
COLLECTION_GENERATE(QUEUE, q6, queue6, /* FMOD */, /* K */, union_t *)
|
||||
COLLECTION_GENERATE(DEQUE, d6, deque6, /* FMOD */, /* K */, union_t *)
|
||||
COLLECTION_GENERATE(LINKEDLIST, ll6, linked6, /* FMOD */, /* K */, union_t *)
|
||||
COLLECTION_GENERATE(HEAP, h6, heap6, /* FMOD */, /* K */, union_t *)
|
||||
COLLECTION_GENERATE(TREESET, ts6, tset6, /* FMOD */, /* K */, union_t *)
|
||||
COLLECTION_GENERATE(TREEMAP, tm6, tmap6, /* FMOD */, union_t *, union_t *)
|
||||
COLLECTION_GENERATE(HASHSET, hs6, hset6, /* FMOD */, /* K */, union_t *)
|
||||
COLLECTION_GENERATE(HASHMAP, hm6, hmap6, /* FMOD */, union_t *, union_t *)
|
||||
COLLECTION_GENERATE(LIST, l6, list6, static, /* K */, union_t *)
|
||||
COLLECTION_GENERATE(STACK, s6, stack6, static, /* K */, union_t *)
|
||||
COLLECTION_GENERATE(QUEUE, q6, queue6, static, /* K */, union_t *)
|
||||
COLLECTION_GENERATE(DEQUE, d6, deque6, static, /* K */, union_t *)
|
||||
COLLECTION_GENERATE(LINKEDLIST, ll6, linked6, static, /* K */, union_t *)
|
||||
COLLECTION_GENERATE(HEAP, h6, heap6, static, /* K */, union_t *)
|
||||
COLLECTION_GENERATE(TREESET, ts6, tset6, static, /* K */, union_t *)
|
||||
COLLECTION_GENERATE(TREEMAP, tm6, tmap6, static, union_t *, union_t *)
|
||||
COLLECTION_GENERATE(HASHSET, hs6, hset6, static, /* K */, union_t *)
|
||||
COLLECTION_GENERATE(HASHMAP, hm6, hmap6, static, union_t *, union_t *)
|
||||
|
||||
COLLECTION_GENERATE(LIST, l7, list7, /* FMOD */, /* K */, union_t)
|
||||
COLLECTION_GENERATE(STACK, s7, stack7, /* FMOD */, /* K */, union_t)
|
||||
COLLECTION_GENERATE(QUEUE, q7, queue7, /* FMOD */, /* K */, union_t)
|
||||
COLLECTION_GENERATE(DEQUE, d7, deque7, /* FMOD */, /* K */, union_t)
|
||||
COLLECTION_GENERATE(LINKEDLIST, ll7, linked7, /* FMOD */, /* K */, union_t)
|
||||
COLLECTION_GENERATE(HEAP, h7, heap7, /* FMOD */, /* K */, union_t)
|
||||
COLLECTION_GENERATE(TREESET, ts7, tset7, /* FMOD */, /* K */, union_t)
|
||||
COLLECTION_GENERATE(TREEMAP, tm7, tmap7, /* FMOD */, union_t, union_t)
|
||||
COLLECTION_GENERATE(HASHSET, hs7, hset7, /* FMOD */, /* K */, union_t)
|
||||
COLLECTION_GENERATE(HASHMAP, hm7, hmap7, /* FMOD */, union_t, union_t)
|
||||
COLLECTION_GENERATE(LIST, l7, list7, static, /* K */, union_t)
|
||||
COLLECTION_GENERATE(STACK, s7, stack7, static, /* K */, union_t)
|
||||
COLLECTION_GENERATE(QUEUE, q7, queue7, static, /* K */, union_t)
|
||||
COLLECTION_GENERATE(DEQUE, d7, deque7, static, /* K */, union_t)
|
||||
COLLECTION_GENERATE(LINKEDLIST, ll7, linked7, static, /* K */, union_t)
|
||||
COLLECTION_GENERATE(HEAP, h7, heap7, static, /* K */, union_t)
|
||||
COLLECTION_GENERATE(TREESET, ts7, tset7, static, /* K */, union_t)
|
||||
COLLECTION_GENERATE(TREEMAP, tm7, tmap7, static, union_t, union_t)
|
||||
COLLECTION_GENERATE(HASHSET, hs7, hset7, static, /* K */, union_t)
|
||||
COLLECTION_GENERATE(HASHMAP, hm7, hmap7, static, union_t, union_t)
|
||||
|
||||
COLLECTION_GENERATE(LIST, l8, list8, /* FMOD */, /* K */, func_t)
|
||||
COLLECTION_GENERATE(STACK, s8, stack8, /* FMOD */, /* K */, func_t)
|
||||
COLLECTION_GENERATE(QUEUE, q8, queue8, /* FMOD */, /* K */, func_t)
|
||||
COLLECTION_GENERATE(DEQUE, d8, deque8, /* FMOD */, /* K */, func_t)
|
||||
COLLECTION_GENERATE(LINKEDLIST, ll8, linked8, /* FMOD */, /* K */, func_t)
|
||||
COLLECTION_GENERATE(HEAP, h8, heap8, /* FMOD */, /* K */, func_t)
|
||||
COLLECTION_GENERATE(TREESET, ts8, tset8, /* FMOD */, /* K */, func_t)
|
||||
COLLECTION_GENERATE(TREEMAP, tm8, tmap8, /* FMOD */, func_t, func_t)
|
||||
COLLECTION_GENERATE(HASHSET, hs8, hset8, /* FMOD */, /* K */, func_t)
|
||||
COLLECTION_GENERATE(HASHMAP, hm8, hmap8, /* FMOD */, func_t, func_t)
|
||||
COLLECTION_GENERATE(LIST, l8, list8, static, /* K */, func_t)
|
||||
COLLECTION_GENERATE(STACK, s8, stack8, static, /* K */, func_t)
|
||||
COLLECTION_GENERATE(QUEUE, q8, queue8, static, /* K */, func_t)
|
||||
COLLECTION_GENERATE(DEQUE, d8, deque8, static, /* K */, func_t)
|
||||
COLLECTION_GENERATE(LINKEDLIST, ll8, linked8, static, /* K */, func_t)
|
||||
COLLECTION_GENERATE(HEAP, h8, heap8, static, /* K */, func_t)
|
||||
COLLECTION_GENERATE(TREESET, ts8, tset8, static, /* K */, func_t)
|
||||
COLLECTION_GENERATE(TREEMAP, tm8, tmap8, static, func_t, func_t)
|
||||
COLLECTION_GENERATE(HASHSET, hs8, hset8, static, /* K */, func_t)
|
||||
COLLECTION_GENERATE(HASHMAP, hm8, hmap8, static, func_t, func_t)
|
||||
|
||||
COLLECTION_GENERATE(LIST, l9, list9, /* FMOD */, /* K */, func_t)
|
||||
COLLECTION_GENERATE(STACK, s9, stack9, /* FMOD */, /* K */, func_t)
|
||||
COLLECTION_GENERATE(QUEUE, q9, queue9, /* FMOD */, /* K */, func_t)
|
||||
COLLECTION_GENERATE(DEQUE, d9, deque9, /* FMOD */, /* K */, func_t)
|
||||
COLLECTION_GENERATE(LINKEDLIST, ll9, linked9, /* FMOD */, /* K */, func_t)
|
||||
COLLECTION_GENERATE(HEAP, h9, heap9, /* FMOD */, /* K */, func_t)
|
||||
COLLECTION_GENERATE(TREESET, ts9, tset9, /* FMOD */, /* K */, func_t)
|
||||
COLLECTION_GENERATE(TREEMAP, tm9, tmap9, /* FMOD */, func_t, func_t)
|
||||
COLLECTION_GENERATE(HASHSET, hs9, hset9, /* FMOD */, /* K */, func_t)
|
||||
COLLECTION_GENERATE(HASHMAP, hm9, hmap9, /* FMOD */, func_t, func_t)
|
||||
COLLECTION_GENERATE(LIST, l9, list9, static, /* K */, func_t)
|
||||
COLLECTION_GENERATE(STACK, s9, stack9, static, /* K */, func_t)
|
||||
COLLECTION_GENERATE(QUEUE, q9, queue9, static, /* K */, func_t)
|
||||
COLLECTION_GENERATE(DEQUE, d9, deque9, static, /* K */, func_t)
|
||||
COLLECTION_GENERATE(LINKEDLIST, ll9, linked9, static, /* K */, func_t)
|
||||
COLLECTION_GENERATE(HEAP, h9, heap9, static, /* K */, func_t)
|
||||
COLLECTION_GENERATE(TREESET, ts9, tset9, static, /* K */, func_t)
|
||||
COLLECTION_GENERATE(TREEMAP, tm9, tmap9, static, func_t, func_t)
|
||||
COLLECTION_GENERATE(HASHSET, hs9, hset9, static, /* K */, func_t)
|
||||
COLLECTION_GENERATE(HASHMAP, hm9, hmap9, static, func_t, func_t)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user