20 Commits
Author SHA1 Message Date
Leonardo 6213b42d5a v1.5.0 2019-06-21 16:17:11 -03:00
Leonardo 8010cce8c7 Restructuring project
View CHANGELOG on v1.5.0 for more information
2019-06-21 16:07:03 -03:00
Leonardo dad9b7a81f Update README.md and Documentation.md 2019-06-19 01:23:18 -03:00
Leonardo 21a2bea746 Fixing previous commit 2019-06-13 00:44:41 -03:00
Leonardo b0a2e42cfe Minor fixes all around
Changed some input parameter names
Updated TODO
Changed how hashtables initialization works. Now the given initial capacity will be guaranteed to be reached before the hashtable rehashes (load is now considered in the calculation).
2019-06-13 00:40:55 -03:00
Leonardo b6cbadd8e2 v1.4.3 2019-06-11 00:44:10 -03:00
Leonardo 870cfe302d Added more set functions
Added is_subset, is_superset, is_proper_subset, is_proper_superset, is_disjointset
2019-06-11 00:42:11 -03:00
Leonardo ea04c7ddaa Quickfix function name 2019-06-09 23:53:34 -03:00
Leonardo a86140094c Update .travis.yml 2019-06-07 01:48:25 -03:00
Leonardo 85c49a92fd v1.4.2 2019-06-07 01:45:10 -03:00
Leonardo aac07a645c Now collections accept plain struct
Also fixed impl prefixes and function modifiers
Added new test for all possible data types
Fixed some READMEs
2019-06-07 01:44:15 -03:00
Leonardo efdb1c80a3 Changed TreeSet max and min to be compatible with the TreeMap and the hash collections 2019-06-06 23:42:14 -03:00
Leonardo a9c7439d15 Update .travis.yml 2019-05-30 21:29:41 -03:00
Leonardo 26555bc10a v1.4.1 2019-05-30 21:27:18 -03:00
Leonardo 0f84d65656 Removed PUBLIC and PRIVATE, corrected some examples and new test 2019-05-30 21:23:37 -03:00
Leonardo a9b775419d Update Documentation.md 2019-05-30 16:54:40 -03:00
Leonardo a384a8b180 Update .gitignore 2019-05-27 17:13:09 -03:00
Leonardo 424582f969 Update documentation and TODO 2019-05-23 23:08:03 -03:00
Leonardo 6044e92262 Update CONTRIBUTING.md 2019-05-17 23:41:31 -03:00
Leonardo ee96bcbc55 Update CHANGELOG
reversed changelog ~duh
2019-05-16 17:07:03 -03:00
75 changed files with 5626 additions and 2777 deletions

No files matched your search

+4 -1
View File
@@ -52,4 +52,7 @@ Mkfile.old
dkms.conf
# vscode folder
.vscode
.vscode
# Experimental folder
experimental/
+2 -8
View File
@@ -8,15 +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 pointertype.c -Wall -Wextra -o pointertype -std=c11
- ./pointertype
- make
+101 -65
View File
@@ -1,5 +1,106 @@
# 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
- is_subset
- is_proper_subset
- is_superset
- is_proper_subset
- is_disjointset
1.4.2
Adapted code so that plain struct type is accepted
Changed TreeSet max and min to be compatible with the TreeMap and the hash collections
Changed function modifier of all implementation detail to static
Fixed some implementation detail functions that were not prefixed with impl
Added types.c to test if it is possible to compile all the collections' generated code accepting all C data types
Removed pointertype.c (replaced by types.c)
1.4.1
Removed PUBLIC and PRIVATE from the main macro
Corrected examples and benchmark
Added new test consisting of compiling the header and source separately
1.4.0
New way on how iterators work to all collections
Added iter_init to work with stack allocated iterators
Added iter_new and iter_free to work with heap allocated iterators
Added two pointers to functions (it_start and it_end) that allow you to access iterators to both start and end of the target collection easily
iter_next and iter_prev now only move the iterator
To access the key, value and index, use a separate function
Removed FOR_EACH_MAP as it is no longer necessary since FOR_EACH also works to associative containers now
Updated benchmark, examples and tests to work on these new iterators
Changed pointertype test to be a pointer to struct instead of pointer to char
Added CHANGELOG and TODO
1.3.0
Changed how the linkedlist functions relative to nodes work
Removed reference to owner list on each node
Renamed some functions for consistency
1.2.4
Fixing some declarations in hashset and hashmap where a pointer type would cause problems
Added a test to make sure all collections support pointer type
Tests:
- pointertype
1.2.3
Added get_ref functions to all collections that support it (only included in hashmap, linkedlist, list and treemap)
1.2.2
Removed unnecessary modulo operation in hashtable functions
1.2.1
Optimized list - now using 'string.h' functions to shift elements around instead of for-loops:
- memset
- memcpy
- memmove
1.2.0
'contains' functions added to all collections
'contains' tests and benchmark
Unified Benchmark
Updated examples
1.1.3
Renamed deque's 'rear' struct member to 'back' to be more consistent with other collections
Better benchmark and foreach tests are alphabetically ordered
1.1.2
Fixing iterators for when they are initialized with an empty target
Better iterator tests
More examples
1.1.1
Reordering functions (implementation details are now at the end of each file)
1.1.0
Added new list functions:
- new_from
- prepend
- insert
- append
- remove
- fits
1.0.1
Fixed hashset logic in robin-hood hashing
1.0.0
First stable version
Includes the following collections:
@@ -18,68 +119,3 @@
Tests:
- foreach
- iterator
1.0.1
Fixed hashset logic in robin-hood hashing
1.1.0
Added new list functions:
- new_from
- prepend
- insert
- append
- remove
- fits
1.1.1
Reordering functions (implementation details are now at the end of each file)
1.1.2
Fixing iterators for when they are initialized with an empty target
Better iterator tests
More examples
1.1.3
Renamed deque's 'rear' struct member to 'back' to be more consistent with other collections
Better benchmark and foreach tests are alphabetically ordered
1.2.0
'contains' functions added to all collections
'contains' tests and benchmark
Unified Benchmark
Updated examples
1.2.1
Optimized list - now using 'string.h' functions to shift elements around instead of for-loops:
- memset
- memcpy
- memmove
1.2.2
Removed unnecessary modulo operation in hashtable functions
1.2.3
Added get_ref functions to all collections that support it (only included in hashmap, linkedlist, list and treemap)
1.2.4
Fixing some declarations in hashset and hashmap where a pointer type would cause problems
Added a test to make sure all collections support pointer type
Tests:
- pointertype
1.3.0
Changed how the linkedlist functions relative to nodes work
Removed reference to owner list on each node
Renamed some functions for consistency
1.4.0
New way on how iterators work to all collections
Added iter_init to work with stack allocated iterators
Added iter_new and iter_free to work with heap allocated iterators
Added two pointers to functions (it_start and it_end) that allow you to access iterators to both start and end of the target collection easily
iter_next and iter_prev now only move the iterator
To access the key, value and index, use a separate function
Removed FOR_EACH_MAP as it is no longer necessary since FOR_EACH also works to associative containers now
Updated benchmark, examples and tests to work on these new iterators
Changed pointertype test to be a pointer to struct instead of pointer to char
Added CHANGELOG and TODO
+2
View File
@@ -13,6 +13,8 @@ Check out `bug_report.md` and `feature_request.md` templates in the `.github` fo
## Here are things you could work on:
> You can check out the TODO file to see what I've planned on doing, in case you want to work on any of those topics
1. New features, new functions, new stuff!
* Before adding anything new, please, first create an issue for it to be discussed;
* Write tests to anything new you make.
+1394 -753
View File
File diff suppressed because it is too large. Load diff
+68 -30
View File
@@ -3,31 +3,76 @@
Generate Simple Data Structures of any type in C for you to use in your projects.
![License](https://img.shields.io/badge/License-MIT-blue.svg)
![Version](https://img.shields.io/badge/Version-v1.4.0-orange.svg)
![Version](https://img.shields.io/badge/Version-v1.5.0-orange.svg)
![Build](https://travis-ci.org/LeoVen/C-Macro-Collections.svg?branch=master)
## Project Structure
* __benchmarks__ - Where all benchmarks are hosted
* __examples__ - Examples separated by collections
* __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*.
## Available Collections
* List
* LinkedList
* Stack
* Queue
* Deque
* Heap
* TreeSet
* TreeMap
* HashSet
* HashMap
* Main C Macro Collections Library
* Deque
* HashMap
* HashSet
* Heap
* LinkedList
* List
* Queue
* Stack
* TreeMap
* TreeSet
* Extra Collections Library
* LinkedQueue
* Stack Allocated Collections Library
* Stack
## Available Collections in future updates
### More to Come
* 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.
## 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).
@@ -85,21 +130,14 @@ Check out the **Documentation.md** to know exactly what represents the *end* and
When including `macro_collections.h` in your source code you gain access to a macro called `COLLECTION_GENERATE` with the following parameters:
> Note: in future updates, PRIVATE and PUBLIC will no longer exist
* \*__C__ - Container name in uppercase (*LIST*, *LINKEDLIST*, *STACK*, *QUEUE*, *DEQUE*, *HEAP*, *TREESET*, *TREEMAP*, *HASHSET*, *HASHMAP*).
* \*__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`).
* __C__ - Container name in uppercase (*LIST*, *LINKEDLIST*, *STACK*, *QUEUE*, *DEQUE*, *HEAP*, *TREESET*, *TREEMAP*, *HASHSET*, *HASHMAP*).
* __PFX__ - Functions prefix or namespace.
* __SNAME__ - Structure name (`typedef struct SNAME##_s SNAME`).
* __FMOD__ - Function modifier (`static` or empty).
* \*\*__K__ - Key type. Only used in *HASHMAP* and *TREEMAP*; ignored by others.
* \*__V__ - Value type. Primary type for most collections, or value to be mapped by *HASHMAP* and *TREEMAP*.
* \*__K__ - Key type. Only used in *HASHMAP* and *TREEMAP*; ignored by others.
* __V__ - Value type. Primary type for most collections, or value to be mapped by *HASHMAP* and *TREEMAP*.
\* Required parameters
\*\* Required only by *HASHMAP* and *TREEMAP*
\* Required only by *HASHMAP* and *TREEMAP*
**In fact, all macros follow this pattern.** So whenever you see a macro with a bunch of parameters and you don't know what they are, you can check out the above list.
@@ -110,4 +148,4 @@ When including `foreach.h` in your source code you gain access to all for-each m
* __TARGET__ - The variable name of the collection you wish to iterate over.
* __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.
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.
+15 -22
View File
@@ -1,13 +1,15 @@
TODO
[ ] Finish Documentation
[ ] Simplify PUBLIC and PRIVATE
[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,37 +22,28 @@ PLANNED
Before 2.0
Get Documentation fixed and completed
1.5
Simplify PUBLIC and PRIVATE (simply remove them)
Conditional code generation
Add extra content macro (Insert/Remove/Append/Prepend) and let user decide if he wants to include them or not
Separate Implementation Detail into a different MACRO (LIST_GENERATE_DETAIL)
1.6
Iterator move and move_to
LinkedList - Insert/Remove/Append/Prepend/Extract
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
1.7
Add shrink function that shrinks the internal buffer to current count of elements
LinkedList - Insert/Remove/Append/Prepend/Extract
Resize buffer function
Add dispose method to each collection in order to automatically free its data
Add copy functions (copy of a collection)
2.0
Add multiset, multimap and new heap implementation
Add new heap collection implementation
Add all stack based collections
2.1
Adapt multiset, multimap, treehashmap and new heap implementation to the current standards
Add dispose method to each collection in order to automatically free its data
Add variadic macros (generate only the necessary functions)
2.2
Add serialization functions
Header:
%d - Type specifier (LIST = 0, DEQUE = 1, STACK = 2, etc) for quick check
%llu - How many elements there are
%d - If data varies in size
%llu - Data size
2.3
Iterator functions (functions that operate relative to iterators position) like add or remove ranges
Sometime
Add treehashmap
SOMETIME
Add TreeHashMap
+10 -10
View File
@@ -60,16 +60,16 @@ void shuffle(int *array, mt_state_ptr st)
}
}
COLLECTION_GENERATE(LIST, PUBLIC, l, list, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(STACK, PUBLIC, s, stack, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(QUEUE, PUBLIC, q, queue, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(DEQUE, PUBLIC, d, deque, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(LINKEDLIST, PUBLIC, ll, linked, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(HEAP, PUBLIC, h, heap, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(TREESET, PUBLIC, ts, tset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(TREEMAP, PUBLIC, tm, tmap, /* FMOD */, int, int)
COLLECTION_GENERATE(HASHSET, PUBLIC, hs, hset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(HASHMAP, PUBLIC, hm, hmap, /* FMOD */, int, int)
COLLECTION_GENERATE(LIST, l, list, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(STACK, s, stack, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(QUEUE, q, queue, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(DEQUE, d, deque, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(LINKEDLIST, ll, linked, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(HEAP, h, heap, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(TREESET, ts, tset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(TREEMAP, tm, tmap, /* FMOD */, int, int)
COLLECTION_GENERATE(HASHSET, hs, hset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(HASHMAP, hm, hmap, /* FMOD */, int, int)
#define BENCHMARK(NAME, PFX, sname, initfunc, insertbody, removebody, searchbody) \
void NAME##_io_benchmark(int *array, int *sarray, size_t s) \
+14
View File
@@ -0,0 +1,14 @@
# Examples
* deque - DEQUE collection examples
* hashmap - HASHMAP collection examples
* hashset - HASHSET collection examples
* heap - HEAP collection examples
* iterators - Examples of using the collection's iterators
* linkedlist - LINKEDLIST collection examples
* list - LIST collection examples
* others - Other examples, generally more robust and using multiple collections
* queue - QUEUE collection examples
* stack - STACK collection examples
* treemap - TREEMAP collection examples
* treeset - TREESET collection examples
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -8,7 +8,7 @@
*
* Iterator Example
*/
#include "deque.h"
#include "cmc/deque.h"
#include <stdio.h>
#include <inttypes.h>
+1
View File
@@ -1,4 +1,5 @@
# Hashmap examples
* countries - Uses a hashmap to map the country name to its population
* foreach.c - ForEach macro example
* iterator.c - A complete example of the hashmap iterator
+1 -1
View File
@@ -1,4 +1,4 @@
#include "hashmap.h"
#include "cmc/hashmap.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+65
View File
@@ -0,0 +1,65 @@
/**
* iterator.c
*
* Creation Date: 23/05/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
* Foreach macro example
*/
#include "cmc/hashmap.h"
#include "utl/foreach.h"
#include <stdio.h>
// Int hash function
size_t inthash(int t)
{
size_t a = t;
a += ~(a << 15);
a ^= (a >> 10);
a += (a << 3);
a ^= (a >> 6);
a += ~(a << 11);
a ^= (a >> 16);
return a;
}
// Int compare function
int intcmp(int a, int b)
{
return (a > b) - (a < b);
}
// Generate all the code for the hashmap
HASHMAP_GENERATE(hm, hashmap, /* FMOD */, int, double)
int main(void)
{
// Create a new hashmap with custom hash function
// The comparison function is only required to know if the key looked for was found
hashmap *map = hm_new(1000, 0.6, intcmp, inthash);
// Add keys mapped to a value
for (int i = 0; i < 5000; i++)
{
hm_insert(map, i, (double)i / 1000.0);
}
// Iterate over the HashMap without the FOR_EACH macro
for (hashmap_iter iter = map->it_start(map); !hm_iter_end(&iter); hm_iter_next(&iter))
{
printf("MAP[%4d] = %.3lf\n", hm_iter_key(&iter), hm_iter_value(&iter));
}
// Iterate over the HashMap using FOR_EACH macro
FOR_EACH(hm, hashmap, map, {
// Inside, the variable 'iter' will be available and from it you can access
// the key, value or index.
printf("MAP[%4d] = %.3lf\n", hm_iter_key(&iter), hm_iter_value(&iter));
})
hm_free(map);
return 0;
}
+1 -1
View File
@@ -8,7 +8,7 @@
*
* Iterator Example
*/
#include "hashmap.h"
#include "cmc/hashmap.h"
#include <stdio.h>
#include <inttypes.h>
+1 -1
View File
@@ -8,7 +8,7 @@
*
* Iterator Example
*/
#include "hashset.h"
#include "cmc/hashset.h"
#include <stdio.h>
#include <inttypes.h>
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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)
{
+1 -1
View File
@@ -8,7 +8,7 @@
*
* Iterator Example
*/
#include "heap.h"
#include "cmc/heap.h"
#include <stdio.h>
#include <inttypes.h>
+1 -2
View File
@@ -7,9 +7,8 @@
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#include "deque.h"
#include "cmc/deque.h"
#include <stdio.h>
#include <stdlib.h>
DEQUE_GENERATE(d, deque, static, int)
+4 -5
View File
@@ -7,9 +7,8 @@
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#include "hashmap.h"
#include "cmc/hashmap.h"
#include <stdio.h>
#include <stdlib.h>
HASHMAP_GENERATE(hm, hmap, static, int, double)
@@ -27,7 +26,7 @@ size_t inthash(int t)
int intcmp(int a, int b)
{
return a - b;
return (a > b) - (a < b);
}
int main(int argc, char const *argv[])
@@ -61,14 +60,14 @@ int main(int argc, char const *argv[])
for (hm_iter_to_start(&iter); !hm_iter_end(&iter); hm_iter_next(&iter))
{
printf("M[%2d] = { %2d : %2.2lf }\n", hm_iter_index(&iter), hm_iter_key(&iter), hm_iter_value(&iter));
printf("HM[%2d] = { %2d : %2.2lf }\n", hm_iter_index(&iter), hm_iter_key(&iter), hm_iter_value(&iter));
}
printf("\n");
for (hm_iter_to_end(&iter); !hm_iter_start(&iter); hm_iter_prev(&iter))
{
printf("M[%2d] = { %2d : %2.2lf }\n", hm_iter_index(&iter), hm_iter_key(&iter), hm_iter_value(&iter));
printf("HM[%2d] = { %2d : %2.2lf }\n", hm_iter_index(&iter), hm_iter_key(&iter), hm_iter_value(&iter));
}
hm_free(hm);
+5 -6
View File
@@ -7,9 +7,8 @@
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#include "hashset.h"
#include "cmc/hashset.h"
#include <stdio.h>
#include <stdlib.h>
HASHSET_GENERATE(hs, hset, static, int)
@@ -27,12 +26,12 @@ size_t inthash(int t)
int intcmp(int a, int b)
{
return a - b;
return (a > b) - (a < b);
}
int main(int argc, char const *argv[])
{
// Initialize hash set and add some elements
// Initialize hashset and add some elements
hset *hs = hs_new(10, 0.9, intcmp, inthash);
for (int i = 0; i < 10; i++)
hs_insert(hs, i);
@@ -60,14 +59,14 @@ int main(int argc, char const *argv[])
for (hs_iter_to_start(&iter); !hs_iter_end(&iter); hs_iter_next(&iter))
{
printf("S[%2d] = %2d\n", hs_iter_index(&iter), hs_iter_value(&iter));
printf("HS[%2d] = %2d\n", hs_iter_index(&iter), hs_iter_value(&iter));
}
printf("\n");
for (hs_iter_to_end(&iter); !hs_iter_start(&iter); hs_iter_prev(&iter))
{
printf("S[%2d] = %2d\n", hs_iter_index(&iter), hs_iter_value(&iter));
printf("HS[%2d] = %2d\n", hs_iter_index(&iter), hs_iter_value(&iter));
}
hs_free(hs);
+2 -3
View File
@@ -7,13 +7,12 @@
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#include "heap.h"
#include "cmc/heap.h"
#include <stdio.h>
#include <stdlib.h>
int intcmp(int a, int b)
{
return a - b;
return (a > b) - (a < b);
}
HEAP_GENERATE(h, heap, static, int)
+6 -7
View File
@@ -7,22 +7,21 @@
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#include "linkedlist.h"
#include "cmc/linkedlist.h"
#include <stdio.h>
#include <stdlib.h>
LINKEDLIST_GENERATE(ll, linkedlist, static, int)
int main(int argc, char const *argv[])
{
// Initialize list and add some elements
linkedlist *l = ll_new();
// Initialize linkedlist and add some elements
linkedlist *ll = ll_new();
for (int i = 0; i < 10; i++)
ll_push_back(l, i);
ll_push_back(ll, i);
// Initialize iterator
linkedlist_iter iter;
ll_iter_init(&iter, l);
ll_iter_init(&iter, ll);
// Make the iterator go back and forward
for (int j = 0; j < 4; j++)
@@ -53,7 +52,7 @@ int main(int argc, char const *argv[])
printf("LL[%2d] = %2d\n", ll_iter_index(&iter), ll_iter_value(&iter));
}
ll_free(l);
ll_free(ll);
return 0;
}
+1 -2
View File
@@ -7,9 +7,8 @@
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#include "list.h"
#include "cmc/list.h"
#include <stdio.h>
#include <stdlib.h>
LIST_GENERATE(l, list, static, int)
+15 -15
View File
@@ -7,17 +7,13 @@
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#include "cmc/queue.h"
#include <stdio.h>
#include <stdlib.h>
#include "queue.h"
QUEUE_GENERATE(q, queue, static, int)
int main(int argc, char const *argv[])
{
size_t i;
int r;
// Initialize queue and add some elements
queue *q = q_new(10);
for (int i = 0; i < 10; i++)
@@ -30,26 +26,30 @@ int main(int argc, char const *argv[])
// Make the iterator go back and forward
for (int j = 0; j < 4; j++)
{
while (q_iter_next(&iter, &r, &i))
printf("C[%2d] = %2d\n", i, r);
while (!q_iter_end(&iter))
{
printf("C[%2d] = %2d\n", q_iter_index(&iter), q_iter_value(&iter));
q_iter_next(&iter);
}
printf("\n");
while (q_iter_prev(&iter, &r, &i))
printf("C[%2d] = %2d\n", i, r);
while (!q_iter_start(&iter))
{
printf("C[%2d] = %2d\n", q_iter_index(&iter), q_iter_value(&iter));
q_iter_prev(&iter);
}
printf("\n\n");
}
for (q_iter_tostart(&iter); !q_iter_end(&iter); /**/)
for (q_iter_to_start(&iter); !q_iter_end(&iter); q_iter_next(&iter))
{
q_iter_next(&iter, &r, &i);
printf("Q[%2d] = %2d\n", i, r);
printf("Q[%2d] = %2d\n", q_iter_index(&iter), q_iter_value(&iter));
}
printf("\n");
for (q_iter_toend(&iter); !q_iter_start(&iter); /**/)
for (q_iter_to_end(&iter); !q_iter_start(&iter); q_iter_prev(&iter))
{
q_iter_prev(&iter, &r, &i);
printf("Q[%2d] = %2d\n", i, r);
printf("Q[%2d] = %2d\n", q_iter_index(&iter), q_iter_value(&iter));
}
q_free(q);
+15 -15
View File
@@ -7,17 +7,13 @@
* 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)
int main(int argc, char const *argv[])
{
size_t i;
int r;
// Initialize stack and add some elements
stack *s = s_new(10);
for (int i = 0; i < 10; i++)
@@ -30,26 +26,30 @@ int main(int argc, char const *argv[])
// Make the iterator go back and forward
for (int j = 0; j < 4; j++)
{
while (s_iter_next(&iter, &r, &i))
printf("C[%2d] = %2d\n", i, r);
while (!s_iter_end(&iter))
{
printf("C[%2d] = %2d\n", s_iter_index(&iter), s_iter_value(&iter));
s_iter_next(&iter);
}
printf("\n");
while (s_iter_prev(&iter, &r, &i))
printf("C[%2d] = %2d\n", i, r);
while (!s_iter_start(&iter))
{
printf("C[%2d] = %2d\n", s_iter_index(&iter), s_iter_value(&iter));
s_iter_prev(&iter);
}
printf("\n\n");
}
for (s_iter_tostart(&iter); !s_iter_end(&iter); /**/)
for (s_iter_to_start(&iter); !s_iter_end(&iter); s_iter_next(&iter))
{
s_iter_next(&iter, &r, &i);
printf("S[%2d] = %2d\n", i, r);
printf("S[%2d] = %2d\n", s_iter_index(&iter), s_iter_value(&iter));
}
printf("\n");
for (s_iter_toend(&iter); !s_iter_start(&iter); /**/)
for (s_iter_to_end(&iter); !s_iter_start(&iter); s_iter_prev(&iter))
{
s_iter_prev(&iter, &r, &i);
printf("S[%2d] = %2d\n", i, r);
printf("S[%2d] = %2d\n", s_iter_index(&iter), s_iter_value(&iter));
}
s_free(s);
+21 -21
View File
@@ -7,58 +7,58 @@
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#include "cmc/treemap.h"
#include <stdio.h>
#include <stdlib.h>
#include "treemap.h"
int intcmp(int a, int b)
{
return a - b;
return (a > b) - (a < b);
}
TREEMAP_GENERATE(tm, tmap, static, int, double)
int main(int argc, char const *argv[])
{
size_t i;
int k;
double v, varr[10] = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9};
double varr[10] = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9};
// Initialize treemap and add some element
tmap *tm = tm_new(intcmp);
tmap *hm = tm_new(intcmp);
for (int i = 0; i < 10; i++)
tm_insert(tm, i, varr[i]);
tm_insert(hm, i, varr[i]);
// Initialize iterator
tmap_iter iter;
tm_iter_init(&iter, tm);
tm_iter_init(&iter, hm);
// Make the iterator go back and forward
for (int j = 0; j < 4; j++)
{
while (tm_iter_next(&iter, &k, &v, &i))
printf("S[%2d] = { %2d : %2.2lf }\n", i, k, v);
while (!tm_iter_end(&iter))
{
printf("C[%2d] = { %2d : %2.2lf }\n", tm_iter_index(&iter), tm_iter_key(&iter), tm_iter_value(&iter));
tm_iter_next(&iter);
}
printf("\n");
while (tm_iter_prev(&iter, &k, &v, &i))
printf("S[%2d] = { %2d : %2.2lf }\n", i, k, v);
while (!tm_iter_start(&iter))
{
printf("C[%2d] = { %2d : %2.2lf }\n", tm_iter_index(&iter), tm_iter_key(&iter), tm_iter_value(&iter));
tm_iter_prev(&iter);
}
printf("\n\n");
}
for (tm_iter_tostart(&iter); !tm_iter_end(&iter); /**/)
for (tm_iter_to_start(&iter); !tm_iter_end(&iter); tm_iter_next(&iter))
{
tm_iter_next(&iter, &k, &v, &i);
printf("M[%2d] = { %2d : %2.2lf }\n", i, k, v);
printf("TM[%2d] = { %2d : %2.2lf }\n", tm_iter_index(&iter), tm_iter_key(&iter), tm_iter_value(&iter));
}
printf("\n");
for (tm_iter_toend(&iter); !tm_iter_start(&iter); /**/)
for (tm_iter_to_end(&iter); !tm_iter_start(&iter); tm_iter_prev(&iter))
{
tm_iter_prev(&iter, &k, &v, &i);
printf("M[%2d] = { %2d : %2.2lf }\n", i, k, v);
printf("TM[%2d] = { %2d : %2.2lf }\n", tm_iter_index(&iter), tm_iter_key(&iter), tm_iter_value(&iter));
}
tm_free(tm);
tm_free(hm);
return 0;
}
+16 -16
View File
@@ -7,22 +7,18 @@
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#include "cmc/treeset.h"
#include <stdio.h>
#include <stdlib.h>
#include "treeset.h"
int intcmp(int a, int b)
{
return a - b;
return (a > b) - (a < b);
}
TREESET_GENERATE(ts, tset, static, int)
int main(int argc, char const *argv[])
{
size_t i;
int r;
// Initialize treeset and add some elements
tset *ts = ts_new(intcmp);
for (int i = 0; i < 10; i++)
@@ -35,26 +31,30 @@ int main(int argc, char const *argv[])
// Make the iterator go back and forward
for (int j = 0; j < 4; j++)
{
while (ts_iter_next(&iter, &r, &i))
printf("C[%2d] = %2d\n", i, r);
while (!ts_iter_end(&iter))
{
printf("C[%2d] = %2d\n", ts_iter_index(&iter), ts_iter_value(&iter));
ts_iter_next(&iter);
}
printf("\n");
while (ts_iter_prev(&iter, &r, &i))
printf("C[%2d] = %2d\n", i, r);
while (!ts_iter_start(&iter))
{
printf("C[%2d] = %2d\n", ts_iter_index(&iter), ts_iter_value(&iter));
ts_iter_prev(&iter);
}
printf("\n\n");
}
for (ts_iter_tostart(&iter); !ts_iter_end(&iter); /**/)
for (ts_iter_to_start(&iter); !ts_iter_end(&iter); ts_iter_next(&iter))
{
ts_iter_next(&iter, &r, &i);
printf("S[%2d] = %2d\n", i, r);
printf("TS[%2d] = %2d\n", ts_iter_index(&iter), ts_iter_value(&iter));
}
printf("\n");
for (ts_iter_toend(&iter); !ts_iter_start(&iter); /**/)
for (ts_iter_to_end(&iter); !ts_iter_start(&iter); ts_iter_prev(&iter))
{
ts_iter_prev(&iter, &r, &i);
printf("S[%2d] = %2d\n", i, r);
printf("TS[%2d] = %2d\n", ts_iter_index(&iter), ts_iter_value(&iter));
}
ts_free(ts);
+1 -1
View File
@@ -8,7 +8,7 @@
*
* Iterator Example
*/
#include "linkedlist.h"
#include "cmc/linkedlist.h"
#include <stdio.h>
#include <inttypes.h>
+1 -1
View File
@@ -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>
+1 -1
View File
@@ -8,7 +8,7 @@
*
* Iterator Example
*/
#include "list.h"
#include "cmc/list.h"
#include <stdio.h>
#include <inttypes.h>
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -7,7 +7,7 @@
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#include "list.h"
#include "cmc/list.h"
#include <stdio.h>
#include <string.h>
+2 -2
View File
@@ -1,5 +1,5 @@
# Other examples
* book_store - A book store where its books are loaded onto a list from a csv file. The newly added ones go to a queue of featured books where old ones are removed to give place to new ones. You can find a book by looking up its ISBN using a treemap or traversing the treemap and find all ISBNs of a corresponding title.
* separate_header_source - Example of how to used `PUBLIC` and `PRIVATE` parameters.
* for_each.c - Using the `FOR_EACH`.
* separate_header_source - Example of how to compile the header and source separately.
* for_each.c - Using the `FOR_EACH` macro.
+23 -13
View File
@@ -9,11 +9,11 @@
#include "book.c"
#include "random.c"
COLLECTION_GENERATE(LIST, PUBLIC, l, list, , , book *)
COLLECTION_GENERATE(LIST, PUBLIC, il, intlist, , , int)
COLLECTION_GENERATE(QUEUE, PUBLIC, q, queue, , , book *)
COLLECTION_GENERATE(TREEMAP, PUBLIC, map, map, , int, char *)
COLLECTION_GENERATE(TREESET, PUBLIC, set, set, , , char *)
COLLECTION_GENERATE(LIST, l, list, , , book *)
COLLECTION_GENERATE(LIST, il, intlist, , , int)
COLLECTION_GENERATE(QUEUE, q, queue, , , book *)
COLLECTION_GENERATE(TREEMAP, map, map, , int, char *)
COLLECTION_GENERATE(TREESET, set, set, , , char *)
list *load(void);
void shuffle(list *l);
@@ -48,7 +48,9 @@ int main(int argc, char const *argv[])
set *counter = set_new(chrcmp);
// Add everything to its place.
FOR_EACH(l, list, book *, books, {
FOR_EACH(l, list, books, {
book *value = l_iter_value(&iter);
// Keep the last added elements
if (q_count(shelf) > 7)
{
@@ -64,7 +66,8 @@ int main(int argc, char const *argv[])
printf("Library Size: %d\n", map_count(library));
printf("Unique book titles: %d\n\n", set_count(counter));
printf("Showcase Books:\n");
FOR_EACH(q, queue, book *, shelf, {
FOR_EACH(q, queue, shelf, {
book *value = q_iter_value(&iter);
printf("[ %d : %-45s ]\n", value->isbn, value->name);
})
printf("\n");
@@ -113,13 +116,16 @@ int main(int argc, char const *argv[])
intlist *search_list = il_new(32);
FOR_EACH_MAP(map, map, int, char *, library, {
FOR_EACH(map, map, library, {
int key = map_iter_key(&iter);
char *value = map_iter_value(&iter);
if (chrcmp(buffer, value) == 0)
il_push_back(search_list, key);
})
FOR_EACH(il, intlist, int, search_list, {
printf("[ %d ]\n", value);
FOR_EACH(il, intlist, search_list, {
printf("[ %d ]\n", il_iter_value(&iter));
})
il_free(search_list);
@@ -127,9 +133,13 @@ int main(int argc, char const *argv[])
}
// Free all memory used by struct book
FOR_EACH(l, list, book *, books, {
free(value->name);
free(value);
FOR_EACH(l, list, books, {
book *b = l_iter_value(&iter);
if (b)
free(b->name);
free(b);
})
l_free(books);
+26 -14
View File
@@ -1,19 +1,19 @@
#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, PUBLIC, l, list, static, , int)
COLLECTION_GENERATE(LINKEDLIST, PUBLIC, ll, llist, static, , int)
COLLECTION_GENERATE(STACK, PUBLIC, s, stack, static, , int)
COLLECTION_GENERATE(QUEUE, PUBLIC, q, queue, static, , int)
COLLECTION_GENERATE(DEQUE, PUBLIC, d, deque, static, , int)
COLLECTION_GENERATE(TREESET, PUBLIC, ts, tset, static, , int)
COLLECTION_GENERATE(LIST, l, list, static, , int)
COLLECTION_GENERATE(LINKEDLIST, ll, llist, static, , int)
COLLECTION_GENERATE(STACK, s, stack, static, , int)
COLLECTION_GENERATE(QUEUE, q, queue, static, , int)
COLLECTION_GENERATE(DEQUE, d, deque, static, , int)
COLLECTION_GENERATE(TREESET, ts, tset, static, , int)
int intcmp(int a, int b)
{
return a - b;
return (a > b) - (a < b);
}
int main(int argc, char const *argv[])
@@ -58,7 +58,9 @@ int main(int argc, char const *argv[])
// - value : the elements that changes with each iteration
// - index : iteration index (first iteration is 0 and last is count - 1)
// - iter : iterator struct
FOR_EACH(l, list, int, l, {
FOR_EACH(l, list, l, {
int value = l_iter_value(&iter);
size_t index = l_iter_index(&iter);
if (index == 0)
printf("[ %d, ", value);
else if (index == iter.target->count - 1)
@@ -67,7 +69,9 @@ int main(int argc, char const *argv[])
printf("%d, ", value);
})
FOR_EACH(s, stack, int, s, {
FOR_EACH(s, stack, s, {
int value = s_iter_value(&iter);
size_t index = s_iter_index(&iter);
if (index == 0)
printf("[ %d, ", value);
else if (index == iter.target->count - 1)
@@ -76,7 +80,9 @@ int main(int argc, char const *argv[])
printf("%d, ", value);
})
FOR_EACH(q, queue, int, q, {
FOR_EACH(q, queue, q, {
int value = q_iter_value(&iter);
size_t index = q_iter_index(&iter);
if (index == 0)
printf("[ %d, ", value);
else if (index == iter.target->count - 1)
@@ -85,7 +91,9 @@ int main(int argc, char const *argv[])
printf("%d, ", value);
})
FOR_EACH(d, deque, int, d, {
FOR_EACH(d, deque, d, {
int value = d_iter_value(&iter);
size_t index = d_iter_index(&iter);
if (index == 0)
printf("[ %d, ", value);
else if (index == iter.target->count - 1)
@@ -94,7 +102,9 @@ int main(int argc, char const *argv[])
printf("%d, ", value);
})
FOR_EACH(ll, llist, int, ll, {
FOR_EACH(ll, llist, ll, {
int value = ll_iter_value(&iter);
size_t index = ll_iter_index(&iter);
if (index == 0)
printf("[ %d, ", value);
else if (index == iter.target->count - 1)
@@ -103,7 +113,9 @@ int main(int argc, char const *argv[])
printf("%d, ", value);
})
FOR_EACH(ts, tset, int, ts, {
FOR_EACH(ts, tset, ts, {
int value = ts_iter_value(&iter);
size_t index = ts_iter_index(&iter);
if (index == 0)
printf("[ %d, ", value);
else if (index == iter.target->count - 1)
@@ -1,6 +1,6 @@
#include "containers.h"
COLLECTION_GENERATE_SOURCE(LIST, PUBLIC, il, int_list, , , int)
COLLECTION_GENERATE_SOURCE(STACK, PRIVATE, cs, char_stack, , , char)
COLLECTION_GENERATE_SOURCE(QUEUE, PUBLIC, queue, index_queue, , , size_t)
COLLECTION_GENERATE_SOURCE(DEQUE, PUBLIC, dq, deque, , , int)
COLLECTION_GENERATE_SOURCE(LIST, il, int_list, , , int)
COLLECTION_GENERATE_SOURCE(STACK, cs, char_stack, , , char)
COLLECTION_GENERATE_SOURCE(QUEUE, queue, index_queue, , , size_t)
COLLECTION_GENERATE_SOURCE(DEQUE, dq, deque, , , int)
@@ -3,7 +3,7 @@
#include <stdbool.h>
#include "macro_collections.h"
COLLECTION_GENERATE_HEADER(LIST, PUBLIC, il, int_list, , , int)
COLLECTION_GENERATE_HEADER(STACK, PRIVATE, cs, char_stack, , , char)
COLLECTION_GENERATE_HEADER(QUEUE, PUBLIC, queue, index_queue, , , size_t)
COLLECTION_GENERATE_HEADER(DEQUE, PUBLIC, dq, deque, , , int)
COLLECTION_GENERATE_HEADER(LIST, il, int_list, , , int)
COLLECTION_GENERATE_HEADER(STACK, cs, char_stack, , , char)
COLLECTION_GENERATE_HEADER(QUEUE, queue, index_queue, , , size_t)
COLLECTION_GENERATE_HEADER(DEQUE, dq, deque, , , int)
@@ -184,9 +184,8 @@ int main(void)
il_push_back(integers, i);
int sum = 0;
FOR_EACH(il, int_list, int, integers, {
printf("%d, ", value);
sum += value;
FOR_EACH(il, int_list, integers, {
sum += il_iter_value(&iter);
})
printf("\n\nSUM: %d\n", sum);
@@ -255,8 +254,8 @@ int main(void)
int sum3 = 0;
FOR_EACH(dq, deque, int, d, {
sum3 += value;
FOR_EACH(dq, deque, d, {
sum3 += dq_iter_value(&iter);
})
printf("Deque sum: %d\n", sum3);
+1 -1
View File
@@ -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>
+1 -1
View File
@@ -8,7 +8,7 @@
*
* Iterator Example
*/
#include "queue.h"
#include "cmc/queue.h"
#include <stdio.h>
#include <inttypes.h>
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -8,7 +8,7 @@
*
* Iterator Example
*/
#include "stack.h"
#include "cmc/stack.h"
#include <stdio.h>
#include <inttypes.h>
+1 -1
View File
@@ -8,7 +8,7 @@
*
* Iterator Example
*/
#include "treemap.h"
#include "cmc/treemap.h"
#include <stdio.h>
#include <inttypes.h>
+1 -1
View File
@@ -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>
+1 -1
View File
@@ -8,7 +8,7 @@
*
* Iterator Example
*/
#include "treeset.h"
#include "cmc/treeset.h"
#include <stdio.h>
#include <inttypes.h>
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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)
+30 -30
View File
@@ -20,24 +20,14 @@
#include <string.h>
#define DEQUE_GENERATE(PFX, SNAME, FMOD, V) \
DEQUE_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \
DEQUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
DEQUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* PRIVATE *******************************************************************/
#define DEQUE_GENERATE_HEADER_PRIVATE(PFX, SNAME, FMOD, K, V) \
#define DEQUE_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \
DEQUE_GENERATE_HEADER(PFX, SNAME, FMOD, V)
#define DEQUE_GENERATE_SOURCE_PRIVATE(PFX, SNAME, FMOD, K, V) \
DEQUE_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \
#define DEQUE_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \
DEQUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* PUBLIC ********************************************************************/
#define DEQUE_GENERATE_HEADER_PUBLIC(PFX, SNAME, FMOD, K, V) \
DEQUE_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \
DEQUE_GENERATE_HEADER(PFX, SNAME, FMOD, V)
#define DEQUE_GENERATE_SOURCE_PUBLIC(PFX, SNAME, FMOD, K, V) \
DEQUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* STRUCT ********************************************************************/
#define DEQUE_GENERATE_STRUCT(PFX, SNAME, FMOD, V)
/* HEADER ********************************************************************/
#define DEQUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
@@ -90,7 +80,7 @@
\
/* Collection Functions */ \
/* Collection Allocation and Deallocation */ \
FMOD SNAME *PFX##_new(size_t size); \
FMOD SNAME *PFX##_new(size_t capacity); \
FMOD void PFX##_clear(SNAME *_deque_); \
FMOD void PFX##_free(SNAME *_deque_); \
/* Collection Input and Output */ \
@@ -132,17 +122,27 @@
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 */ \
FMOD bool PFX##_impl_grow(SNAME *_deque_); \
SNAME##_iter PFX##_impl_it_start(SNAME *_deque_); \
SNAME##_iter PFX##_impl_it_end(SNAME *_deque_); \
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 size) \
FMOD SNAME *PFX##_new(size_t capacity) \
{ \
if (size < 1) \
if (capacity < 1) \
return NULL; \
\
SNAME *_deque_ = malloc(sizeof(SNAME)); \
@@ -150,7 +150,7 @@
if (!_deque_) \
return NULL; \
\
_deque_->buffer = malloc(sizeof(V) * size); \
_deque_->buffer = malloc(sizeof(V) * capacity); \
\
if (!_deque_->buffer) \
{ \
@@ -158,9 +158,9 @@
return NULL; \
} \
\
memset(_deque_->buffer, 0, sizeof(V) * size); \
memset(_deque_->buffer, 0, sizeof(V) * capacity); \
\
_deque_->capacity = size; \
_deque_->capacity = capacity; \
_deque_->count = 0; \
_deque_->front = 0; \
_deque_->back = 0; \
@@ -225,7 +225,7 @@
if (PFX##_empty(_deque_)) \
return false; \
\
_deque_->buffer[_deque_->front] = 0; \
_deque_->buffer[_deque_->front] = PFX##_impl_default_value(); \
\
_deque_->front = (_deque_->front == _deque_->capacity - 1) ? 0 : _deque_->front + 1; \
\
@@ -241,7 +241,7 @@
\
_deque_->back = (_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1; \
\
_deque_->buffer[_deque_->back] = 0; \
_deque_->buffer[_deque_->back] = PFX##_impl_default_value(); \
\
_deque_->count--; \
\
@@ -283,7 +283,7 @@
FMOD V PFX##_front(SNAME *_deque_) \
{ \
if (PFX##_empty(_deque_)) \
return 0; \
PFX##_impl_default_value(); \
\
return _deque_->buffer[_deque_->front]; \
} \
@@ -291,7 +291,7 @@
FMOD V PFX##_back(SNAME *_deque_) \
{ \
if (PFX##_empty(_deque_)) \
return 0; \
PFX##_impl_default_value(); \
\
return _deque_->buffer[(_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1]; \
} \
@@ -422,7 +422,7 @@
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return 0; \
PFX##_impl_default_value(); \
\
return iter->target->buffer[iter->cursor]; \
} \
@@ -440,7 +440,7 @@
return iter->index; \
} \
\
FMOD bool PFX##_impl_grow(SNAME *_deque_) \
static bool PFX##_impl_grow(SNAME *_deque_) \
{ \
\
size_t new_capacity = _deque_->capacity * 2; \
@@ -465,7 +465,7 @@
return true; \
} \
\
SNAME##_iter PFX##_impl_it_start(SNAME *_deque_) \
static SNAME##_iter PFX##_impl_it_start(SNAME *_deque_) \
{ \
SNAME##_iter iter; \
\
@@ -474,7 +474,7 @@
return iter; \
} \
\
SNAME##_iter PFX##_impl_it_end(SNAME *_deque_) \
static SNAME##_iter PFX##_impl_it_end(SNAME *_deque_) \
{ \
SNAME##_iter iter; \
\
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+121 -121
View File
@@ -26,126 +26,126 @@ typedef enum HeapOrder
} HeapOrder;
#define HEAP_GENERATE(PFX, SNAME, FMOD, V) \
HEAP_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \
HEAP_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
HEAP_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* PRIVATE *******************************************************************/
#define HEAP_GENERATE_HEADER_PRIVATE(PFX, SNAME, FMOD, K, V) \
#define HEAP_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \
HEAP_GENERATE_HEADER(PFX, SNAME, FMOD, V)
#define HEAP_GENERATE_SOURCE_PRIVATE(PFX, SNAME, FMOD, K, V) \
HEAP_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \
#define HEAP_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \
HEAP_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* PUBLIC ********************************************************************/
#define HEAP_GENERATE_HEADER_PUBLIC(PFX, SNAME, FMOD, K, V) \
HEAP_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \
HEAP_GENERATE_HEADER(PFX, SNAME, FMOD, V)
#define HEAP_GENERATE_SOURCE_PUBLIC(PFX, SNAME, FMOD, K, V) \
HEAP_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* STRUCT ********************************************************************/
#define HEAP_GENERATE_STRUCT(PFX, SNAME, FMOD, V)
/* HEADER ********************************************************************/
#define HEAP_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
\
/* Heap Structure */ \
typedef struct SNAME##_s \
{ \
/* Dynamic array of elements */ \
V *buffer; \
\
/* Current array capacity */ \
size_t capacity; \
\
/* Current amount of elements in the heap */ \
size_t count; \
\
/* Heap order (MaxHeap or MinHeap) */ \
enum HeapOrder HO; \
\
/* Element comparison function */ \
int (*cmp)(V, V); \
\
/* Function that returns an iterator to the start of the heap */ \
struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
\
/* Function that returns an iterator to the end of the heap */ \
struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
\
} SNAME, *SNAME##_ptr; \
\
/* Heap Iterator */ \
typedef struct SNAME##_iter_s \
{ \
/* Target heap */ \
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(size_t size, HeapOrder HO, int (*compare)(V, V)); \
FMOD void PFX##_clear(SNAME *_heap_); \
FMOD void PFX##_free(SNAME *_heap_); \
/* Collection Input and Output */ \
FMOD bool PFX##_insert(SNAME *_heap_, V element); \
FMOD bool PFX##_remove(SNAME *_heap_, V *result); \
/* Conditional Input and Output */ \
FMOD bool PFX##_insert_if(SNAME *_heap_, V element, bool condition); \
FMOD bool PFX##_remove_if(SNAME *_heap_, V *result, bool condition); \
/* Element Access */ \
FMOD V PFX##_peek(SNAME *_heap_); \
FMOD V *PFX##_peek_ref(SNAME *_heap_); \
/* Collection State */ \
FMOD bool PFX##_contains(SNAME *_heap_, V element); \
FMOD bool PFX##_empty(SNAME *_heap_); \
FMOD bool PFX##_full(SNAME *_heap_); \
FMOD size_t PFX##_count(SNAME *_heap_); \
FMOD size_t PFX##_capacity(SNAME *_heap_); \
\
/* 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 size_t PFX##_iter_index(SNAME##_iter *iter); \
\
#define HEAP_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
\
/* Heap Structure */ \
typedef struct SNAME##_s \
{ \
/* Dynamic array of elements */ \
V *buffer; \
\
/* Current array capacity */ \
size_t capacity; \
\
/* Current amount of elements in the heap */ \
size_t count; \
\
/* Heap order (MaxHeap or MinHeap) */ \
enum HeapOrder HO; \
\
/* Element comparison function */ \
int (*cmp)(V, V); \
\
/* Function that returns an iterator to the start of the heap */ \
struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
\
/* Function that returns an iterator to the end of the heap */ \
struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
\
} SNAME, *SNAME##_ptr; \
\
/* Heap Iterator */ \
typedef struct SNAME##_iter_s \
{ \
/* Target heap */ \
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(size_t capacity, HeapOrder HO, int (*compare)(V, V)); \
FMOD void PFX##_clear(SNAME *_heap_); \
FMOD void PFX##_free(SNAME *_heap_); \
/* Collection Input and Output */ \
FMOD bool PFX##_insert(SNAME *_heap_, V element); \
FMOD bool PFX##_remove(SNAME *_heap_, V *result); \
/* Conditional Input and Output */ \
FMOD bool PFX##_insert_if(SNAME *_heap_, V element, bool condition); \
FMOD bool PFX##_remove_if(SNAME *_heap_, V *result, bool condition); \
/* Element Access */ \
FMOD V PFX##_peek(SNAME *_heap_); \
FMOD V *PFX##_peek_ref(SNAME *_heap_); \
/* Collection State */ \
FMOD bool PFX##_contains(SNAME *_heap_, V element); \
FMOD bool PFX##_empty(SNAME *_heap_); \
FMOD bool PFX##_full(SNAME *_heap_); \
FMOD size_t PFX##_count(SNAME *_heap_); \
FMOD size_t PFX##_capacity(SNAME *_heap_); \
\
/* 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 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 HEAP_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \
\
/* Implementation Detail Functions */ \
FMOD bool PFX##_impl_grow(SNAME *_heap_); \
FMOD size_t PFX##_impl_p(size_t index); \
FMOD size_t PFX##_impl_l(size_t index); \
FMOD size_t PFX##_impl_r(size_t index); \
FMOD bool PFX##_impl_float_up(SNAME *_heap_, size_t index); \
FMOD bool PFX##_impl_float_down(SNAME *_heap_, size_t index); \
SNAME##_iter PFX##_impl_it_start(SNAME *_heap_); \
SNAME##_iter PFX##_impl_it_end(SNAME *_heap_); \
static bool PFX##_impl_grow(SNAME *_heap_); \
static size_t PFX##_impl_p(size_t index); \
static size_t PFX##_impl_l(size_t index); \
static size_t PFX##_impl_r(size_t index); \
static bool PFX##_impl_float_up(SNAME *_heap_, size_t index); \
static bool PFX##_impl_float_down(SNAME *_heap_, size_t index); \
static SNAME##_iter PFX##_impl_it_start(SNAME *_heap_); \
static SNAME##_iter PFX##_impl_it_end(SNAME *_heap_); \
\
FMOD SNAME *PFX##_new(size_t size, HeapOrder HO, int (*compare)(V, V)) \
FMOD SNAME *PFX##_new(size_t capacity, HeapOrder HO, int (*compare)(V, V)) \
{ \
if (size < 1) \
if (capacity < 1) \
return NULL; \
\
if (HO != MinHeap && HO != MaxHeap) \
@@ -156,7 +156,7 @@ typedef enum HeapOrder
if (!_heap_) \
return NULL; \
\
_heap_->buffer = malloc(sizeof(V) * size); \
_heap_->buffer = malloc(sizeof(V) * capacity); \
\
if (!_heap_->buffer) \
{ \
@@ -164,9 +164,9 @@ typedef enum HeapOrder
return NULL; \
} \
\
memset(_heap_->buffer, 0, sizeof(V) * size); \
memset(_heap_->buffer, 0, sizeof(V) * capacity); \
\
_heap_->capacity = size; \
_heap_->capacity = capacity; \
_heap_->count = 0; \
_heap_->HO = HO; \
_heap_->cmp = compare; \
@@ -219,7 +219,7 @@ typedef enum HeapOrder
\
*result = _heap_->buffer[0]; \
_heap_->buffer[0] = _heap_->buffer[_heap_->count - 1]; \
_heap_->buffer[_heap_->count - 1] = 0; \
_heap_->buffer[_heap_->count - 1] = PFX##_impl_default_value(); \
\
_heap_->count--; \
\
@@ -248,7 +248,7 @@ typedef enum HeapOrder
FMOD V PFX##_peek(SNAME *_heap_) \
{ \
if (PFX##_empty(_heap_)) \
return 0; \
return PFX##_impl_default_value(); \
\
return _heap_->buffer[0]; \
} \
@@ -374,7 +374,7 @@ typedef enum HeapOrder
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return 0; \
return PFX##_impl_default_value(); \
\
return iter->target->buffer[iter->cursor]; \
} \
@@ -384,7 +384,7 @@ typedef enum HeapOrder
return iter->cursor; \
} \
\
FMOD bool PFX##_impl_grow(SNAME *_heap_) \
static bool PFX##_impl_grow(SNAME *_heap_) \
{ \
size_t new_capacity = _heap_->capacity * 2; \
\
@@ -399,7 +399,7 @@ typedef enum HeapOrder
return true; \
} \
\
FMOD size_t PFX##_impl_p(size_t index) \
static size_t PFX##_impl_p(size_t index) \
{ \
if (index == 0) \
return 0; \
@@ -407,17 +407,17 @@ typedef enum HeapOrder
return (index - 1) / 2; \
} \
\
FMOD size_t PFX##_impl_l(size_t index) \
static size_t PFX##_impl_l(size_t index) \
{ \
return 2 * index + 1; \
} \
\
FMOD size_t PFX##_impl_r(size_t index) \
static size_t PFX##_impl_r(size_t index) \
{ \
return 2 * index + 2; \
} \
\
FMOD bool PFX##_impl_float_up(SNAME *_heap_, size_t index) \
static bool PFX##_impl_float_up(SNAME *_heap_, size_t index) \
{ \
size_t C = index; \
V child = _heap_->buffer[C]; \
@@ -440,7 +440,7 @@ typedef enum HeapOrder
return true; \
} \
\
FMOD bool PFX##_impl_float_down(SNAME *_heap_, size_t index) \
static bool PFX##_impl_float_down(SNAME *_heap_, size_t index) \
{ \
int mod = _heap_->HO; \
\
@@ -475,7 +475,7 @@ typedef enum HeapOrder
return true; \
} \
\
SNAME##_iter PFX##_impl_it_start(SNAME *_heap_) \
static SNAME##_iter PFX##_impl_it_start(SNAME *_heap_) \
{ \
SNAME##_iter iter; \
\
@@ -485,7 +485,7 @@ typedef enum HeapOrder
return iter; \
} \
\
SNAME##_iter PFX##_impl_it_end(SNAME *_heap_) \
static SNAME##_iter PFX##_impl_it_end(SNAME *_heap_) \
{ \
SNAME##_iter iter; \
\
+25 -27
View File
@@ -17,26 +17,17 @@
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define LINKEDLIST_GENERATE(PFX, SNAME, FMOD, V) \
LINKEDLIST_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \
LINKEDLIST_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
LINKEDLIST_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* PRIVATE *******************************************************************/
#define LINKEDLIST_GENERATE_HEADER_PRIVATE(PFX, SNAME, FMOD, K, V) \
#define LINKEDLIST_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \
LINKEDLIST_GENERATE_HEADER(PFX, SNAME, FMOD, V)
#define LINKEDLIST_GENERATE_SOURCE_PRIVATE(PFX, SNAME, FMOD, K, V) \
LINKEDLIST_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \
#define LINKEDLIST_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \
LINKEDLIST_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* PUBLIC ********************************************************************/
#define LINKEDLIST_GENERATE_HEADER_PUBLIC(PFX, SNAME, FMOD, K, V) \
LINKEDLIST_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \
LINKEDLIST_GENERATE_HEADER(PFX, SNAME, FMOD, V)
#define LINKEDLIST_GENERATE_SOURCE_PUBLIC(PFX, SNAME, FMOD, K, V) \
LINKEDLIST_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* STRUCT ********************************************************************/
#define LINKEDLIST_GENERATE_STRUCT(PFX, SNAME, FMOD, V)
/* HEADER ********************************************************************/
#define LINKEDLIST_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
@@ -59,7 +50,7 @@
/* Function that returns an iterator to the end of the list */ \
struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
\
} SNAME, *SNAME_ptr; \
} SNAME, *SNAME##_ptr; \
\
/* Doubly-linked list node */ \
typedef struct SNAME##_node_s \
@@ -158,12 +149,22 @@
FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \
FMOD SNAME##_node *PFX##_iter_node(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 LINKEDLIST_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \
\
/* Implementation Detail Functions */ \
SNAME##_iter PFX##_impl_it_start(SNAME *_list_); \
SNAME##_iter PFX##_impl_it_end(SNAME *_list_); \
static SNAME##_iter PFX##_impl_it_start(SNAME *_list_); \
static SNAME##_iter PFX##_impl_it_end(SNAME *_list_); \
\
FMOD SNAME *PFX##_new(void) \
{ \
@@ -375,23 +376,20 @@
FMOD V PFX##_front(SNAME *_list_) \
{ \
if (PFX##_empty(_list_)) \
return 0; \
PFX##_impl_default_value(); \
\
return _list_->head->data; \
} \
\
FMOD V PFX##_get(SNAME *_list_, size_t index) \
{ \
if (index >= _list_->count) \
return 0; \
\
if (PFX##_empty(_list_)) \
return 0; \
if (index >= _list_->count || PFX##_empty(_list_)) \
PFX##_impl_default_value(); \
\
SNAME##_node *scan = PFX##_get_node(_list_, index); \
\
if (scan == NULL) \
return 0; \
return PFX##_impl_default_value(); \
\
return scan->data; \
} \
@@ -415,7 +413,7 @@
FMOD V PFX##_back(SNAME *_list_) \
{ \
if (PFX##_empty(_list_)) \
return 0; \
return PFX##_impl_default_value(); \
\
return _list_->tail->data; \
} \
@@ -712,7 +710,7 @@
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return 0; \
return PFX##_impl_default_value(); \
\
return iter->cursor->data; \
} \
@@ -735,7 +733,7 @@
return iter->cursor; \
} \
\
SNAME##_iter PFX##_impl_it_start(SNAME *_list_) \
static SNAME##_iter PFX##_impl_it_start(SNAME *_list_) \
{ \
SNAME##_iter iter; \
\
@@ -745,7 +743,7 @@
return iter; \
} \
\
SNAME##_iter PFX##_impl_it_end(SNAME *_list_) \
static SNAME##_iter PFX##_impl_it_end(SNAME *_list_) \
{ \
SNAME##_iter iter; \
\
+27 -30
View File
@@ -20,24 +20,14 @@
#include <string.h>
#define LIST_GENERATE(PFX, SNAME, FMOD, V) \
LIST_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \
LIST_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
LIST_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* PRIVATE *******************************************************************/
#define LIST_GENERATE_HEADER_PRIVATE(PFX, SNAME, FMOD, K, V) \
#define LIST_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \
LIST_GENERATE_HEADER(PFX, SNAME, FMOD, V)
#define LIST_GENERATE_SOURCE_PRIVATE(PFX, SNAME, FMOD, K, V) \
LIST_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \
#define LIST_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \
LIST_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* PUBLIC ********************************************************************/
#define LIST_GENERATE_HEADER_PUBLIC(PFX, SNAME, FMOD, K, V) \
LIST_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \
LIST_GENERATE_HEADER(PFX, SNAME, FMOD, V)
#define LIST_GENERATE_SOURCE_PUBLIC(PFX, SNAME, FMOD, K, V) \
LIST_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* STRUCT ********************************************************************/
#define LIST_GENERATE_STRUCT(PFX, SNAME, FMOD, V)
/* HEADER ********************************************************************/
#define LIST_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
@@ -134,13 +124,23 @@
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 LIST_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \
\
/* Implementation Detail Functions */ \
FMOD bool PFX##_impl_grow(SNAME *_list_, size_t required); \
SNAME##_iter PFX##_impl_it_start(SNAME *_list_); \
SNAME##_iter PFX##_impl_it_end(SNAME *_list_); \
static bool PFX##_impl_grow(SNAME *_list_, size_t required); \
static SNAME##_iter PFX##_impl_it_start(SNAME *_list_); \
static SNAME##_iter PFX##_impl_it_end(SNAME *_list_); \
\
FMOD SNAME *PFX##_new(size_t capacity) \
{ \
@@ -270,7 +270,7 @@
\
memmove(_list_->buffer, _list_->buffer + 1, _list_->count * sizeof(V)); \
\
_list_->buffer[--_list_->count] = 0; \
_list_->buffer[--_list_->count] = PFX##_impl_default_value(); \
\
return true; \
} \
@@ -294,7 +294,7 @@
\
memmove(_list_->buffer + index, _list_->buffer + index + 1, (_list_->count - index) * sizeof(V)); \
\
_list_->buffer[--_list_->count] = 0; \
_list_->buffer[--_list_->count] = PFX##_impl_default_value(); \
\
return true; \
} \
@@ -304,7 +304,7 @@
if (PFX##_empty(_list_)) \
return false; \
\
_list_->buffer[--_list_->count] = 0; \
_list_->buffer[--_list_->count] = PFX##_impl_default_value(); \
\
return true; \
} \
@@ -430,18 +430,15 @@
FMOD V PFX##_front(SNAME *_list_) \
{ \
if (PFX##_empty(_list_)) \
return 0; \
return PFX##_impl_default_value(); \
\
return _list_->buffer[0]; \
} \
\
FMOD V PFX##_get(SNAME *_list_, size_t index) \
{ \
if (index >= _list_->count) \
return 0; \
\
if (PFX##_empty(_list_)) \
return 0; \
if (index >= _list_->count || PFX##_empty(_list_)) \
return PFX##_impl_default_value(); \
\
return _list_->buffer[index]; \
} \
@@ -460,7 +457,7 @@
FMOD V PFX##_back(SNAME *_list_) \
{ \
if (PFX##_empty(_list_)) \
return 0; \
return PFX##_impl_default_value(); \
\
return _list_->buffer[_list_->count - 1]; \
} \
@@ -605,7 +602,7 @@
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return 0; \
return PFX##_impl_default_value(); \
\
return iter->target->buffer[iter->cursor]; \
} \
@@ -623,7 +620,7 @@
return iter->cursor; \
} \
\
FMOD bool PFX##_impl_grow(SNAME *_list_, size_t required) \
static bool PFX##_impl_grow(SNAME *_list_, size_t required) \
{ \
size_t new_capacity = _list_->capacity * 2; \
\
@@ -641,7 +638,7 @@
return true; \
} \
\
SNAME##_iter PFX##_impl_it_start(SNAME *_list_) \
static SNAME##_iter PFX##_impl_it_start(SNAME *_list_) \
{ \
SNAME##_iter iter; \
\
@@ -651,7 +648,7 @@
return iter; \
} \
\
SNAME##_iter PFX##_impl_it_end(SNAME *_list_) \
static SNAME##_iter PFX##_impl_it_end(SNAME *_list_) \
{ \
SNAME##_iter iter; \
\
+29 -29
View File
@@ -20,24 +20,14 @@
#include <string.h>
#define QUEUE_GENERATE(PFX, SNAME, FMOD, V) \
QUEUE_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \
QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* PRIVATE *******************************************************************/
#define QUEUE_GENERATE_HEADER_PRIVATE(PFX, SNAME, FMOD, K, V) \
#define QUEUE_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \
QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V)
#define QUEUE_GENERATE_SOURCE_PRIVATE(PFX, SNAME, FMOD, K, V) \
QUEUE_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \
#define QUEUE_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \
QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* PUBLIC ********************************************************************/
#define QUEUE_GENERATE_HEADER_PUBLIC(PFX, SNAME, FMOD, K, V) \
QUEUE_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \
QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V)
#define QUEUE_GENERATE_SOURCE_PUBLIC(PFX, SNAME, FMOD, K, V) \
QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* STRUCT ********************************************************************/
#define QUEUE_GENERATE_STRUCT(PFX, SNAME, FMOD, V)
/* HEADER ********************************************************************/
#define QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
@@ -90,7 +80,7 @@
\
/* Collection Functions */ \
/* Collection Allocation and Deallocation */ \
FMOD SNAME *PFX##_new(size_t size); \
FMOD SNAME *PFX##_new(size_t capacity); \
FMOD void PFX##_clear(SNAME *_queue_); \
FMOD void PFX##_free(SNAME *_queue_); \
/* Collection Input and Output */ \
@@ -127,17 +117,27 @@
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 QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \
\
/* Implementation Detail Functions */ \
FMOD bool PFX##_grow(SNAME *_queue_); \
SNAME##_iter PFX##_impl_it_start(SNAME *_queue_); \
SNAME##_iter PFX##_impl_it_end(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_); \
\
FMOD SNAME *PFX##_new(size_t size) \
FMOD SNAME *PFX##_new(size_t capacity) \
{ \
if (size < 1) \
if (capacity < 1) \
return NULL; \
\
SNAME *_queue_ = malloc(sizeof(SNAME)); \
@@ -145,7 +145,7 @@
if (!_queue_) \
return NULL; \
\
_queue_->buffer = malloc(sizeof(V) * size); \
_queue_->buffer = malloc(sizeof(V) * capacity); \
\
if (!_queue_->buffer) \
{ \
@@ -153,9 +153,9 @@
return NULL; \
} \
\
memset(_queue_->buffer, 0, sizeof(V) * size); \
memset(_queue_->buffer, 0, sizeof(V) * capacity); \
\
_queue_->capacity = size; \
_queue_->capacity = capacity; \
_queue_->count = 0; \
_queue_->front = 0; \
_queue_->rear = 0; \
@@ -185,7 +185,7 @@
{ \
if (PFX##_full(_queue_)) \
{ \
if (!PFX##_grow(_queue_)) \
if (!PFX##_impl_grow(_queue_)) \
return false; \
} \
\
@@ -202,7 +202,7 @@
if (PFX##_empty(_queue_)) \
return false; \
\
_queue_->buffer[_queue_->front] = 0; \
_queue_->buffer[_queue_->front] = PFX##_impl_default_value(); \
\
_queue_->front = (_queue_->front == _queue_->capacity - 1) ? 0 : _queue_->front + 1; \
_queue_->count--; \
@@ -229,7 +229,7 @@
FMOD V PFX##_peek(SNAME *_queue_) \
{ \
if (PFX##_empty(_queue_)) \
return 0; \
PFX##_impl_default_value(); \
\
return _queue_->buffer[_queue_->front]; \
} \
@@ -360,7 +360,7 @@
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return 0; \
PFX##_impl_default_value(); \
\
return iter->target->buffer[iter->cursor]; \
} \
@@ -378,7 +378,7 @@
return iter->index; \
} \
\
FMOD bool PFX##_grow(SNAME *_queue_) \
static bool PFX##_impl_grow(SNAME *_queue_) \
{ \
\
size_t new_capacity = _queue_->capacity * 2; \
@@ -403,7 +403,7 @@
return true; \
} \
\
SNAME##_iter PFX##_impl_it_start(SNAME *_queue_) \
static SNAME##_iter PFX##_impl_it_start(SNAME *_queue_) \
{ \
SNAME##_iter iter; \
\
@@ -413,7 +413,7 @@
return iter; \
} \
\
SNAME##_iter PFX##_impl_it_end(SNAME *_queue_) \
static SNAME##_iter PFX##_impl_it_end(SNAME *_queue_) \
{ \
SNAME##_iter iter; \
\
+28 -28
View File
@@ -20,24 +20,14 @@
#include <string.h>
#define STACK_GENERATE(PFX, SNAME, FMOD, V) \
STACK_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \
STACK_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* PRIVATE *******************************************************************/
#define STACK_GENERATE_HEADER_PRIVATE(PFX, SNAME, FMOD, K, V) \
#define STACK_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \
STACK_GENERATE_HEADER(PFX, SNAME, FMOD, V)
#define STACK_GENERATE_SOURCE_PRIVATE(PFX, SNAME, FMOD, K, V) \
STACK_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \
#define STACK_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \
STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* PUBLIC ********************************************************************/
#define STACK_GENERATE_HEADER_PUBLIC(PFX, SNAME, FMOD, K, V) \
STACK_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \
STACK_GENERATE_HEADER(PFX, SNAME, FMOD, V)
#define STACK_GENERATE_SOURCE_PUBLIC(PFX, SNAME, FMOD, K, V) \
STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* STRUCT ********************************************************************/
#define STACK_GENERATE_STRUCT(PFX, SNAME, FMOD, V)
/* HEADER ********************************************************************/
#define STACK_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
@@ -81,7 +71,7 @@
\
/* Collection Functions */ \
/* Collection Allocation and Deallocation */ \
FMOD SNAME *PFX##_new(size_t size); \
FMOD SNAME *PFX##_new(size_t capacity); \
FMOD void PFX##_clear(SNAME *_stack_); \
FMOD void PFX##_free(SNAME *_stack_); \
/* Collection Input and Output */ \
@@ -118,17 +108,27 @@
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 STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \
\
/* Implementation Detail Functions */ \
FMOD bool PFX##_impl_grow(SNAME *_stack_); \
SNAME##_iter PFX##_impl_it_start(SNAME *_stack_); \
SNAME##_iter PFX##_impl_it_end(SNAME *_stack_); \
static bool PFX##_impl_grow(SNAME *_stack_); \
static SNAME##_iter PFX##_impl_it_start(SNAME *_stack_); \
static SNAME##_iter PFX##_impl_it_end(SNAME *_stack_); \
\
FMOD SNAME *PFX##_new(size_t size) \
FMOD SNAME *PFX##_new(size_t capacity) \
{ \
if (size < 1) \
if (capacity < 1) \
return NULL; \
\
SNAME *_stack_ = malloc(sizeof(SNAME)); \
@@ -136,7 +136,7 @@
if (!_stack_) \
return NULL; \
\
_stack_->buffer = malloc(sizeof(V) * size); \
_stack_->buffer = malloc(sizeof(V) * capacity); \
\
if (!_stack_->buffer) \
{ \
@@ -144,9 +144,9 @@
return NULL; \
} \
\
memset(_stack_->buffer, 0, sizeof(V) * size); \
memset(_stack_->buffer, 0, sizeof(V) * capacity); \
\
_stack_->capacity = size; \
_stack_->capacity = capacity; \
_stack_->count = 0; \
\
_stack_->it_start = PFX##_impl_it_start; \
@@ -186,7 +186,7 @@
if (PFX##_empty(_stack_)) \
return false; \
\
_stack_->buffer[--_stack_->count] = 0; \
_stack_->buffer[--_stack_->count] = PFX##_impl_default_value(); \
\
return true; \
} \
@@ -210,7 +210,7 @@
FMOD V PFX##_top(SNAME *_stack_) \
{ \
if (PFX##_empty(_stack_)) \
return 0; \
PFX##_impl_default_value(); \
\
return _stack_->buffer[_stack_->count - 1]; \
} \
@@ -328,7 +328,7 @@
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return 0; \
PFX##_impl_default_value(); \
\
return iter->target->buffer[iter->cursor]; \
} \
@@ -346,7 +346,7 @@
return iter->target->count - 1 - iter->cursor; \
} \
\
FMOD bool PFX##_impl_grow(SNAME *_stack_) \
static bool PFX##_impl_grow(SNAME *_stack_) \
{ \
size_t new_capacity = _stack_->capacity * 2; \
\
@@ -361,7 +361,7 @@
return true; \
} \
\
SNAME##_iter PFX##_impl_it_start(SNAME *_stack_) \
static SNAME##_iter PFX##_impl_it_start(SNAME *_stack_) \
{ \
SNAME##_iter iter; \
\
@@ -371,7 +371,7 @@
return iter; \
} \
\
SNAME##_iter PFX##_impl_it_end(SNAME *_stack_) \
static SNAME##_iter PFX##_impl_it_end(SNAME *_stack_) \
{ \
SNAME##_iter iter; \
\
+52 -32
View File
@@ -17,26 +17,17 @@
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define TREEMAP_GENERATE(PFX, SNAME, FMOD, K, V) \
TREEMAP_GENERATE_STRUCT(PFX, SNAME, FMOD, K, V) \
TREEMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \
TREEMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V)
/* PRIVATE *******************************************************************/
#define TREEMAP_GENERATE_HEADER_PRIVATE(PFX, SNAME, FMOD, K, V) \
#define TREEMAP_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \
TREEMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V)
#define TREEMAP_GENERATE_SOURCE_PRIVATE(PFX, SNAME, FMOD, K, V) \
TREEMAP_GENERATE_STRUCT(PFX, SNAME, FMOD, K, V) \
#define TREEMAP_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \
TREEMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V)
/* PUBLIC ********************************************************************/
#define TREEMAP_GENERATE_HEADER_PUBLIC(PFX, SNAME, FMOD, K, V) \
TREEMAP_GENERATE_STRUCT(PFX, SNAME, FMOD, K, V) \
TREEMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V)
#define TREEMAP_GENERATE_SOURCE_PUBLIC(PFX, SNAME, FMOD, K, V) \
TREEMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V)
/* STRUCT ********************************************************************/
#define TREEMAP_GENERATE_STRUCT(PFX, SNAME, FMOD, K, V)
/* HEADER ********************************************************************/
#define TREEMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \
@@ -151,19 +142,39 @@
FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \
FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \
\
/* Default Key */ \
static inline K PFX##_impl_default_key(void) \
{ \
K _empty_key_; \
\
memset(&_empty_key_, 0, sizeof(K)); \
\
return _empty_key_; \
} \
\
/* Default Value */ \
static inline V PFX##_impl_default_value(void) \
{ \
V _empty_value_; \
\
memset(&_empty_value_, 0, sizeof(V)); \
\
return _empty_value_; \
} \
\
/* SOURCE ********************************************************************/
#define TREEMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) \
\
/* Implementation Detail Functions */ \
FMOD SNAME##_node *PFX##_impl_new_node(K key, V value); \
FMOD SNAME##_node *PFX##_impl_get_node(SNAME *_map_, K key); \
FMOD unsigned char PFX##_impl_h(SNAME##_node *node); \
FMOD unsigned char PFX##_impl_hupdate(SNAME##_node *node); \
FMOD void PFX##_impl_rotate_right(SNAME##_node **Z); \
FMOD void PFX##_impl_rotate_left(SNAME##_node **Z); \
FMOD void PFX##_impl_rebalance(SNAME *_map_, SNAME##_node *node); \
SNAME##_iter PFX##_impl_it_start(SNAME *_map_); \
SNAME##_iter PFX##_impl_it_end(SNAME *_map_); \
static SNAME##_node *PFX##_impl_new_node(K key, V value); \
static SNAME##_node *PFX##_impl_get_node(SNAME *_map_, K key); \
static unsigned char PFX##_impl_h(SNAME##_node *node); \
static unsigned char PFX##_impl_hupdate(SNAME##_node *node); \
static void PFX##_impl_rotate_right(SNAME##_node **Z); \
static void PFX##_impl_rotate_left(SNAME##_node **Z); \
static void PFX##_impl_rebalance(SNAME *_map_, SNAME##_node *node); \
static SNAME##_iter PFX##_impl_it_start(SNAME *_map_); \
static SNAME##_iter PFX##_impl_it_end(SNAME *_map_); \
\
FMOD SNAME *PFX##_new(int (*compare)(K, K)) \
{ \
@@ -479,7 +490,7 @@
SNAME##_node *node = PFX##_impl_get_node(_map_, key); \
\
if (!node) \
return 0; \
return PFX##_impl_default_value(); \
\
return node->value; \
} \
@@ -665,16 +676,25 @@
\
FMOD K PFX##_iter_key(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
PFX##_impl_default_key(); \
\
return iter->cursor->key; \
} \
\
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
PFX##_impl_default_value(); \
\
return iter->cursor->value; \
} \
\
FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return NULL; \
\
return &(iter->cursor->value); \
} \
\
@@ -683,7 +703,7 @@
return iter->index; \
} \
\
FMOD SNAME##_node *PFX##_impl_new_node(K key, V value) \
static SNAME##_node *PFX##_impl_new_node(K key, V value) \
{ \
SNAME##_node *node = malloc(sizeof(SNAME##_node)); \
\
@@ -700,7 +720,7 @@
return node; \
} \
\
FMOD SNAME##_node *PFX##_impl_get_node(SNAME *_map_, K key) \
static SNAME##_node *PFX##_impl_get_node(SNAME *_map_, K key) \
{ \
if (PFX##_empty(_map_)) \
return NULL; \
@@ -720,7 +740,7 @@
return NULL; \
} \
\
FMOD unsigned char PFX##_impl_h(SNAME##_node *node) \
static unsigned char PFX##_impl_h(SNAME##_node *node) \
{ \
if (node == NULL) \
return 0; \
@@ -728,7 +748,7 @@
return node->height; \
} \
\
FMOD unsigned char PFX##_impl_hupdate(SNAME##_node *node) \
static unsigned char PFX##_impl_hupdate(SNAME##_node *node) \
{ \
if (node == NULL) \
return 0; \
@@ -739,7 +759,7 @@
return 1 + (h_l > h_r ? h_l : h_r); \
} \
\
FMOD void PFX##_impl_rotate_right(SNAME##_node **Z) \
static void PFX##_impl_rotate_right(SNAME##_node **Z) \
{ \
SNAME##_node *root = *Z; \
SNAME##_node *new_root = root->left; \
@@ -768,7 +788,7 @@
*Z = new_root; \
} \
\
FMOD void PFX##_impl_rotate_left(SNAME##_node **Z) \
static void PFX##_impl_rotate_left(SNAME##_node **Z) \
{ \
SNAME##_node *root = *Z; \
SNAME##_node *new_root = root->right; \
@@ -797,7 +817,7 @@
*Z = new_root; \
} \
\
FMOD void PFX##_impl_rebalance(SNAME *_map_, SNAME##_node *node) \
static void PFX##_impl_rebalance(SNAME *_map_, SNAME##_node *node) \
{ \
SNAME##_node *scan = node, *child = NULL; \
\
@@ -841,7 +861,7 @@
} \
} \
\
SNAME##_iter PFX##_impl_it_start(SNAME *_map_) \
static SNAME##_iter PFX##_impl_it_start(SNAME *_map_) \
{ \
SNAME##_iter iter; \
\
@@ -850,7 +870,7 @@
return iter; \
} \
\
SNAME##_iter PFX##_impl_it_end(SNAME *_map_) \
static SNAME##_iter PFX##_impl_it_end(SNAME *_map_) \
{ \
SNAME##_iter iter; \
\
+182 -63
View File
@@ -17,26 +17,17 @@
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define TREESET_GENERATE(PFX, SNAME, FMOD, V) \
TREESET_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \
TREESET_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
TREESET_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* PRIVATE *******************************************************************/
#define TREESET_GENERATE_HEADER_PRIVATE(PFX, SNAME, FMOD, K, V) \
#define TREESET_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \
TREESET_GENERATE_HEADER(PFX, SNAME, FMOD, V)
#define TREESET_GENERATE_SOURCE_PRIVATE(PFX, SNAME, FMOD, K, V) \
TREESET_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \
#define TREESET_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \
TREESET_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* PUBLIC ********************************************************************/
#define TREESET_GENERATE_HEADER_PUBLIC(PFX, SNAME, FMOD, K, V) \
TREESET_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \
TREESET_GENERATE_HEADER(PFX, SNAME, FMOD, V)
#define TREESET_GENERATE_SOURCE_PUBLIC(PFX, SNAME, FMOD, K, V) \
TREESET_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* STRUCT ********************************************************************/
#define TREESET_GENERATE_STRUCT(PFX, SNAME, FMOD, V)
/* HEADER ********************************************************************/
#define TREESET_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
@@ -118,8 +109,8 @@
FMOD bool PFX##_insert_if(SNAME *_set_, V element, bool condition); \
FMOD bool PFX##_remove_if(SNAME *_set_, V element, bool condition); \
/* Element Access */ \
FMOD V PFX##_max(SNAME *_set_); \
FMOD V PFX##_min(SNAME *_set_); \
FMOD bool PFX##_max(SNAME *_set_, V *value); \
FMOD bool PFX##_min(SNAME *_set_, V *value); \
/* Collection State */ \
FMOD bool PFX##_contains(SNAME *_set_, V element); \
FMOD bool PFX##_empty(SNAME *_set_); \
@@ -130,6 +121,11 @@
FMOD SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_); \
FMOD SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_); \
FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_); \
FMOD bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_); \
FMOD bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_); \
FMOD bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_); \
FMOD bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_); \
FMOD bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_); \
\
/* Iterator Functions */ \
/* Iterator Allocation and Deallocation */ \
@@ -149,18 +145,29 @@
FMOD V PFX##_iter_value(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 TREESET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \
\
FMOD SNAME##_node *PFX##_new_node(V element); \
FMOD SNAME##_node *PFX##_get_node(SNAME *_set_, V element); \
FMOD unsigned char PFX##_h(SNAME##_node *node); \
FMOD unsigned char PFX##_hupdate(SNAME##_node *node); \
FMOD void PFX##_rotate_right(SNAME##_node **Z); \
FMOD void PFX##_rotate_left(SNAME##_node **Z); \
FMOD void PFX##_rebalance(SNAME *_set_, SNAME##_node *node); \
SNAME##_iter PFX##_impl_it_start(SNAME *_set_); \
SNAME##_iter PFX##_impl_it_end(SNAME *_set_); \
/* Implementation Detail Functions */ \
static SNAME##_node *PFX##_impl_new_node(V element); \
static SNAME##_node *PFX##_impl_get_node(SNAME *_set_, V element); \
static unsigned char PFX##_impl_h(SNAME##_node *node); \
static unsigned char PFX##_impl_hupdate(SNAME##_node *node); \
static void PFX##_impl_rotate_right(SNAME##_node **Z); \
static void PFX##_impl_rotate_left(SNAME##_node **Z); \
static void PFX##_impl_rebalance(SNAME *_set_, SNAME##_node *node); \
static SNAME##_iter PFX##_impl_it_start(SNAME *_set_); \
static SNAME##_iter PFX##_impl_it_end(SNAME *_set_); \
\
FMOD SNAME *PFX##_new(int (*compare)(V, V)) \
{ \
@@ -245,7 +252,7 @@
{ \
if (PFX##_empty(_set_)) \
{ \
_set_->root = PFX##_new_node(element); \
_set_->root = PFX##_impl_new_node(element); \
\
if (!_set_->root) \
return false; \
@@ -271,7 +278,7 @@
\
if (_set_->cmp(parent->value, element) > 0) \
{ \
parent->left = PFX##_new_node(element); \
parent->left = PFX##_impl_new_node(element); \
\
if (!parent->left) \
return false; \
@@ -281,7 +288,7 @@
} \
else \
{ \
parent->right = PFX##_new_node(element); \
parent->right = PFX##_impl_new_node(element); \
\
if (!parent->right) \
return false; \
@@ -290,7 +297,7 @@
node = parent->right; \
} \
\
PFX##_rebalance(_set_, node); \
PFX##_impl_rebalance(_set_, node); \
} \
\
_set_->count++; \
@@ -300,7 +307,7 @@
\
FMOD bool PFX##_remove(SNAME *_set_, V element) \
{ \
SNAME##_node *node = PFX##_get_node(_set_, element); \
SNAME##_node *node = PFX##_impl_get_node(_set_, element); \
\
if (!node) \
return false; \
@@ -409,7 +416,7 @@
} \
\
if (unbalanced != NULL) \
PFX##_rebalance(_set_, unbalanced); \
PFX##_impl_rebalance(_set_, unbalanced); \
\
_set_->count--; \
\
@@ -435,30 +442,34 @@
return false; \
} \
\
FMOD V PFX##_max(SNAME *_set_) \
FMOD bool PFX##_max(SNAME *_set_, V *value) \
{ \
if (PFX##_empty(_set_)) \
return 0; \
return false; \
\
SNAME##_node *scan = _set_->root; \
\
while (scan->right != NULL) \
scan = scan->right; \
\
return scan->value; \
*value = scan->value; \
\
return true; \
} \
\
FMOD V PFX##_min(SNAME *_set_) \
FMOD bool PFX##_min(SNAME *_set_, V *value) \
{ \
if (PFX##_empty(_set_)) \
return 0; \
return false; \
\
SNAME##_node *scan = _set_->root; \
\
while (scan->left != NULL) \
scan = scan->left; \
\
return scan->value; \
*value = scan->value; \
\
return true; \
} \
\
FMOD bool PFX##_contains(SNAME *_set_, V element) \
@@ -529,7 +540,7 @@
{ \
V value = PFX##_iter_value(&iter); \
\
if (PFX##_get_node(_set_B_, value) != NULL) \
if (PFX##_impl_get_node(_set_B_, value) != NULL) \
PFX##_insert(_set_r_, value); \
} \
\
@@ -550,7 +561,7 @@
{ \
V value = PFX##_iter_value(&iter); \
\
if (PFX##_get_node(_set2_, value) == NULL) \
if (PFX##_impl_get_node(_set2_, value) == NULL) \
PFX##_insert(_set_r_, value); \
} \
\
@@ -572,7 +583,7 @@
{ \
V value = PFX##_iter_value(&iter1); \
\
if (PFX##_get_node(_set2_, value) == NULL) \
if (PFX##_impl_get_node(_set2_, value) == NULL) \
PFX##_insert(_set_r_, value); \
} \
\
@@ -580,13 +591,118 @@
{ \
V value = PFX##_iter_value(&iter2); \
\
if (PFX##_get_node(_set1_, value) == NULL) \
if (PFX##_impl_get_node(_set1_, value) == NULL) \
PFX##_insert(_set_r_, value); \
} \
\
return _set_r_; \
} \
\
/* Is _set1_ a subset of _set2_ ? */ \
/* A set X is a subset of a set Y when: X <= Y */ \
/* If X is a subset of Y, then Y is a superset of X */ \
FMOD bool PFX##_is_subset(SNAME *_set1_, SNAME *_set2_) \
{ \
/* If the cardinality of _set1_ is greater than that of _set2_, then it is safe */ \
/* to say that _set1_ can't be a subset of _set2_ */ \
if (PFX##_count(_set1_) > PFX##_count(_set2_)) \
return false; \
\
/* The empty set is a subset of all sets */ \
if (PFX##_empty(_set1_)) \
return true; \
\
SNAME##_iter iter; \
\
PFX##_iter_init(&iter, _set1_); \
\
for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
{ \
V value = PFX##_iter_value(&iter); \
\
if (!PFX##_contains(_set2_, value)) \
return false; \
} \
\
return true; \
} \
\
/* Is _set1_ a superset of _set2_ ? */ \
/* A set X is a superset of a set Y when: X >= Y */ \
/* If X is a superset of Y, then Y is a subset of X */ \
FMOD bool PFX##_is_superset(SNAME *_set1_, SNAME *_set2_) \
{ \
return PFX##_is_subset(_set2_, _set1_); \
} \
\
/* Is _set1_ a proper subset of _set2_ ? */ \
/* A set X is a proper subset of a set Y when: X < Y */ \
/* If X is a proper subset of Y, then Y is a proper superset of X */ \
FMOD bool PFX##_is_proper_subset(SNAME *_set1_, SNAME *_set2_) \
{ \
/* If the cardinality of _set1_ is greater than or equal to that of _set2_, then */ \
/* it is safe to say that _set1_ can't be a proper subset of _set2_ */ \
if (PFX##_count(_set1_) >= PFX##_count(_set2_)) \
return false; \
\
if (PFX##_empty(_set1_)) \
{ \
/* The empty set is a proper subset of all non-empty sets */ \
if (!PFX##_empty(_set2_)) \
return true; \
/* The empty set is not a proper subset of itself (this is true for any set) */ \
else \
return false; \
} \
\
SNAME##_iter iter; \
\
PFX##_iter_init(&iter, _set1_); \
\
for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
{ \
V value = PFX##_iter_value(&iter); \
\
if (!PFX##_contains(_set2_, value)) \
return false; \
} \
\
return true; \
} \
\
/* Is _set1_ a proper superset of _set2_ ? */ \
/* A set X is a proper superset of a set Y when: X > Y */ \
/* If X is a proper superset of Y, then Y is a proper subset of X */ \
FMOD bool PFX##_is_proper_superset(SNAME *_set1_, SNAME *_set2_) \
{ \
return PFX##_is_proper_subset(_set2_, _set1_); \
} \
\
/* Is _set1_ a disjointset of _set2_ ? */ \
/* A set X is a disjointset of a set Y if their intersection is empty, that is, if */ \
/* there are no elements in common between the two */ \
FMOD bool PFX##_is_disjointset(SNAME *_set1_, SNAME *_set2_) \
{ \
/* The intersection of an empty set with any other set will result in an empty */ \
/* set */ \
if (PFX##_empty(_set1_)) \
return true; \
\
SNAME##_iter iter; \
\
PFX##_iter_init(&iter, _set1_); \
\
for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
{ \
V value = PFX##_iter_value(&iter); \
\
if (PFX##_contains(_set2_, value)) \
return false; \
} \
\
return true; \
} \
\
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \
{ \
SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \
@@ -730,6 +846,9 @@
\
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
PFX##_impl_default_value(); \
\
return iter->cursor->value; \
} \
\
@@ -738,7 +857,7 @@
return iter->index; \
} \
\
FMOD SNAME##_node *PFX##_new_node(V element) \
static SNAME##_node *PFX##_impl_new_node(V element) \
{ \
SNAME##_node *node = malloc(sizeof(SNAME##_node)); \
\
@@ -754,7 +873,7 @@
return node; \
} \
\
FMOD SNAME##_node *PFX##_get_node(SNAME *_set_, V element) \
static SNAME##_node *PFX##_impl_get_node(SNAME *_set_, V element) \
{ \
if (PFX##_empty(_set_)) \
return NULL; \
@@ -774,7 +893,7 @@
return NULL; \
} \
\
FMOD unsigned char PFX##_h(SNAME##_node *node) \
static unsigned char PFX##_impl_h(SNAME##_node *node) \
{ \
if (node == NULL) \
return 0; \
@@ -782,18 +901,18 @@
return node->height; \
} \
\
FMOD unsigned char PFX##_hupdate(SNAME##_node *node) \
static unsigned char PFX##_impl_hupdate(SNAME##_node *node) \
{ \
if (node == NULL) \
return 0; \
\
unsigned char h_l = PFX##_h(node->left); \
unsigned char h_r = PFX##_h(node->right); \
unsigned char h_l = PFX##_impl_h(node->left); \
unsigned char h_r = PFX##_impl_h(node->right); \
\
return 1 + (h_l > h_r ? h_l : h_r); \
} \
\
FMOD void PFX##_rotate_right(SNAME##_node **Z) \
static void PFX##_impl_rotate_right(SNAME##_node **Z) \
{ \
SNAME##_node *root = *Z; \
SNAME##_node *new_root = root->left; \
@@ -816,13 +935,13 @@
\
new_root->right = root; \
\
root->height = PFX##_hupdate(root); \
new_root->height = PFX##_hupdate(new_root); \
root->height = PFX##_impl_hupdate(root); \
new_root->height = PFX##_impl_hupdate(new_root); \
\
*Z = new_root; \
} \
\
FMOD void PFX##_rotate_left(SNAME##_node **Z) \
static void PFX##_impl_rotate_left(SNAME##_node **Z) \
{ \
SNAME##_node *root = *Z; \
SNAME##_node *new_root = root->right; \
@@ -845,13 +964,13 @@
\
new_root->left = root; \
\
root->height = PFX##_hupdate(root); \
new_root->height = PFX##_hupdate(new_root); \
root->height = PFX##_impl_hupdate(root); \
new_root->height = PFX##_impl_hupdate(new_root); \
\
*Z = new_root; \
} \
\
FMOD void PFX##_rebalance(SNAME *_set_, SNAME##_node *node) \
static void PFX##_impl_rebalance(SNAME *_set_, SNAME##_node *node) \
{ \
SNAME##_node *scan = node, *child = NULL; \
\
@@ -863,26 +982,26 @@
if (scan->parent == NULL) \
is_root = true; \
\
scan->height = PFX##_hupdate(scan); \
balance = PFX##_h(scan->right) - PFX##_h(scan->left); \
scan->height = PFX##_impl_hupdate(scan); \
balance = PFX##_impl_h(scan->right) - PFX##_impl_h(scan->left); \
\
if (balance >= 2) \
{ \
child = scan->right; \
\
if (PFX##_h(child->right) < PFX##_h(child->left)) \
PFX##_rotate_right(&(scan->right)); \
if (PFX##_impl_h(child->right) < PFX##_impl_h(child->left)) \
PFX##_impl_rotate_right(&(scan->right)); \
\
PFX##_rotate_left(&scan); \
PFX##_impl_rotate_left(&scan); \
} \
else if (balance <= -2) \
{ \
child = scan->left; \
\
if (PFX##_h(child->left) < PFX##_h(child->right)) \
PFX##_rotate_left(&(scan->left)); \
if (PFX##_impl_h(child->left) < PFX##_impl_h(child->right)) \
PFX##_impl_rotate_left(&(scan->left)); \
\
PFX##_rotate_right(&scan); \
PFX##_impl_rotate_right(&scan); \
} \
\
if (is_root) \
@@ -895,7 +1014,7 @@
} \
} \
\
SNAME##_iter PFX##_impl_it_start(SNAME *_set_) \
static SNAME##_iter PFX##_impl_it_start(SNAME *_set_) \
{ \
SNAME##_iter iter; \
\
@@ -904,7 +1023,7 @@
return iter; \
} \
\
SNAME##_iter PFX##_impl_it_end(SNAME *_set_) \
static SNAME##_iter PFX##_impl_it_end(SNAME *_set_) \
{ \
SNAME##_iter iter; \
\
+654
View File
@@ -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 */
+384
View File
@@ -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 */
+27 -22
View File
@@ -14,35 +14,40 @@
#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) C##_WRAPGEN_HEADER
#define CONCATC_(C) C##_WRAPGEN_SOURCE
#define CONCATH(C, P) CONCATH_(C, P)
#define CONCATC(C, P) CONCATC_(C, P)
#define CONCATH(C) CONCATH_(C)
#define CONCATC(C) CONCATC_(C)
#define COLLECTION_GENERATE(C, P, PFX, SNAME, FMOD, K, V) \
COLLECTION_GENERATE_HEADER(C, P, PFX, SNAME, FMOD, K, V) \
COLLECTION_GENERATE_SOURCE(C, P, PFX, SNAME, FMOD, K, V)
#define COLLECTION_GENERATE(C, PFX, SNAME, FMOD, K, V) \
COLLECTION_GENERATE_HEADER(C, PFX, SNAME, FMOD, K, V) \
COLLECTION_GENERATE_SOURCE(C, PFX, SNAME, FMOD, K, V)
#define COLLECTION_GENERATE_HEADER(C, P, PFX, SNAME, FMOD, K, V) \
CONCATH(C, P) \
#define COLLECTION_GENERATE_HEADER(C, PFX, SNAME, FMOD, K, V) \
CONCATH(C) \
(PFX, SNAME, FMOD, K, V)
#define COLLECTION_GENERATE_SOURCE(C, P, PFX, SNAME, FMOD, K, V) \
CONCATC(C, P) \
#define COLLECTION_GENERATE_SOURCE(C, PFX, SNAME, FMOD, K, V) \
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
View File
@@ -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 */
View File
File renamed without changes.
+203
View File
@@ -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 */
+15
View File
@@ -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
+7
View File
@@ -0,0 +1,7 @@
# Tests
* `sep/main.c`, `sep/sep.c` and `sep/sep.h` - Tests separate header and source compilation;
* `contains.c` - Tests the `contains` function for all collections;
* `foreach.c` - Tests the ForEach macros for all collections;
* `iterators.c` - Tests all collection's iterators;
* `types.c` - Tests if all containers accept all possible C data types (struct, union, enum, pointers, function pointers)
+10 -10
View File
@@ -20,16 +20,16 @@ size_t inthash(int t)
return a;
}
COLLECTION_GENERATE(LIST, PUBLIC, l, list, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(STACK, PUBLIC, s, stack, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(QUEUE, PUBLIC, q, queue, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(DEQUE, PUBLIC, d, deque, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(LINKEDLIST, PUBLIC, ll, linked, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(HEAP, PUBLIC, h, heap, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(TREESET, PUBLIC, ts, tset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(TREEMAP, PUBLIC, tm, tmap, /* FMOD */, int, int)
COLLECTION_GENERATE(HASHSET, PUBLIC, hs, hset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(HASHMAP, PUBLIC, hm, hmap, /* FMOD */, int, int)
COLLECTION_GENERATE(LIST, l, list, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(STACK, s, stack, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(QUEUE, q, queue, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(DEQUE, d, deque, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(LINKEDLIST, ll, linked, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(HEAP, h, heap, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(TREESET, ts, tset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(TREEMAP, tm, tmap, /* FMOD */, int, int)
COLLECTION_GENERATE(HASHSET, hs, hset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(HASHMAP, hm, hmap, /* FMOD */, int, int)
int main(void)
{
+11 -11
View File
@@ -4,7 +4,7 @@
int intcmp(int a, int b)
{
return a - b;
return (a > b) - (a < b);
}
size_t inthash(int t)
@@ -19,16 +19,16 @@ size_t inthash(int t)
return a;
}
COLLECTION_GENERATE(LIST, PUBLIC, l, list, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(STACK, PUBLIC, s, stack, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(QUEUE, PUBLIC, q, queue, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(DEQUE, PUBLIC, d, deque, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(LINKEDLIST, PUBLIC, ll, linked, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(HEAP, PUBLIC, h, heap, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(TREESET, PUBLIC, ts, tset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(TREEMAP, PUBLIC, tm, tmap, /* FMOD */, int, int)
COLLECTION_GENERATE(HASHSET, PUBLIC, hs, hset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(HASHMAP, PUBLIC, hm, hmap, /* FMOD */, int, int)
COLLECTION_GENERATE(LIST, l, list, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(STACK, s, stack, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(QUEUE, q, queue, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(DEQUE, d, deque, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(LINKEDLIST, ll, linked, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(HEAP, h, heap, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(TREESET, ts, tset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(TREEMAP, tm, tmap, /* FMOD */, int, int)
COLLECTION_GENERATE(HASHSET, hs, hset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(HASHMAP, hm, hmap, /* FMOD */, int, int)
int main(void)
{
+11 -11
View File
@@ -4,7 +4,7 @@
int intcmp(int a, int b)
{
return a - b;
return (a > b) - (a < b);
}
size_t inthash(int t)
@@ -19,16 +19,16 @@ size_t inthash(int t)
return a;
}
COLLECTION_GENERATE(LIST, PUBLIC, l, list, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(STACK, PUBLIC, s, stack, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(QUEUE, PUBLIC, q, queue, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(DEQUE, PUBLIC, d, deque, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(LINKEDLIST, PUBLIC, ll, linked, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(HEAP, PUBLIC, h, heap, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(TREESET, PUBLIC, ts, tset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(TREEMAP, PUBLIC, tm, tmap, /* FMOD */, int, double)
COLLECTION_GENERATE(HASHSET, PUBLIC, hs, hset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(HASHMAP, PUBLIC, hm, hmap, /* FMOD */, int, double)
COLLECTION_GENERATE(LIST, l, list, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(STACK, s, stack, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(QUEUE, q, queue, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(DEQUE, d, deque, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(LINKEDLIST, ll, linked, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(HEAP, h, heap, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(TREESET, ts, tset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(TREEMAP, tm, tmap, /* FMOD */, int, double)
COLLECTION_GENERATE(HASHSET, hs, hset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(HASHMAP, hm, hmap, /* FMOD */, int, double)
#define ITERATOR_TEST(NAME, PFX, sname, initfunc, insertbody, sumbody, validation1, validation2) \
void NAME##_iterator_test(void) \
-29
View File
@@ -1,29 +0,0 @@
// Tests all containers if they accept a pinter type
// Compile with -Wall -Wextra
#include "../src/macro_collections.h"
#include <stdio.h>
typedef struct my_struct_s
{
int a, b;
} my_struct;
COLLECTION_GENERATE(LIST, PUBLIC, l, list, /* FMOD */, /* K */, my_struct *)
COLLECTION_GENERATE(STACK, PUBLIC, s, stack, /* FMOD */, /* K */, my_struct *)
COLLECTION_GENERATE(QUEUE, PUBLIC, q, queue, /* FMOD */, /* K */, my_struct *)
COLLECTION_GENERATE(DEQUE, PUBLIC, d, deque, /* FMOD */, /* K */, my_struct *)
COLLECTION_GENERATE(LINKEDLIST, PUBLIC, ll, linked, /* FMOD */, /* K */, my_struct *)
COLLECTION_GENERATE(HEAP, PUBLIC, h, heap, /* FMOD */, /* K */, my_struct *)
COLLECTION_GENERATE(TREESET, PUBLIC, ts, tset, /* FMOD */, /* K */, my_struct *)
COLLECTION_GENERATE(TREEMAP, PUBLIC, tm, tmap, /* FMOD */, my_struct *, my_struct *)
COLLECTION_GENERATE(HASHSET, PUBLIC, hs, hset, /* FMOD */, /* K */, my_struct *)
COLLECTION_GENERATE(HASHMAP, PUBLIC, hm, hmap, /* FMOD */, my_struct *, my_struct *)
int main(void)
{
printf("+--------------------------------------------------+\n");
printf("| Pointer Data Type is Working |\n");
printf("+--------------------------------------------------+\n");
return 0;
}
+50
View File
@@ -0,0 +1,50 @@
#include "sep.h"
#include <stdio.h>
int intcmp(int a, int b)
{
return (a > b) - (a < b);
}
size_t inthash(int t)
{
size_t a = t;
a += ~(a << 15);
a ^= (a >> 10);
a += (a << 3);
a ^= (a >> 6);
a += ~(a << 11);
a ^= (a >> 16);
return a;
}
int main(void)
{
list *l = l_new(1000);
stack *s = s_new(1000);
queue *q = q_new(1000);
deque *d = d_new(1000);
linked *ll = ll_new();
heap *h = h_new(1000, MaxHeap, intcmp);
tset *ts = ts_new(intcmp);
tmap *tm = tm_new(intcmp);
hset *hs = hs_new(1000, 0.9, intcmp, inthash);
hmap *hm = hm_new(1000, 0.9, intcmp, inthash);
printf("+--------------------------------------------------+\n");
printf("| Separate Header and Source is Working |\n");
printf("+--------------------------------------------------+\n");
l_free(l);
ll_free(ll);
s_free(s);
q_free(q);
d_free(d);
h_free(h);
ts_free(ts);
tm_free(tm);
hs_free(hs);
hm_free(hm);
return 0;
}
+12
View File
@@ -0,0 +1,12 @@
#include "sep.h"
COLLECTION_GENERATE_SOURCE(LIST, l, list, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_SOURCE(STACK, s, stack, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_SOURCE(QUEUE, q, queue, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_SOURCE(DEQUE, d, deque, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_SOURCE(LINKEDLIST, ll, linked, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_SOURCE(HEAP, h, heap, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_SOURCE(TREESET, ts, tset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_SOURCE(TREEMAP, tm, tmap, /* FMOD */, int, int)
COLLECTION_GENERATE_SOURCE(HASHSET, hs, hset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_SOURCE(HASHMAP, hm, hmap, /* FMOD */, int, int)
+12
View File
@@ -0,0 +1,12 @@
#include "../../src/macro_collections.h"
COLLECTION_GENERATE_HEADER(LIST, l, list, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_HEADER(STACK, s, stack, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_HEADER(QUEUE, q, queue, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_HEADER(DEQUE, d, deque, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_HEADER(LINKEDLIST, ll, linked, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_HEADER(HEAP, h, heap, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_HEADER(TREESET, ts, tset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_HEADER(TREEMAP, tm, tmap, /* FMOD */, int, int)
COLLECTION_GENERATE_HEADER(HASHSET, hs, hset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_HEADER(HASHMAP, hm, hmap, /* FMOD */, int, int)
+146
View File
@@ -0,0 +1,146 @@
// Tests all containers if they accept all C data types
// Compile with -Wall -Wextra
#include "../src/macro_collections.h"
#include <stdio.h>
typedef struct struct_s
{
int a, b;
char *c, *d;
double e[10];
} struct_t;
typedef enum enum_e
{
HELLO,
WORLD,
NONE = 0
} enum_t;
typedef union union_u {
enum enum_e a;
struct struct_s b;
double c;
char *d;
} union_t;
typedef int (*func_t)(int, double, char *);
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, 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, 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, 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, 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, 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, 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, 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, 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, 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)
{
printf("+--------------------------------------------------+\n");
printf("| All Data Types Are Working |\n");
printf("+--------------------------------------------------+\n");
return 0;
}