40 Commits
Author SHA1 Message Date
Leonardo e8142f96b1 v1.5.3 2019-07-04 15:49:56 -03:00
Leonardo 97d50bc3d9 Fixing and adding more tests 2019-07-04 15:34:25 -03:00
Leonardo 8c457eeb12 Fixing missing return statements 2019-07-04 14:55:17 -03:00
Leonardo 846d0bbba6 More tests 2019-07-04 02:18:05 -03:00
Leonardo a9314ee8f7 Update assert.h 2019-07-04 02:13:41 -03:00
Leonardo 9bff706bba test quickfix 2019-07-02 01:49:19 -03:00
Leonardo 31c871c4c2 Fixing CI shield 2019-07-02 01:38:08 -03:00
Leonardo 82b374ec83 Revert "Fixing CI shield and trying to fix code coverage through codecov.yml"
This reverts commit 940552d6cd.
2019-07-02 01:36:46 -03:00
Leonardo 940552d6cd Fixing CI shield and trying to fix code coverage through codecov.yml 2019-07-02 01:30:03 -03:00
Leonardo 6a2cb70fb5 Tests update 2019-07-02 01:05:16 -03:00
Leonardo 78cfc0c335 Create .gitattributes 2019-07-01 17:20:04 -03:00
Leonardo f454934b07 Reorganizing tests 2019-07-01 17:10:28 -03:00
Leonardo 5504f82052 Added codecov shield 2019-06-28 01:48:31 -03:00
Leonardo d01997b7cb v1.5.2 2019-06-28 01:08:55 -03:00
Leonardo 7b349ea426 Many minor fixes, changes and first attempt of codecov
Changes on assert.h, foreach.h, test.h and timer.h
Updated benchmarks, examples and tests
Updated tests/Makefile for future
Added list.c test
Added CMC namespace to CONCATC and CONCATH on macro_collections.h
2019-06-28 00:52:23 -03:00
Leonardo 1edb12a83c Added assert macros utility 2019-06-27 23:55:10 -03:00
Leonardo 176bbc66ad Added UnitTest utility and removed unnecessary logging functions 2019-06-26 01:32:44 -03:00
Leonardo 41eebe546a v1.5.1 2019-06-24 02:11:28 -03:00
Leonardo afaecb2dde Update TODO, CHANGELOG and headers 2019-06-24 02:11:10 -03:00
Leonardo 9062415322 Added sac/queue.h, moved timer.h to utl folder, new queue benchmark 2019-06-24 02:09:02 -03:00
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
107 changed files with 13718 additions and 2863 deletions

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
# Auto detect text files and perform LF normalization
* text=auto
*.h linguist-language=C
*.c linguist-language=C
+4 -1
View File
@@ -52,4 +52,7 @@ Mkfile.old
dkms.conf
# vscode folder
.vscode
.vscode
# Experimental folder
experimental/
+6 -8
View File
@@ -8,15 +8,13 @@ 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
- cd main
- make
after_success:
- bash <(curl -s https://codecov.io/bash)
+121 -66
View File
@@ -1,4 +1,124 @@
# MAJOR.MINOR.ADJUSTMENTS
# RELEASE.MAJOR.MINOR
1.5.3
Tests completely reorganized and now with full code coverage
Some fixes where there was a missing return statement
Expanded utl/assert.h
1.5.2
Added utl/test.h
Added utl/assert.h
Added tests/list.c - UnitTest for LIST
Small fixes on utl/foreach.h, utl/test.h and redone utl/timer.h
Removed utl/log.h functions that were unnecessary
Added the CMC namespace to CONCATC and CONCATH at macro_collections.h
1.5.1
New queue benchmark
Added sac/queue.h
Added utl/timer.h
Fixing descriptions and other minor fixes
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
@@ -18,68 +138,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
+71 -31
View File
@@ -3,31 +3,78 @@
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)
![Build](https://travis-ci.org/LeoVen/C-Macro-Collections.svg?branch=master)
![Version](https://img.shields.io/badge/Version-v1.5.3-orange.svg)
[![Build](https://travis-ci.org/LeoVen/C-Macro-Collections.svg?branch=master)](https://travis-ci.org/LeoVen/C-Macro-Collections)
[![codecov](https://codecov.io/gh/LeoVen/C-Macro-Collections/branch/master/graph/badge.svg)](https://codecov.io/gh/LeoVen/C-Macro-Collections)
## 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
* Queue
* 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 +132,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 +150,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.
+16 -22
View File
@@ -1,13 +1,16 @@
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
[ ] ToString method to all Collections
MAYBE
@@ -20,37 +23,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
+25 -26
View File
@@ -13,7 +13,6 @@
* - Output
*/
#include "macro_collections.h"
#include "util/timer.h"
#include "util/twister.c"
#include <stdio.h>
#include <stdint.h>
@@ -60,16 +59,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) \
@@ -82,17 +81,17 @@ COLLECTION_GENERATE(HASHMAP, PUBLIC, hm, hmap, /* FMOD */, int, int)
\
sname *coll = initfunc; \
\
TIMER_START(total) \
TIMER_START(timer) \
timer_start(total); \
timer_start(timer); \
\
for (size_t i = 0; i < NTOTAL; i++) \
{ \
insertbody; \
} \
\
TIMER_STOP(timer) \
timer_stop(timer); \
\
TIMER_CALC(timer) \
timer_calc(timer); \
\
size_t s1 = PFX##_count(coll); \
\
@@ -100,16 +99,16 @@ COLLECTION_GENERATE(HASHMAP, PUBLIC, hm, hmap, /* FMOD */, int, int)
\
double input_time = timer.result; \
\
TIMER_START(timer) \
timer_start(timer); \
\
for (size_t i = 0; i < s; i++) \
{ \
searchbody; \
} \
\
TIMER_STOP(timer) \
timer_stop(timer); \
\
TIMER_CALC(timer) \
timer_calc(timer); \
\
printf(" SEARCH %10s TOOK %8.0lf milliseconds for %8" PRIuMAX " elements\n", #NAME, timer.result, s); \
\
@@ -117,30 +116,30 @@ COLLECTION_GENERATE(HASHMAP, PUBLIC, hm, hmap, /* FMOD */, int, int)
\
sname##_iter iter; \
\
TIMER_START(timer) \
timer_start(timer); \
\
for (PFX##_iter_init(&iter, coll); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
{ \
} \
\
TIMER_STOP(timer) \
timer_stop(timer); \
\
TIMER_CALC(timer) \
timer_calc(timer); \
\
printf("ITERATION %10s TOOK %8.0lf milliseconds for %8" PRIuMAX " elements\n", #NAME, timer.result, s1); \
\
double iter_time = timer.result; \
\
TIMER_START(timer); \
timer_start(timer); \
\
for (size_t i = 0; i < NTOTAL; i++) \
{ \
removebody; \
} \
\
TIMER_STOP(timer) \
timer_stop(timer); \
\
TIMER_CALC(timer) \
timer_calc(timer); \
\
size_t s2 = PFX##_count(coll); \
\
@@ -148,8 +147,8 @@ COLLECTION_GENERATE(HASHMAP, PUBLIC, hm, hmap, /* FMOD */, int, int)
\
double output_time = timer.result; \
\
TIMER_STOP(total) \
TIMER_CALC(total) \
timer_stop(total); \
timer_calc(total); \
\
PFX##_free(coll); \
\
+10
View File
@@ -0,0 +1,10 @@
CFLAGS = -Wall -Wextra
INCLUDE = ../../src
main:
gcc queue.c -I $(INCLUDE) $(CFLAGS) -o a.exe -DCMC_QUEUE
a.exe
gcc queue.c -I $(INCLUDE) $(CFLAGS) -o a.exe -DSAC_QUEUE
a.exe
gcc queue.c -I $(INCLUDE) $(CFLAGS) -o a.exe -DEXT_QUEUE
a.exe
+82
View File
@@ -0,0 +1,82 @@
/**
* queue.c
*
* Creation Date: 24/06/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
/* Showing off how different queue implementations affect runtime cost */
#include "utl/timer.h"
#include <stdio.h>
#include <inttypes.h>
#define MAX 200000
#if defined(CMC_QUEUE)
#include "cmc/queue.h"
QUEUE_GENERATE(q, queue, , int)
#define TARGET "QUEUE"
#elif defined(SAC_QUEUE)
#include "sac/queue.h"
SAC_QUEUE_GENERATE(q, queue, , int, MAX)
#define TARGET "SAC QUEUE"
#elif defined(EXT_QUEUE)
#include "ext/linkedqueue.h"
LINKEDQUEUE_GENERATE(q, queue, , int)
#define TARGET "LINKED QUEUE"
#else
#error Please define either CMC_QUEUE, SAC_QUEUE or EXT_QUEUE
#endif
int main(void)
{
#if defined(CMC_QUEUE)
queue *q = q_new(MAX);
#elif defined(SAC_QUEUE)
queue _q = q_new();
queue_ptr q = &_q;
#elif defined(EXT_QUEUE)
queue *q = q_new();
#endif
size_t sum = 0;
int i = 0;
timer_t timer;
TIMER_START(timer);
while (q_count(q) != MAX)
{
q_enqueue(q, i++);
if (i % 10 == 0)
{
for (size_t i = 0; i < 9; i++)
{
sum += q_peek(q);
q_dequeue(q);
}
}
}
TIMER_STOP(timer);
TIMER_CALC(timer);
printf("----------------------------------------\n");
printf("%s\n", TARGET);
printf("Execution time: %.0lf milliseconds\n", timer.result);
printf("SUM: %" PRIuMAX "\n", sum);
printf("----------------------------------------\n");
#if defined(CMC_QUEUE) || defined(EXT_QUEUE)
q_free(q);
#endif
return 0;
}
-27
View File
@@ -1,27 +0,0 @@
/**
* timer.h
*
* Creation Date: 12/04/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
* Simple timer macros.
*/
#include <time.h>
typedef struct timer_s
{
clock_t start;
clock_t stop;
double result;
} timer_t;
#define TIMER_START(timer) \
timer.start = clock();
#define TIMER_STOP(timer) \
timer.stop = clock();
#define TIMER_CALC(timer) \
timer.result = (double)(((timer.stop - timer.start) * 1000.0) / CLOCKS_PER_SEC);
+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.
+28 -18
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)
{
@@ -59,14 +61,15 @@ int main(int argc, char const *argv[])
map_insert(library, value->isbn, value->name);
set_insert(counter, value->name);
})
});
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");
set_free(counter);
@@ -113,24 +116,31 @@ 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);
}
}
// 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);
q_free(shelf);
+32 -20
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,59 +58,71 @@ 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)
printf("%d ]\n", value);
else
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)
printf("%d ]\n", value);
else
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)
printf("%d ]\n", value);
else
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)
printf("%d ]\n", value);
else
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)
printf("%d ]\n", value);
else
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)
printf("%d ]\n", value);
else
printf("%d, ", value);
})
});
l_free(l);
ll_free(ll);
@@ -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,10 +184,9 @@ 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,9 +254,9 @@ 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 -31
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; \
return 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; \
return 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; \
return PFX##_impl_default_value(); \
\
return iter->target->buffer[iter->cursor]; \
} \
@@ -440,9 +440,8 @@
return iter->index; \
} \
\
FMOD bool PFX##_impl_grow(SNAME *_deque_) \
static bool PFX##_impl_grow(SNAME *_deque_) \
{ \
\
size_t new_capacity = _deque_->capacity * 2; \
\
V *new_buffer = malloc(sizeof(V) * new_capacity); \
@@ -465,7 +464,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 +473,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; \
return 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_)) \
return 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; \
return 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; \
return 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; \
return 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; \
return 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)) \
return PFX##_impl_default_key(); \
\
return iter->cursor->key; \
} \
\
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return 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)) \
return 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_)) \
return 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)) \
return 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 */
+32 -26
View File
@@ -11,38 +11,44 @@
#ifndef CMC_MACRO_COLLECTIONS
#define CMC_MACRO_COLLECTIONS
#include <stdlib.h>
#include <stdbool.h>
#define CMC_CONCATH_(C) C##_WRAPGEN_HEADER
#define CMC_CONCATC_(C) C##_WRAPGEN_SOURCE
#define CONCATH_(C, P) C##_GENERATE_HEADER##_##P
#define CONCATC_(C, P) C##_GENERATE_SOURCE##_##P
#define CMC_CONCATH(C) CMC_CONCATH_(C)
#define CMC_CONCATC(C) CMC_CONCATC_(C)
#define CONCATH(C, P) CONCATH_(C, P)
#define CONCATC(C, P) CONCATC_(C, P)
#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(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_HEADER(C, P, PFX, SNAME, FMOD, K, V) \
CONCATH(C, P) \
#define COLLECTION_GENERATE_HEADER(C, PFX, SNAME, FMOD, K, V) \
CMC_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) \
CMC_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/deque.h"
#include "cmc/hashmap.h"
#include "cmc/hashset.h"
#include "cmc/heap.h"
#include "cmc/linkedlist.h"
#include "cmc/list.h"
#include "cmc/queue.h"
#include "cmc/stack.h"
#include "cmc/treemap.h"
#include "cmc/treeset.h"
#include "foreach.h"
#include "ext/linkedqueue.h"
#endif /* CMC_MACRO_COLLECTIONS */
#include "sac/queue.h"
#include "sac/stack.h"
#include "utl/assert.h"
#include "utl/foreach.h"
#include "utl/log.h"
#include "utl/test.h"
#include "utl/timer.h"
#endif /* CMC_MACRO_COLLECTIONS */
+357
View File
@@ -0,0 +1,357 @@
/**
* queue.h
*
* Creation Date: 24/06/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
/**
* A Purely Stack Allocated Queue
*
* This means that the Queue 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_QUEUE_H
#define CMC_SAC_QUEUE_H
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define SAC_QUEUE_GENERATE(PFX, SNAME, FMOD, V, SIZE) \
SAC_QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V, SIZE) \
SAC_QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V, SIZE)
#define SAC_QUEUE_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V, SIZE) \
SAC_QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V, SIZE)
#define SAC_QUEUE_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V, SIZE) \
SAC_QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V, SIZE)
/* HEADER ********************************************************************/
#define SAC_QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V, SIZE) \
\
/* Queue Structure */ \
typedef struct SNAME##_s \
{ \
/* Internal Storage */ \
V buffer[SIZE]; \
\
/* Current amount of elements */ \
size_t count; \
\
/* Index representing the front of the queue */ \
size_t front; \
\
/* Index representing the back of the queue */ \
size_t rear; \
\
/* Function that returns an iterator to the start of the queue */ \
struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
\
/* Function that returns an iterator to the end of the queue */ \
struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
\
} SNAME, *SNAME##_ptr; \
\
/* Queue Iterator */ \
typedef struct SNAME##_iter_s \
{ \
/* Target queue */ \
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(void); \
FMOD void PFX##_clear(SNAME *_queue_); \
/* Collection Input and Output */ \
FMOD bool PFX##_enqueue(SNAME *_queue_, V element); \
FMOD bool PFX##_dequeue(SNAME *_queue_); \
/* Conditional Input and Output */ \
FMOD bool PFX##_enqueue_if(SNAME *_queue_, V element, bool condition); \
FMOD bool PFX##_dequeue_if(SNAME *_queue_, bool condition); \
/* Element Access */ \
FMOD V PFX##_peek(SNAME *_queue_); \
/* Collection State */ \
FMOD bool PFX##_contains(SNAME *_queue_, V element, int (*comparator)(V, V)); \
FMOD bool PFX##_empty(SNAME *_queue_); \
FMOD bool PFX##_full(SNAME *_queue_); \
FMOD size_t PFX##_count(SNAME *_queue_); \
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_QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V, SIZE) \
\
/* Implementation Detail Functions */ \
static SNAME##_iter PFX##_impl_it_start(SNAME *_queue_); \
static SNAME##_iter PFX##_impl_it_end(SNAME *_queue_); \
\
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 *_queue_) \
{ \
memset(_queue_->buffer, 0, sizeof(_queue_->buffer)); \
\
_queue_->count = 0; \
_queue_->front = 0; \
_queue_->rear = 0; \
} \
\
FMOD bool PFX##_enqueue(SNAME *_queue_, V element) \
{ \
if (PFX##_full(_queue_)) \
return false; \
\
_queue_->buffer[_queue_->rear] = element; \
\
_queue_->rear = (_queue_->rear == SIZE - 1) ? 0 : _queue_->rear + 1; \
_queue_->count++; \
\
return true; \
} \
\
FMOD bool PFX##_dequeue(SNAME *_queue_) \
{ \
if (PFX##_empty(_queue_)) \
return false; \
\
_queue_->buffer[_queue_->front] = PFX##_impl_default_value(); \
\
_queue_->front = (_queue_->front == SIZE - 1) ? 0 : _queue_->front + 1; \
_queue_->count--; \
\
return true; \
} \
\
FMOD bool PFX##_enqueue_if(SNAME *_queue_, V element, bool condition) \
{ \
if (condition) \
return PFX##_enqueue(_queue_, element); \
\
return false; \
} \
\
FMOD bool PFX##_dequeue_if(SNAME *_queue_, bool condition) \
{ \
if (condition) \
return PFX##_dequeue(_queue_); \
\
return false; \
} \
\
FMOD V PFX##_peek(SNAME *_queue_) \
{ \
if (PFX##_empty(_queue_)) \
return PFX##_impl_default_value(); \
\
return _queue_->buffer[_queue_->front]; \
} \
\
FMOD bool PFX##_contains(SNAME *_queue_, V element, int (*comparator)(V, V)) \
{ \
for (size_t i = _queue_->front, j = 0; j < _queue_->count; i = (i + 1) % _queue_->count, j++) \
{ \
if (comparator(_queue_->buffer[i], element) == 0) \
return true; \
} \
\
return false; \
} \
\
FMOD bool PFX##_empty(SNAME *_queue_) \
{ \
return _queue_->count == 0; \
} \
\
FMOD bool PFX##_full(SNAME *_queue_) \
{ \
return _queue_->count >= SIZE; \
} \
\
FMOD size_t PFX##_count(SNAME *_queue_) \
{ \
return _queue_->count; \
} \
\
FMOD size_t PFX##_capacity(void) \
{ \
return SIZE; \
} \
\
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \
{ \
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) \
{ \
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->front; \
iter->index = 0; \
iter->start = true; \
iter->end = PFX##_empty(iter->target); \
} \
\
FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
iter->cursor = 0; \
else \
iter->cursor = (iter->target->rear == 0) ? SIZE - 1 : iter->target->rear - 1; \
\
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->index == iter->target->count - 1) \
iter->end = true; \
else \
{ \
iter->cursor = (iter->cursor + 1) % (SIZE); \
iter->index++; \
} \
\
return true; \
} \
\
FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \
{ \
if (iter->start) \
return false; \
\
iter->end = PFX##_empty(iter->target); \
\
if (iter->index == 0) \
iter->start = true; \
else \
{ \
iter->cursor = (iter->cursor == 0) ? SIZE - 1 : iter->cursor - 1; \
iter->index--; \
} \
\
return true; \
} \
\
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return 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->index; \
} \
\
static SNAME##_iter PFX##_impl_it_start(SNAME *_queue_) \
{ \
SNAME##_iter iter; \
\
PFX##_iter_init(&iter, _queue_); \
PFX##_iter_to_start(&iter); \
\
return iter; \
} \
\
static SNAME##_iter PFX##_impl_it_end(SNAME *_queue_) \
{ \
SNAME##_iter iter; \
\
PFX##_iter_init(&iter, _queue_); \
PFX##_iter_to_end(&iter); \
\
return iter; \
}
#endif /* CMC_SAC_QUEUE_H */
+327
View File
@@ -0,0 +1,327 @@
/**
* 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_); \
/* 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(_stack_->buffer)); \
\
_stack_->count = 0; \
} \
\
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_)) \
return 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)) \
return 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 */
+1870
View File
File diff suppressed because it is too large. Load diff
+9 -3
View File
@@ -1,5 +1,5 @@
/**
* @file for_each.h
* for_each.h
*
* Creation Date: 25/02/2019
*
@@ -8,6 +8,12 @@
*
*/
/**
* ForEach utility
*
* Read Documentation.md for more information
*/
#ifndef CMC_FOR_EACH
#define CMC_FOR_EACH
@@ -18,7 +24,7 @@
{ \
BODY; \
} \
} while (0);
} while (0)
#define FOR_EACH_REV(PFX, SNAME, TARGET, BODY) \
do \
@@ -27,6 +33,6 @@
{ \
BODY; \
} \
} while (0);
} while (0)
#endif /* CMC_FOR_EACH */
+170
View File
@@ -0,0 +1,170 @@
/**
* 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.
*
* You can customize the logging utility by accessing cmc_log_config and
* directly modifying its values to better suit your needs.
*/
/**
* 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
*
* 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 *cmc_log_names[] = {"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"};
#ifdef CMC_LOG_COLOR
static const char *cmc_log_color[] = {"\x1b[94m", "\x1b[36m", "\x1b[32m", "\x1b[33m", "\x1b[31m", "\x1b[35m"};
#endif
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 */
} cmc_log_config = {0, 0, true, true, NULL, true};
typedef enum cmc_log_type_e
{
LOG_TRACE = 1,
LOG_DEBUG = 2,
LOG_INFO = 3,
LOG_WARN = 4,
LOG_ERROR = 5,
LOG_FATAL = 6
} cmc_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(cmc_log_type log, const char *filename, const char *funcname, int line, const char *fmt, ...)
{
if (!cmc_log_config.enabled)
return;
if (cmc_log_config.tenabled)
{
if (cmc_log_config.tlevel < 0 && ((int)log * -1) < cmc_log_config.tlevel)
return;
else if (cmc_log_config.tlevel > 0 && (int)log < cmc_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';
#ifdef CMC_LOG_COLOR
fprintf(stderr,
"%s %s%5s\x1b[0m \x1b[90m%s at %s:%d:\x1b[0m ",
time, cmc_log_color[i], cmc_log_names[i], filename, funcname, line);
#else
fprintf(stderr,
"%s %5s %s at %s:%d: ",
time, cmc_log_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 (cmc_log_config.file && cmc_log_config.fenabled)
{
if (cmc_log_config.flevel < 0 && ((int)log * -1) < cmc_log_config.flevel)
return;
else if (cmc_log_config.flevel > 0 && (int)log < cmc_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(cmc_log_config.file, "%s %5s %s at %s:%d: ", time, cmc_log_names[i], filename, funcname, line);
va_list file_args;
va_start(file_args, fmt);
vfprintf(cmc_log_config.file, fmt, file_args);
va_end(file_args);
fprintf(cmc_log_config.file, "\n");
fflush(cmc_log_config.file);
}
}
#endif /* CMC_LOG_H */
+176
View File
@@ -0,0 +1,176 @@
/**
* test.h
*
* Creation Date: 26/06/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
/**
* Simple Unit Test Utility
*
* CMC_CREATE_UNIT
* Create a UnitTest
* Parameters:
* - UNAME : UnitTest name (const char *)
* - VERBOSE : Print PASSED / FAILED messages if true (bool)
* - BODY : Body containing all tests related to this UnitTest
*
* CMC_CREATE_TEST
* Create a Test inside a UnitTest.
* Parameters:
* - TNAME : Test name (const char *)
* - BODY : Block of code containing a specific test
* Inside the BODY use the following macros:
* - CMC_TEST_PASS
* Pass current test.
* - CMC_TEST_FAIL
* Fail current test.
* - CMC_TEST_PASS_ELSE_FAIL
* If given expression is true, pass current test, else fail.
* - CMC_TEST_ABORT
* Abort current unit test and displays error message. All tests
* after the abort won't be called.
* All of these macros can only be called once per test.
*
* CMC_TEST_COLOR
* Define this macro to allow colored output.
*/
#ifndef CMC_TEST_H
#define CMC_TEST_H
#include "timer.h"
#include <inttypes.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef CMC_TEST_COLOR
static const char *cmc_test_color[] = {"\x1b[32m", "\x1b[31m", "\x1b[35m"};
#endif
typedef struct cmc_test_info_s
{
uintmax_t total;
uintmax_t passed;
uintmax_t failed;
bool aborted;
bool verbose;
} cmc_test_info;
/* Logging function */
static void cmc_test_log(const char *unit_name, const char *current_test, bool aborted, bool passed)
{
if (aborted)
{
#ifdef CMC_TEST_COLOR
printf("UNIT_TEST %s %sABORTED\x1b[0m AT %s\n",
unit_name,
cmc_test_color[2],
current_test);
#else
printf("UNIT_TEST %s ABORTED at %s\n", unit_name, current_test);
#endif
}
else
{
#ifdef CMC_TEST_COLOR
printf("Test from %s %s%7s\x1b[0m %s\n",
unit_name,
passed ? cmc_test_color[0] : cmc_test_color[1],
passed ? "PASSED" : "FAILED",
current_test);
#else
printf("Test from %s %7s %s\n", unit_name, passed ? "PASSED" : "FAILED", current_test);
#endif
}
}
#define CMC_CREATE_UNIT(UNAME, VERBOSE, BODY) \
void UNAME(void) \
{ \
const char *unit_name = #UNAME; \
const char *current_test = NULL; \
\
cmc_test_info tinfo = {0}; \
timer_t timer = {0}; \
\
tinfo.verbose = VERBOSE; \
\
/* Tests */ \
timer_start(timer); \
BODY; \
timer_stop(timer); \
timer_calc(timer); \
\
unittest_abort: \
if (tinfo.aborted) \
{ \
cmc_test_log(unit_name, current_test, true, false); \
} \
\
printf("+--------------------------------------------------+\n"); \
printf("| Unit Test Report : %-30s|\n", unit_name); \
printf("| TOTAL : %10" PRIuMAX " |\n", tinfo.total); \
printf("| PASSED : %10" PRIuMAX " |\n", tinfo.passed); \
printf("| FAILED : %10" PRIuMAX " |\n", tinfo.failed); \
printf("| |\n"); \
printf("| Total Unit Test Runtime : %9.0f milliseconds |\n", timer.result); \
printf("+--------------------------------------------------+\n"); \
}
#define CMC_CREATE_TEST(TNAME, BODY) \
do \
{ \
current_test = #TNAME; \
\
tinfo.total += 1; \
\
BODY; \
\
} while (0)
#define CMC_TEST_PASS() \
do \
{ \
tinfo.passed += 1; \
if (tinfo.verbose) \
cmc_test_log(unit_name, current_test, false, true); \
\
} while (0)
#define CMC_TEST_FAIL() \
do \
{ \
tinfo.failed += 1; \
if (tinfo.verbose) \
cmc_test_log(unit_name, current_test, false, false); \
\
} while (0)
#define CMC_TEST_PASS_ELSE_FAIL(EXPRESSION) \
do \
{ \
if (EXPRESSION) \
CMC_TEST_PASS(); \
else \
CMC_TEST_FAIL(); \
\
} while (0)
#define CMC_TEST_ABORT() \
do \
{ \
\
tinfo.aborted = true; \
tinfo.total -= 1; \
goto unittest_abort; \
\
} while (0)
#endif /* CMC_TEST_H */
+47
View File
@@ -0,0 +1,47 @@
/**
* timer.h
*
* Creation Date: 12/04/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
/* Simple timer macros utility */
#ifndef CMC_TIMER_H
#define CMC_TIMER_H
#include <time.h>
typedef struct timer_s
{
clock_t start;
clock_t stop;
double result;
} timer_t;
#define timer_start(timer) \
do \
{ \
(timer).start = clock(); \
\
} while (0)
#define timer_stop(timer) \
do \
{ \
(timer).stop = clock(); \
\
} while (0)
#define timer_calc(timer) \
do \
{ \
timer_t *t = &(timer); \
t->result = (double)(t->stop - t->start) * 1000.0 / CLOCKS_PER_SEC; \
\
} while (0)
#endif /* CMC_TIMER_H */
+17
View File
@@ -0,0 +1,17 @@
CC = gcc
CFLAGS = -std=c11 -Wall -Wextra
CFLAGS += -Wno-unused-function -Wno-unused-paramter -Wno-unused-variable -Wno-unused-label
main:
$(CC) foreach.c -o foreach $(CFLAGS)
./foreach
$(CC) iterators.c -o iterators $(CFLAGS)
./iterators
$(CC) contains.c -o contains $(CFLAGS)
./contains
$(CC) types.c -o types $(CFLAGS)
./types
$(CC) -c ./sep/sep.c -o ./sep/sep.o $(CFLAGS)
$(CC) -c ./sep/main.c -o ./sep/main.o $(CFLAGS)
$(CC) ./sep/sep.o ./sep/main.o -o ./sep/sep
./sep/sep
+8
View File
@@ -0,0 +1,8 @@
# Tests
* `main` - Unit tests for the main C Macro Collections library with code coverage;
* `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)
{
+31 -31
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)
{
@@ -72,45 +72,45 @@ int main(void)
FOR_EACH(d, deque, d, {
sum3 += d_iter_value(&iter);
})
});
FOR_EACH(hm, hmap, hm, {
sum10 += hm_iter_key(&iter);
sum11 += hm_iter_value(&iter);
})
});
FOR_EACH(hs, hset, hs, {
sum9 += hs_iter_value(&iter);
})
});
FOR_EACH(h, heap, h, {
sum5 += h_iter_value(&iter);
})
});
FOR_EACH(ll, linked, ll, {
sum4 += ll_iter_value(&iter);
})
});
FOR_EACH(l, list, l, {
sum0 += l_iter_value(&iter);
})
});
FOR_EACH(q, queue, q, {
sum2 += q_iter_value(&iter);
})
});
FOR_EACH(s, stack, s, {
sum1 += s_iter_value(&iter);
})
});
FOR_EACH(tm, tmap, tm, {
sum7 += tm_iter_key(&iter);
sum8 += tm_iter_value(&iter);
})
});
FOR_EACH(ts, tset, ts, {
sum6 += ts_iter_value(&iter);
})
});
printf("\n-------------------- FOR_EACH --------------------\n");
if (sum3 == 50005000)
@@ -161,45 +161,45 @@ int main(void)
FOR_EACH_REV(d, deque, d, {
sum3 += d_iter_value(&iter);
})
});
FOR_EACH_REV(hm, hmap, hm, {
sum10 += hm_iter_key(&iter);
sum11 += hm_iter_value(&iter);
})
});
FOR_EACH_REV(hs, hset, hs, {
sum9 += hs_iter_value(&iter);
})
});
FOR_EACH_REV(h, heap, h, {
sum5 += h_iter_value(&iter);
})
});
FOR_EACH_REV(ll, linked, ll, {
sum4 += ll_iter_value(&iter);
})
});
FOR_EACH_REV(l, list, l, {
sum0 += l_iter_value(&iter);
})
});
FOR_EACH_REV(q, queue, q, {
sum2 += q_iter_value(&iter);
})
});
FOR_EACH_REV(s, stack, s, {
sum1 += s_iter_value(&iter);
})
});
FOR_EACH_REV(tm, tmap, tm, {
sum7 += tm_iter_key(&iter);
sum8 += tm_iter_value(&iter);
})
});
FOR_EACH_REV(ts, tset, ts, {
sum6 += ts_iter_value(&iter);
})
});
printf("-------------------- FOR_EACH_REV --------------------\n");
if (sum3 == 50005000)
+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) \
+16
View File
@@ -0,0 +1,16 @@
CC = gcc
CFLAGS = -std=c11 -Wall -Wextra
CFLAGS += -Wno-unused-function -Wno-unused-parameter -Wno-unused-variable -Wno-unused-label
CVFLAGS = --coverage -O0
INCLUDE = ../../src/
main:
$(CC) main.c -o main $(CFLAGS) $(CVFLAGS) -I $(INCLUDE)
./main
gcov ./main.c
dev:
$(CC) main.c -o main $(CFLAGS) $(CVFLAGS) -I $(INCLUDE)
./main
gcov ./main.c -n
rm *.gcda *.gcno *.exe
+7
View File
@@ -0,0 +1,7 @@
# main
Tests for the main C Macro Collections library. In order to provide a good code coverage, all macros have been expanded and added to `src/*.c`.
* `src` - Since gcov fails to detect code that was expanded by macro, all collections where manually expanded and dumped into their respective source files;
* `unt` - Unit Tests;
* `main.c` - Where all tests are compiled together and called by main().
+26
View File
@@ -0,0 +1,26 @@
#include "unt/deque.c"
#include "unt/hashmap.c"
#include "unt/hashset.c"
#include "unt/heap.c"
#include "unt/linkedlist.c"
#include "unt/list.c"
#include "unt/queue.c"
#include "unt/stack.c"
#include "unt/treemap.c"
#include "unt/treeset.c"
int main(void)
{
deque_test();
hashmap_test();
hashset_test();
heap_test();
linkedlist_test();
list_test();
queue_test();
stack_test();
treemap_test();
treeset_test();
return 0;
}
+291
View File
@@ -0,0 +1,291 @@
#include "cmc/deque.h"
typedef struct deque_s
{
size_t *buffer;
size_t capacity;
size_t count;
size_t front;
size_t back;
struct deque_iter_s (*it_start)(struct deque_s *);
struct deque_iter_s (*it_end)(struct deque_s *);
} deque, *deque_ptr;
typedef struct deque_iter_s
{
struct deque_s *target;
size_t cursor;
size_t index;
bool start;
bool end;
} deque_iter, *deque_iter_ptr;
deque *d_new(size_t capacity);
void d_clear(deque *_deque_);
void d_free(deque *_deque_);
bool d_push_front(deque *_deque_, size_t element);
bool d_push_back(deque *_deque_, size_t element);
bool d_pop_front(deque *_deque_);
bool d_pop_back(deque *_deque_);
bool d_push_front_if(deque *_deque_, size_t element, bool condition);
bool d_push_back_if(deque *_deque_, size_t element, bool condition);
bool d_pop_front_if(deque *_deque_, bool condition);
bool d_pop_back_if(deque *_deque_, bool condition);
size_t d_front(deque *_deque_);
size_t d_back(deque *_deque_);
bool d_contains(deque *_deque_, size_t element, int (*comparator)(size_t, size_t));
bool d_empty(deque *_deque_);
bool d_full(deque *_deque_);
size_t d_count(deque *_deque_);
size_t d_capacity(deque *_deque_);
deque_iter *d_iter_new(deque *target);
void d_iter_free(deque_iter *iter);
void d_iter_init(deque_iter *iter, deque *target);
bool d_iter_start(deque_iter *iter);
bool d_iter_end(deque_iter *iter);
void d_iter_to_start(deque_iter *iter);
void d_iter_to_end(deque_iter *iter);
bool d_iter_next(deque_iter *iter);
bool d_iter_prev(deque_iter *iter);
size_t d_iter_value(deque_iter *iter);
size_t *d_iter_rvalue(deque_iter *iter);
size_t d_iter_index(deque_iter *iter);
static inline size_t d_impl_default_value(void)
{
size_t _empty_value_;
memset(&_empty_value_, 0, sizeof(size_t));
return _empty_value_;
}
static bool d_impl_grow(deque *_deque_);
static deque_iter d_impl_it_start(deque *_deque_);
static deque_iter d_impl_it_end(deque *_deque_);
deque *d_new(size_t capacity)
{
if (capacity < 1)
return NULL;
deque *_deque_ = malloc(sizeof(deque));
if (!_deque_)
return NULL;
_deque_->buffer = malloc(sizeof(size_t) * capacity);
if (!_deque_->buffer)
{
free(_deque_);
return NULL;
}
memset(_deque_->buffer, 0, sizeof(size_t) * capacity);
_deque_->capacity = capacity;
_deque_->count = 0;
_deque_->front = 0;
_deque_->back = 0;
_deque_->it_start = d_impl_it_start;
_deque_->it_end = d_impl_it_end;
return _deque_;
}
void d_clear(deque *_deque_)
{
memset(_deque_->buffer, 0, sizeof(size_t) * _deque_->capacity);
_deque_->count = 0;
_deque_->front = 0;
_deque_->back = 0;
}
void d_free(deque *_deque_)
{
free(_deque_->buffer);
free(_deque_);
}
bool d_push_front(deque *_deque_, size_t element)
{
if (d_full(_deque_))
{
if (!d_impl_grow(_deque_))
return false;
}
_deque_->front = (_deque_->front == 0) ? _deque_->capacity - 1 : _deque_->front - 1;
_deque_->buffer[_deque_->front] = element;
_deque_->count++;
return true;
}
bool d_push_back(deque *_deque_, size_t element)
{
if (d_full(_deque_))
{
if (!d_impl_grow(_deque_))
return false;
}
_deque_->buffer[_deque_->back] = element;
_deque_->back = (_deque_->back == _deque_->capacity - 1) ? 0 : _deque_->back + 1;
_deque_->count++;
return true;
}
bool d_pop_front(deque *_deque_)
{
if (d_empty(_deque_))
return false;
_deque_->buffer[_deque_->front] = d_impl_default_value();
_deque_->front = (_deque_->front == _deque_->capacity - 1) ? 0 : _deque_->front + 1;
_deque_->count--;
return true;
}
bool d_pop_back(deque *_deque_)
{
if (d_empty(_deque_))
return false;
_deque_->back = (_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1;
_deque_->buffer[_deque_->back] = d_impl_default_value();
_deque_->count--;
return true;
}
bool d_push_front_if(deque *_deque_, size_t element, bool condition)
{
if (condition)
return d_push_front(_deque_, element);
return false;
}
bool d_push_back_if(deque *_deque_, size_t element, bool condition)
{
if (condition)
return d_push_back(_deque_, element);
return false;
}
bool d_pop_front_if(deque *_deque_, bool condition)
{
if (condition)
return d_pop_front(_deque_);
return false;
}
bool d_pop_back_if(deque *_deque_, bool condition)
{
if (condition)
return d_pop_back(_deque_);
return false;
}
size_t d_front(deque *_deque_)
{
if (d_empty(_deque_))
return d_impl_default_value();
return _deque_->buffer[_deque_->front];
}
size_t d_back(deque *_deque_)
{
if (d_empty(_deque_))
return d_impl_default_value();
return _deque_->buffer[(_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1];
}
bool d_contains(deque *_deque_, size_t element, int (*comparator)(size_t, size_t))
{
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;
}
bool d_empty(deque *_deque_) { return _deque_->count == 0; }
bool d_full(deque *_deque_) { return _deque_->count >= _deque_->capacity; }
size_t d_count(deque *_deque_) { return _deque_->count; }
size_t d_capacity(deque *_deque_) { return _deque_->capacity; }
deque_iter *d_iter_new(deque *target)
{
deque_iter *iter = malloc(sizeof(deque_iter));
if (!iter)
return NULL;
d_iter_init(iter, target);
return iter;
}
void d_iter_free(deque_iter *iter) { free(iter); }
void d_iter_init(deque_iter *iter, deque *target)
{
iter->target = target;
iter->cursor = target->front;
iter->index = 0;
iter->start = true;
iter->end = d_empty(target);
}
bool d_iter_start(deque_iter *iter) { return d_empty(iter->target) || iter->start; }
bool d_iter_end(deque_iter *iter) { return d_empty(iter->target) || iter->end; }
void d_iter_to_start(deque_iter *iter)
{
iter->cursor = iter->target->front;
iter->index = 0;
iter->start = true;
iter->end = d_empty(iter->target);
}
void d_iter_to_end(deque_iter *iter)
{
if (d_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 = d_empty(iter->target);
iter->end = true;
}
bool d_iter_next(deque_iter *iter)
{
if (iter->end)
return false;
iter->start = d_empty(iter->target);
if (iter->index == iter->target->count - 1)
iter->end = true;
else
{
iter->cursor = (iter->cursor + 1) % (iter->target->capacity);
iter->index++;
}
return true;
}
bool d_iter_prev(deque_iter *iter)
{
if (iter->start)
return false;
iter->end = d_empty(iter->target);
if (iter->index == 0)
iter->start = true;
else
{
iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1;
iter->index--;
}
return true;
}
size_t d_iter_value(deque_iter *iter)
{
if (d_empty(iter->target))
return d_impl_default_value();
return iter->target->buffer[iter->cursor];
}
size_t *d_iter_rvalue(deque_iter *iter)
{
if (d_empty(iter->target))
return NULL;
return &(iter->target->buffer[iter->cursor]);
}
size_t d_iter_index(deque_iter *iter) { return iter->index; }
static bool d_impl_grow(deque *_deque_)
{
size_t new_capacity = _deque_->capacity * 2;
size_t *new_buffer = malloc(sizeof(size_t) * new_capacity);
if (!new_buffer)
return false;
for (size_t i = _deque_->front, j = 0; j < _deque_->count; i = (i + 1) % _deque_->capacity, j++)
{
new_buffer[j] = _deque_->buffer[i];
}
free(_deque_->buffer);
_deque_->buffer = new_buffer;
_deque_->capacity = new_capacity;
_deque_->front = 0;
_deque_->back = _deque_->count;
return true;
}
static deque_iter d_impl_it_start(deque *_deque_)
{
deque_iter iter;
d_iter_init(&iter, _deque_);
return iter;
}
static deque_iter d_impl_it_end(deque *_deque_)
{
deque_iter iter;
d_iter_init(&iter, _deque_);
d_iter_to_end(&iter);
return iter;
}
+425
View File
@@ -0,0 +1,425 @@
#include "cmc/hashmap.h"
typedef struct hashmap_s
{
struct hashmap_entry_s *buffer;
size_t capacity;
size_t count;
double load;
int (*cmp)(size_t, size_t);
size_t (*hash)(size_t);
struct hashmap_iter_s (*it_start)(struct hashmap_s *);
struct hashmap_iter_s (*it_end)(struct hashmap_s *);
} hashmap, *hashmap_ptr;
typedef struct hashmap_entry_s
{
size_t key;
size_t value;
size_t dist;
enum EntryState_e state;
} hashmap_entry, *hashmap_entry_ptr;
typedef struct hashmap_iter_s
{
struct hashmap_s *target;
size_t cursor;
size_t index;
size_t first;
size_t last;
bool start;
bool end;
} hashmap_iter, *hashmap_iter_ptr;
hashmap *hm_new(size_t capacity, double load, int (*compare)(size_t, size_t), size_t (*hash)(size_t));
void hm_clear(hashmap *_map_);
void hm_free(hashmap *_map_);
bool hm_insert(hashmap *_map_, size_t key, size_t value);
bool hm_remove(hashmap *_map_, size_t key, size_t *value);
bool hm_insert_if(hashmap *_map_, size_t key, size_t value, bool condition);
bool hm_remove_if(hashmap *_map_, size_t key, size_t *value, bool condition);
bool hm_max(hashmap *_map_, size_t *key, size_t *value);
bool hm_min(hashmap *_map_, size_t *key, size_t *value);
size_t hm_get(hashmap *_map_, size_t key);
size_t *hm_get_ref(hashmap *_map_, size_t key);
bool hm_contains(hashmap *_map_, size_t key);
bool hm_empty(hashmap *_map_);
size_t hm_count(hashmap *_map_);
size_t hm_capacity(hashmap *_map_);
hashmap_iter *hm_iter_new(hashmap *target);
void hm_iter_free(hashmap_iter *iter);
void hm_iter_init(hashmap_iter *iter, hashmap *target);
bool hm_iter_start(hashmap_iter *iter);
bool hm_iter_end(hashmap_iter *iter);
void hm_iter_to_start(hashmap_iter *iter);
void hm_iter_to_end(hashmap_iter *iter);
bool hm_iter_next(hashmap_iter *iter);
bool hm_iter_prev(hashmap_iter *iter);
size_t hm_iter_key(hashmap_iter *iter);
size_t hm_iter_value(hashmap_iter *iter);
size_t *hm_iter_rvalue(hashmap_iter *iter);
size_t hm_iter_index(hashmap_iter *iter);
static inline size_t hm_impl_default_key(void)
{
size_t _empty_key_;
memset(&_empty_key_, 0, sizeof(size_t));
return _empty_key_;
}
static inline size_t hm_impl_default_value(void)
{
size_t _empty_value_;
memset(&_empty_value_, 0, sizeof(size_t));
return _empty_value_;
}
static bool hm_impl_grow(hashmap *_map_);
static hashmap_entry *hm_impl_get_entry(hashmap *_map_, size_t key);
static size_t hm_impl_calculate_size(size_t required);
static hashmap_iter hm_impl_it_start(hashmap *_map_);
static hashmap_iter hm_impl_it_end(hashmap *_map_);
hashmap *hm_new(size_t capacity, double load, int (*compare)(size_t, size_t), size_t (*hash)(size_t))
{
if (capacity == 0 || load <= 0 || load >= 1)
return NULL;
size_t real_capacity = hm_impl_calculate_size(capacity / load);
hashmap *_map_ = malloc(sizeof(hashmap));
if (!_map_)
return NULL;
_map_->buffer = malloc(sizeof(hashmap_entry) * real_capacity);
if (!_map_->buffer)
{
free(_map_);
return NULL;
}
memset(_map_->buffer, 0, sizeof(hashmap_entry) * real_capacity);
_map_->count = 0;
_map_->capacity = real_capacity;
_map_->load = load;
_map_->cmp = compare;
_map_->hash = hash;
_map_->it_start = hm_impl_it_start;
_map_->it_end = hm_impl_it_end;
return _map_;
}
void hm_clear(hashmap *_map_)
{
memset(_map_->buffer, 0, sizeof(hashmap_entry) * _map_->capacity);
_map_->count = 0;
}
void hm_free(hashmap *_map_)
{
free(_map_->buffer);
free(_map_);
}
bool hm_insert(hashmap *_map_, size_t key, size_t value)
{
if ((double)_map_->capacity * _map_->load <= (double)_map_->count)
{
if (!hm_impl_grow(_map_))
return false;
}
size_t hash = _map_->hash(key);
size_t original_pos = hash % _map_->capacity;
size_t pos = original_pos;
hashmap_entry *target = &(_map_->buffer[pos]);
if (hm_impl_get_entry(_map_, key) != NULL)
return false;
if (target->state == ES_EMPTY || target->state == ES_DELETED)
{
target->key = key;
target->value = value;
target->dist = original_pos - pos;
target->state = ES_FILLED;
}
else
{
while (true)
{
pos++;
target = &(_map_->buffer[pos % _map_->capacity]);
if (target->state == ES_EMPTY || target->state == ES_DELETED)
{
target->key = key;
target->value = value;
target->dist = pos - original_pos;
target->state = ES_FILLED;
break;
}
else if (target->dist < original_pos - pos)
{
size_t tmp_k = target->key;
size_t tmp_v = target->value;
size_t tmp_dist = target->dist;
target->key = key;
target->value = value;
target->dist = pos - original_pos;
key = tmp_k;
value = tmp_v;
original_pos = pos - tmp_dist;
}
}
}
_map_->count++;
return true;
}
bool hm_remove(hashmap *_map_, size_t key, size_t *value)
{
hashmap_entry *result = hm_impl_get_entry(_map_, key);
if (result == NULL)
return false;
*value = result->value;
result->key = hm_impl_default_key();
result->value = hm_impl_default_value();
result->dist = 0;
result->state = ES_DELETED;
_map_->count--;
return true;
}
bool hm_insert_if(hashmap *_map_, size_t key, size_t value, bool condition)
{
if (condition)
return hm_insert(_map_, key, value);
return false;
}
bool hm_remove_if(hashmap *_map_, size_t key, size_t *value, bool condition)
{
if (condition)
return hm_remove(_map_, key, value);
return false;
}
bool hm_max(hashmap *_map_, size_t *key, size_t *value)
{
if (hm_empty(_map_))
return false;
hashmap_iter iter;
for (hm_iter_init(&iter, _map_); !hm_iter_end(&iter); hm_iter_next(&iter))
{
size_t result_key = hm_iter_key(&iter);
size_t result_value = hm_iter_value(&iter);
size_t index = hm_iter_index(&iter);
if (index == 0)
{
*key = result_key;
*value = result_value;
}
else if (_map_->cmp(result_key, *key) > 0)
{
*key = result_key;
*value = result_value;
}
}
return true;
}
bool hm_min(hashmap *_map_, size_t *key, size_t *value)
{
if (hm_empty(_map_))
return false;
hashmap_iter iter;
for (hm_iter_init(&iter, _map_); !hm_iter_end(&iter); hm_iter_next(&iter))
{
size_t result_key = hm_iter_key(&iter);
size_t result_value = hm_iter_value(&iter);
size_t index = hm_iter_index(&iter);
if (index == 0)
{
*key = result_key;
*value = result_value;
}
else if (_map_->cmp(result_key, *key) < 0)
{
*key = result_key;
*value = result_value;
}
}
return true;
}
size_t hm_get(hashmap *_map_, size_t key)
{
hashmap_entry *entry = hm_impl_get_entry(_map_, key);
if (!entry)
return hm_impl_default_value();
return entry->value;
}
size_t *hm_get_ref(hashmap *_map_, size_t key)
{
hashmap_entry *entry = hm_impl_get_entry(_map_, key);
if (!entry)
return NULL;
return &(entry->value);
}
bool hm_contains(hashmap *_map_, size_t key) { return hm_impl_get_entry(_map_, key) != NULL; }
bool hm_empty(hashmap *_map_) { return _map_->count == 0; }
size_t hm_count(hashmap *_map_) { return _map_->count; }
size_t hm_capacity(hashmap *_map_) { return _map_->capacity; }
hashmap_iter *hm_iter_new(hashmap *target)
{
hashmap_iter *iter = malloc(sizeof(hashmap_iter));
if (!iter)
return NULL;
hm_iter_init(iter, target);
return iter;
}
void hm_iter_free(hashmap_iter *iter) { free(iter); }
void hm_iter_init(hashmap_iter *iter, hashmap *target)
{
iter->target = target;
iter->cursor = 0;
iter->index = 0;
iter->start = true;
iter->end = hm_empty(target);
if (!hm_empty(target))
{
for (size_t i = 0; i < target->capacity; i++)
{
if (target->buffer[i].state == ES_FILLED)
{
iter->first = i;
break;
}
}
iter->cursor = iter->first;
for (size_t i = target->capacity; i > 0; i--)
{
if (target->buffer[i - 1].state == ES_FILLED)
{
iter->last = i - 1;
break;
}
}
}
}
bool hm_iter_start(hashmap_iter *iter) { return hm_empty(iter->target) || iter->start; }
bool hm_iter_end(hashmap_iter *iter) { return hm_empty(iter->target) || iter->end; }
void hm_iter_to_start(hashmap_iter *iter)
{
iter->cursor = iter->first;
iter->index = 0;
iter->start = true;
iter->end = hm_empty(iter->target);
}
void hm_iter_to_end(hashmap_iter *iter)
{
iter->cursor = iter->last;
iter->index = iter->target->count - 1;
iter->start = hm_empty(iter->target);
iter->end = true;
}
bool hm_iter_next(hashmap_iter *iter)
{
if (iter->end)
return false;
hashmap_entry *scan = &(iter->target->buffer[iter->cursor]);
if (iter->cursor == iter->last)
{
iter->end = true;
return false;
}
iter->index++;
while (1)
{
iter->cursor++;
scan = &(iter->target->buffer[iter->cursor]);
if (scan->state == ES_FILLED)
break;
}
iter->start = hm_empty(iter->target);
return true;
}
bool hm_iter_prev(hashmap_iter *iter)
{
if (iter->start)
return false;
hashmap_entry *scan = &(iter->target->buffer[iter->cursor]);
if (iter->cursor == iter->first)
{
iter->start = true;
return false;
}
iter->index--;
while (1)
{
iter->cursor--;
scan = &(iter->target->buffer[iter->cursor]);
if (scan->state == ES_FILLED)
break;
}
iter->end = hm_empty(iter->target);
return true;
}
size_t hm_iter_key(hashmap_iter *iter)
{
if (hm_empty(iter->target))
return hm_impl_default_key();
return iter->target->buffer[iter->cursor].key;
}
size_t hm_iter_value(hashmap_iter *iter)
{
if (hm_empty(iter->target))
return hm_impl_default_value();
return iter->target->buffer[iter->cursor].value;
}
size_t *hm_iter_rvalue(hashmap_iter *iter)
{
if (hm_empty(iter->target))
return NULL;
return &(iter->target->buffer[iter->cursor].value);
}
size_t hm_iter_index(hashmap_iter *iter) { return iter->index; }
static bool hm_impl_grow(hashmap *_map_)
{
size_t new_size = hm_impl_calculate_size(_map_->capacity + _map_->capacity / 2);
hashmap *_new_map_ = hm_new(new_size, _map_->load, _map_->cmp, _map_->hash);
if (!_new_map_)
return false;
hashmap_iter iter;
for (hm_iter_init(&iter, _map_); !hm_iter_end(&iter); hm_iter_next(&iter))
{
size_t key = hm_iter_key(&iter);
size_t value = hm_iter_value(&iter);
hm_insert(_new_map_, key, value);
}
if (_map_->count != _new_map_->count)
{
hm_free(_new_map_);
return false;
}
hashmap_entry *tmp = _map_->buffer;
_map_->buffer = _new_map_->buffer;
_new_map_->buffer = tmp;
_map_->capacity = _new_map_->capacity;
hm_free(_new_map_);
return true;
}
static hashmap_entry *hm_impl_get_entry(hashmap *_map_, size_t key)
{
size_t hash = _map_->hash(key);
size_t pos = hash % _map_->capacity;
hashmap_entry *target = &(_map_->buffer[pos]);
while (target->state == ES_FILLED || target->state == ES_DELETED)
{
if (_map_->cmp(target->key, key) == 0)
return target;
pos++;
target = &(_map_->buffer[pos % _map_->capacity]);
}
return NULL;
}
static size_t hm_impl_calculate_size(size_t required)
{
const size_t count = sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]);
if (cmc_hashtable_primes[count - 1] < required)
return required;
size_t i = 0;
while (cmc_hashtable_primes[i] < required)
i++;
return cmc_hashtable_primes[i];
}
static hashmap_iter hm_impl_it_start(hashmap *_map_)
{
hashmap_iter iter;
hm_iter_init(&iter, _map_);
return iter;
}
static hashmap_iter hm_impl_it_end(hashmap *_map_)
{
hashmap_iter iter;
hm_iter_init(&iter, _map_);
hm_iter_to_end(&iter);
return iter;
}
+499
View File
@@ -0,0 +1,499 @@
#include "cmc/hashset.h"
typedef struct hashset_s
{
struct hashset_entry_s *buffer;
size_t capacity;
size_t count;
double load;
int (*cmp)(size_t, size_t);
size_t (*hash)(size_t);
struct hashset_iter_s (*it_start)(struct hashset_s *);
struct hashset_iter_s (*it_end)(struct hashset_s *);
} hashset, *hashset_ptr;
typedef struct hashset_entry_s
{
size_t value;
size_t dist;
enum EntryState_e state;
} hashset_entry, *hashset_entry_ptr;
typedef struct hashset_iter_s
{
struct hashset_s *target;
size_t cursor;
size_t index;
size_t first;
size_t last;
bool start;
bool end;
} hashset_iter, *hashset_iter_ptr;
hashset *hs_new(size_t capacity, double load, int (*compare)(size_t, size_t), size_t (*hash)(size_t));
void hs_clear(hashset *_set_);
void hs_free(hashset *_set_);
bool hs_insert(hashset *_set_, size_t element);
bool hs_remove(hashset *_set_, size_t element);
bool hs_insert_if(hashset *_set_, size_t element, bool condition);
bool hs_remove_if(hashset *_set_, size_t element, bool condition);
bool hs_max(hashset *_set_, size_t *value);
bool hs_min(hashset *_set_, size_t *value);
bool hs_contains(hashset *_set_, size_t element);
bool hs_empty(hashset *_set_);
size_t hs_count(hashset *_set_);
size_t hs_capacity(hashset *_set_);
hashset *hs_union(hashset *_set1_, hashset *_set2_);
hashset *hs_intersection(hashset *_set1_, hashset *_set2_);
hashset *hs_difference(hashset *_set1_, hashset *_set2_);
hashset *hs_symmetric_difference(hashset *_set1_, hashset *_set2_);
bool hs_is_subset(hashset *_set1_, hashset *_set2_);
bool hs_is_superset(hashset *_set1_, hashset *_set2_);
bool hs_is_proper_subset(hashset *_set1_, hashset *_set2_);
bool hs_is_proper_superset(hashset *_set1_, hashset *_set2_);
bool hs_is_disjointset(hashset *_set1_, hashset *_set2_);
hashset_iter *hs_iter_new(hashset *target);
void hs_iter_free(hashset_iter *iter);
void hs_iter_init(hashset_iter *iter, hashset *target);
bool hs_iter_start(hashset_iter *iter);
bool hs_iter_end(hashset_iter *iter);
void hs_iter_to_start(hashset_iter *iter);
void hs_iter_to_end(hashset_iter *iter);
bool hs_iter_next(hashset_iter *iter);
bool hs_iter_prev(hashset_iter *iter);
size_t hs_iter_value(hashset_iter *iter);
size_t hs_iter_index(hashset_iter *iter);
static inline size_t hs_impl_default_value(void)
{
size_t _empty_value_;
memset(&_empty_value_, 0, sizeof(size_t));
return _empty_value_;
}
static bool hs_impl_grow(hashset *_set_);
static hashset_entry *hs_impl_get_entry(hashset *_set_, size_t element);
static size_t hs_impl_calculate_size(size_t required);
static hashset_iter hs_impl_it_start(hashset *_set_);
static hashset_iter hs_impl_it_end(hashset *_set_);
hashset *hs_new(size_t capacity, double load, int (*compare)(size_t, size_t), size_t (*hash)(size_t))
{
if (capacity == 0 || load <= 0 || load >= 1)
return NULL;
size_t real_capacity = hs_impl_calculate_size(capacity / load);
hashset *_set_ = malloc(sizeof(hashset));
if (!_set_)
return NULL;
_set_->buffer = malloc(sizeof(hashset_entry) * real_capacity);
if (!_set_->buffer)
{
free(_set_);
return NULL;
}
memset(_set_->buffer, 0, sizeof(hashset_entry) * real_capacity);
_set_->count = 0;
_set_->capacity = real_capacity;
_set_->load = load;
_set_->cmp = compare;
_set_->hash = hash;
_set_->it_start = hs_impl_it_start;
_set_->it_end = hs_impl_it_end;
return _set_;
}
void hs_clear(hashset *_set_)
{
memset(_set_->buffer, 0, sizeof(hashset_entry) * _set_->capacity);
_set_->count = 0;
}
void hs_free(hashset *_set_)
{
free(_set_->buffer);
free(_set_);
}
bool hs_insert(hashset *_set_, size_t element)
{
if ((double)_set_->capacity * _set_->load <= (double)_set_->count)
{
if (!hs_impl_grow(_set_))
return false;
}
size_t hash = _set_->hash(element);
size_t original_pos = hash % _set_->capacity;
size_t pos = original_pos;
hashset_entry *target = &(_set_->buffer[pos]);
if (hs_impl_get_entry(_set_, element) != NULL)
return false;
if (target->state == ES_EMPTY || target->state == ES_DELETED)
{
target->value = element;
target->dist = pos - original_pos;
target->state = ES_FILLED;
}
else
{
while (true)
{
pos++;
target = &(_set_->buffer[pos % _set_->capacity]);
if (target->state == ES_EMPTY || target->state == ES_DELETED)
{
target->value = element;
target->dist = pos - original_pos;
target->state = ES_FILLED;
break;
}
else if (target->dist < pos - original_pos)
{
size_t tmp = target->value;
size_t tmp_dist = target->dist;
target->value = element;
target->dist = pos - original_pos;
element = tmp;
original_pos = pos - tmp_dist;
}
}
}
_set_->count++;
return true;
}
bool hs_remove(hashset *_set_, size_t element)
{
hashset_entry *result = hs_impl_get_entry(_set_, element);
if (result == NULL)
return false;
result->value = hs_impl_default_value();
result->dist = 0;
result->state = ES_DELETED;
_set_->count--;
return true;
}
bool hs_insert_if(hashset *_set_, size_t element, bool condition)
{
if (condition)
return hs_insert(_set_, element);
return false;
}
bool hs_remove_if(hashset *_set_, size_t element, bool condition)
{
if (condition)
return hs_remove(_set_, element);
return false;
}
bool hs_max(hashset *_set_, size_t *value)
{
if (hs_empty(_set_))
return false;
hashset_iter iter;
for (hs_iter_init(&iter, _set_); !hs_iter_end(&iter); hs_iter_next(&iter))
{
size_t result = hs_iter_value(&iter);
size_t index = hs_iter_index(&iter);
if (index == 0)
*value = result;
else if (_set_->cmp(result, *value) > 0)
*value = result;
}
return true;
}
bool hs_min(hashset *_set_, size_t *value)
{
if (hs_empty(_set_))
return false;
hashset_iter iter;
for (hs_iter_init(&iter, _set_); !hs_iter_end(&iter); hs_iter_next(&iter))
{
size_t result = hs_iter_value(&iter);
size_t index = hs_iter_index(&iter);
if (index == 0)
*value = result;
else if (_set_->cmp(result, *value) < 0)
*value = result;
}
return true;
}
bool hs_contains(hashset *_set_, size_t element) { return hs_impl_get_entry(_set_, element) != NULL; }
bool hs_empty(hashset *_set_) { return _set_->count == 0; }
size_t hs_count(hashset *_set_) { return _set_->count; }
size_t hs_capacity(hashset *_set_) { return _set_->capacity; }
hashset *hs_union(hashset *_set1_, hashset *_set2_)
{
hashset *_set_r_ = hs_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash);
if (!_set_r_)
return false;
hashset_iter iter1, iter2;
hs_iter_init(&iter1, _set1_);
hs_iter_init(&iter2, _set2_);
for (hs_iter_to_start(&iter1); !hs_iter_end(&iter1); hs_iter_next(&iter1))
{
hs_insert(_set_r_, hs_iter_value(&iter1));
}
for (hs_iter_to_start(&iter2); !hs_iter_end(&iter2); hs_iter_next(&iter2))
{
hs_insert(_set_r_, hs_iter_value(&iter2));
}
return _set_r_;
}
hashset *hs_intersection(hashset *_set1_, hashset *_set2_)
{
hashset *_set_r_ = hs_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash);
if (!_set_r_)
return false;
hashset *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_;
hashset *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_;
hashset_iter iter;
hs_iter_init(&iter, _set_A_);
for (hs_iter_to_start(&iter); !hs_iter_end(&iter); hs_iter_next(&iter))
{
size_t value = hs_iter_value(&iter);
if (hs_impl_get_entry(_set_B_, value) != NULL)
hs_insert(_set_r_, value);
}
return _set_r_;
}
hashset *hs_difference(hashset *_set1_, hashset *_set2_)
{
hashset *_set_r_ = hs_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash);
if (!_set_r_)
return false;
hashset_iter iter;
hs_iter_init(&iter, _set1_);
for (hs_iter_to_start(&iter); !hs_iter_end(&iter); hs_iter_next(&iter))
{
size_t value = hs_iter_value(&iter);
if (hs_impl_get_entry(_set2_, value) == NULL)
hs_insert(_set_r_, value);
}
return _set_r_;
}
hashset *hs_symmetric_difference(hashset *_set1_, hashset *_set2_)
{
hashset_iter iter1, iter2;
hashset *_set_r_ = hs_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash);
if (!_set_r_)
return false;
hs_iter_init(&iter1, _set1_);
hs_iter_init(&iter2, _set2_);
for (hs_iter_to_start(&iter1); !hs_iter_end(&iter1); hs_iter_next(&iter1))
{
size_t value = hs_iter_value(&iter1);
if (hs_impl_get_entry(_set2_, value) == NULL)
hs_insert(_set_r_, value);
}
for (hs_iter_to_start(&iter2); !hs_iter_end(&iter2); hs_iter_next(&iter2))
{
size_t value = hs_iter_value(&iter2);
if (hs_impl_get_entry(_set1_, value) == NULL)
hs_insert(_set_r_, value);
}
return _set_r_;
}
bool hs_is_subset(hashset *_set1_, hashset *_set2_)
{
if (hs_count(_set1_) > hs_count(_set2_))
return false;
if (hs_empty(_set1_))
return true;
hashset_iter iter;
hs_iter_init(&iter, _set1_);
for (hs_iter_to_start(&iter); !hs_iter_end(&iter); hs_iter_next(&iter))
{
size_t value = hs_iter_value(&iter);
if (!hs_contains(_set2_, value))
return false;
}
return true;
}
bool hs_is_superset(hashset *_set1_, hashset *_set2_) { return hs_is_subset(_set2_, _set1_); }
bool hs_is_proper_subset(hashset *_set1_, hashset *_set2_)
{
if (hs_count(_set1_) >= hs_count(_set2_))
return false;
if (hs_empty(_set1_))
{
if (!hs_empty(_set2_))
return true;
else
return false;
}
hashset_iter iter;
hs_iter_init(&iter, _set1_);
for (hs_iter_to_start(&iter); !hs_iter_end(&iter); hs_iter_next(&iter))
{
size_t value = hs_iter_value(&iter);
if (!hs_contains(_set2_, value))
return false;
}
return true;
}
bool hs_is_proper_superset(hashset *_set1_, hashset *_set2_) { return hs_is_proper_subset(_set2_, _set1_); }
bool hs_is_disjointset(hashset *_set1_, hashset *_set2_)
{
if (hs_empty(_set1_))
return true;
hashset_iter iter;
hs_iter_init(&iter, _set1_);
for (hs_iter_to_start(&iter); !hs_iter_end(&iter); hs_iter_next(&iter))
{
size_t value = hs_iter_value(&iter);
if (hs_contains(_set2_, value))
return false;
}
return true;
}
hashset_iter *hs_iter_new(hashset *target)
{
hashset_iter *iter = malloc(sizeof(hashset_iter));
if (!iter)
return NULL;
hs_iter_init(iter, target);
return iter;
}
void hs_iter_free(hashset_iter *iter) { free(iter); }
void hs_iter_init(hashset_iter *iter, hashset *target)
{
iter->target = target;
iter->cursor = 0;
iter->index = 0;
iter->start = true;
iter->end = hs_empty(target);
if (!hs_empty(target))
{
for (size_t i = 0; i < target->capacity; i++)
{
if (target->buffer[i].state == ES_FILLED)
{
iter->first = i;
break;
}
}
iter->cursor = iter->first;
for (size_t i = target->capacity; i > 0; i--)
{
if (target->buffer[i - 1].state == ES_FILLED)
{
iter->last = i - 1;
break;
}
}
}
}
bool hs_iter_start(hashset_iter *iter) { return hs_empty(iter->target) || iter->start; }
bool hs_iter_end(hashset_iter *iter) { return hs_empty(iter->target) || iter->end; }
void hs_iter_to_start(hashset_iter *iter)
{
iter->cursor = iter->first;
iter->index = 0;
iter->start = true;
iter->end = hs_empty(iter->target);
}
void hs_iter_to_end(hashset_iter *iter)
{
iter->cursor = iter->last;
iter->index = iter->target->count - 1;
iter->start = hs_empty(iter->target);
iter->end = true;
}
bool hs_iter_next(hashset_iter *iter)
{
if (iter->end)
return false;
hashset_entry *scan = &(iter->target->buffer[iter->cursor]);
if (iter->cursor == iter->last)
iter->end = true;
else
{
iter->index++;
while (1)
{
iter->cursor++;
scan = &(iter->target->buffer[iter->cursor]);
if (scan->state == ES_FILLED)
break;
}
}
iter->start = hs_empty(iter->target);
return true;
}
bool hs_iter_prev(hashset_iter *iter)
{
if (iter->start)
return false;
hashset_entry *scan = &(iter->target->buffer[iter->cursor]);
if (iter->cursor == iter->first)
iter->start = true;
else
{
iter->index--;
while (1)
{
iter->cursor--;
scan = &(iter->target->buffer[iter->cursor]);
if (scan->state == ES_FILLED)
break;
}
}
iter->end = hs_empty(iter->target);
return true;
}
size_t hs_iter_value(hashset_iter *iter)
{
if (hs_empty(iter->target))
return hs_impl_default_value();
return iter->target->buffer[iter->cursor].value;
}
size_t hs_iter_index(hashset_iter *iter) { return iter->index; }
static bool hs_impl_grow(hashset *_set_)
{
size_t new_size = hs_impl_calculate_size(_set_->capacity + _set_->capacity / 2);
hashset *_new_set_ = hs_new(new_size, _set_->load, _set_->cmp, _set_->hash);
if (!_new_set_)
return false;
hashset_iter iter;
for (hs_iter_init(&iter, _set_); !hs_iter_end(&iter); hs_iter_next(&iter))
{
hs_insert(_new_set_, hs_iter_value(&iter));
}
if (_set_->count != _new_set_->count)
{
hs_free(_new_set_);
return false;
}
hashset_entry *tmp = _set_->buffer;
_set_->buffer = _new_set_->buffer;
_new_set_->buffer = tmp;
_set_->capacity = _new_set_->capacity;
hs_free(_new_set_);
return true;
}
static hashset_entry *hs_impl_get_entry(hashset *_set_, size_t element)
{
size_t hash = _set_->hash(element);
size_t pos = hash % _set_->capacity;
hashset_entry *target = &(_set_->buffer[pos]);
while (target->state == ES_FILLED || target->state == ES_DELETED)
{
if (_set_->cmp(target->value, element) == 0)
return target;
pos++;
target = &(_set_->buffer[pos % _set_->capacity]);
}
return NULL;
}
static size_t hs_impl_calculate_size(size_t required)
{
const size_t count = sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]);
if (cmc_hashtable_primes[count - 1] < required)
return required;
size_t i = 0;
while (cmc_hashtable_primes[i] < required)
i++;
return cmc_hashtable_primes[i];
}
static hashset_iter hs_impl_it_start(hashset *_set_)
{
hashset_iter iter;
hs_iter_init(&iter, _set_);
return iter;
}
static hashset_iter hs_impl_it_end(hashset *_set_)
{
hashset_iter iter;
hs_iter_init(&iter, _set_);
hs_iter_to_end(&iter);
return iter;
}
+294
View File
@@ -0,0 +1,294 @@
#include "cmc/heap.h"
typedef struct heap_s
{
size_t *buffer;
size_t capacity;
size_t count;
enum HeapOrder HO;
int (*cmp)(size_t, size_t);
struct heap_iter_s (*it_start)(struct heap_s *);
struct heap_iter_s (*it_end)(struct heap_s *);
} heap, *heap_ptr;
typedef struct heap_iter_s
{
struct heap_s *target;
size_t cursor;
bool start;
bool end;
} heap_iter, *heap_iter_ptr;
heap *h_new(size_t capacity, HeapOrder HO, int (*compare)(size_t, size_t));
void h_clear(heap *_heap_);
void h_free(heap *_heap_);
bool h_insert(heap *_heap_, size_t element);
bool h_remove(heap *_heap_, size_t *result);
bool h_insert_if(heap *_heap_, size_t element, bool condition);
bool h_remove_if(heap *_heap_, size_t *result, bool condition);
size_t h_peek(heap *_heap_);
size_t *h_peek_ref(heap *_heap_);
bool h_contains(heap *_heap_, size_t element);
bool h_empty(heap *_heap_);
bool h_full(heap *_heap_);
size_t h_count(heap *_heap_);
size_t h_capacity(heap *_heap_);
heap_iter *h_iter_new(heap *target);
void h_iter_free(heap_iter *iter);
void h_iter_init(heap_iter *iter, heap *target);
bool h_iter_start(heap_iter *iter);
bool h_iter_end(heap_iter *iter);
void h_iter_to_start(heap_iter *iter);
void h_iter_to_end(heap_iter *iter);
bool h_iter_next(heap_iter *iter);
bool h_iter_prev(heap_iter *iter);
size_t h_iter_value(heap_iter *iter);
size_t h_iter_index(heap_iter *iter);
static inline size_t h_impl_default_value(void)
{
size_t _empty_value_;
memset(&_empty_value_, 0, sizeof(size_t));
return _empty_value_;
}
static bool h_impl_grow(heap *_heap_);
static size_t h_impl_p(size_t index);
static size_t h_impl_l(size_t index);
static size_t h_impl_r(size_t index);
static bool h_impl_float_up(heap *_heap_, size_t index);
static bool h_impl_float_down(heap *_heap_, size_t index);
static heap_iter h_impl_it_start(heap *_heap_);
static heap_iter h_impl_it_end(heap *_heap_);
heap *h_new(size_t capacity, HeapOrder HO, int (*compare)(size_t, size_t))
{
if (capacity < 1)
return NULL;
if (HO != MinHeap && HO != MaxHeap)
return NULL;
heap *_heap_ = malloc(sizeof(heap));
if (!_heap_)
return NULL;
_heap_->buffer = malloc(sizeof(size_t) * capacity);
if (!_heap_->buffer)
{
free(_heap_);
return NULL;
}
memset(_heap_->buffer, 0, sizeof(size_t) * capacity);
_heap_->capacity = capacity;
_heap_->count = 0;
_heap_->HO = HO;
_heap_->cmp = compare;
_heap_->it_start = h_impl_it_start;
_heap_->it_end = h_impl_it_end;
return _heap_;
}
void h_clear(heap *_heap_)
{
memset(_heap_->buffer, 0, sizeof(size_t) * _heap_->capacity);
_heap_->count = 0;
}
void h_free(heap *_heap_)
{
free(_heap_->buffer);
free(_heap_);
}
bool h_insert(heap *_heap_, size_t element)
{
if (h_full(_heap_))
{
if (!h_impl_grow(_heap_))
return false;
}
if (_heap_->count == 0)
{
_heap_->buffer[_heap_->count++] = element;
return true;
}
_heap_->buffer[_heap_->count++] = element;
if (!h_impl_float_up(_heap_, _heap_->count - 1))
return false;
return true;
}
bool h_remove(heap *_heap_, size_t *result)
{
if (h_empty(_heap_))
return false;
*result = _heap_->buffer[0];
_heap_->buffer[0] = _heap_->buffer[_heap_->count - 1];
_heap_->buffer[_heap_->count - 1] = h_impl_default_value();
_heap_->count--;
if (!h_impl_float_down(_heap_, 0))
return false;
return true;
}
bool h_insert_if(heap *_heap_, size_t element, bool condition)
{
if (condition)
return h_insert(_heap_, element);
return false;
}
bool h_remove_if(heap *_heap_, size_t *result, bool condition)
{
if (condition)
return h_remove(_heap_, result);
return false;
}
size_t h_peek(heap *_heap_)
{
if (h_empty(_heap_))
return h_impl_default_value();
return _heap_->buffer[0];
}
size_t *h_peek_ref(heap *_heap_)
{
if (h_empty(_heap_))
return NULL;
return &(_heap_->buffer[0]);
}
bool h_contains(heap *_heap_, size_t element)
{
for (size_t i = 0; i < _heap_->count; i++)
{
if (_heap_->cmp(_heap_->buffer[i], element) == 0)
return true;
}
return false;
}
bool h_empty(heap *_heap_) { return _heap_->count == 0; }
bool h_full(heap *_heap_) { return _heap_->count >= _heap_->capacity; }
size_t h_count(heap *_heap_) { return _heap_->count; }
size_t h_capacity(heap *_heap_) { return _heap_->capacity; }
heap_iter *h_iter_new(heap *target)
{
heap_iter *iter = malloc(sizeof(heap_iter));
if (!iter)
return NULL;
h_iter_init(iter, target);
return iter;
}
void h_iter_free(heap_iter *iter) { free(iter); }
void h_iter_init(heap_iter *iter, heap *target)
{
iter->target = target;
iter->cursor = 0;
iter->start = true;
iter->end = h_empty(target);
}
bool h_iter_start(heap_iter *iter) { return h_empty(iter->target) || iter->start; }
bool h_iter_end(heap_iter *iter) { return h_empty(iter->target) || iter->end; }
void h_iter_to_start(heap_iter *iter)
{
iter->cursor = 0;
iter->start = true;
iter->end = h_empty(iter->target);
}
void h_iter_to_end(heap_iter *iter)
{
iter->cursor = iter->target->count - 1;
iter->start = h_empty(iter->target);
iter->end = true;
}
bool h_iter_next(heap_iter *iter)
{
if (iter->end)
return false;
iter->start = false;
if (iter->cursor == iter->target->count - 1)
iter->end = true;
else
iter->cursor++;
return true;
}
bool h_iter_prev(heap_iter *iter)
{
if (iter->start)
return false;
iter->end = false;
if (iter->cursor == 0)
iter->start = true;
else
iter->cursor--;
return true;
}
size_t h_iter_value(heap_iter *iter)
{
if (h_empty(iter->target))
return h_impl_default_value();
return iter->target->buffer[iter->cursor];
}
size_t h_iter_index(heap_iter *iter) { return iter->cursor; }
static bool h_impl_grow(heap *_heap_)
{
size_t new_capacity = _heap_->capacity * 2;
size_t *new_buffer = realloc(_heap_->buffer, sizeof(size_t) * new_capacity);
if (!new_buffer)
return false;
_heap_->buffer = new_buffer;
_heap_->capacity = new_capacity;
return true;
}
static size_t h_impl_p(size_t index)
{
if (index == 0)
return 0;
return (index - 1) / 2;
}
static size_t h_impl_l(size_t index) { return 2 * index + 1; }
static size_t h_impl_r(size_t index) { return 2 * index + 2; }
static bool h_impl_float_up(heap *_heap_, size_t index)
{
size_t C = index;
size_t child = _heap_->buffer[C];
size_t parent = _heap_->buffer[h_impl_p(C)];
int mod = _heap_->HO;
while (C > 0 && _heap_->cmp(child, parent) * mod > 0)
{
size_t tmp = _heap_->buffer[C];
_heap_->buffer[C] = _heap_->buffer[h_impl_p(C)];
_heap_->buffer[h_impl_p(C)] = tmp;
C = h_impl_p(C);
child = _heap_->buffer[C];
parent = _heap_->buffer[h_impl_p(C)];
}
return true;
}
static bool h_impl_float_down(heap *_heap_, size_t index)
{
int mod = _heap_->HO;
while (index < _heap_->count)
{
size_t L = h_impl_l(index);
size_t R = h_impl_r(index);
size_t C = index;
if (L < _heap_->count && _heap_->cmp(_heap_->buffer[L], _heap_->buffer[C]) * mod > 0)
{
C = L;
}
if (R < _heap_->count && _heap_->cmp(_heap_->buffer[R], _heap_->buffer[C]) * mod > 0)
{
C = R;
}
if (C != index)
{
size_t tmp = _heap_->buffer[index];
_heap_->buffer[index] = _heap_->buffer[C];
_heap_->buffer[C] = tmp;
index = C;
}
else
break;
}
return true;
}
static heap_iter h_impl_it_start(heap *_heap_)
{
heap_iter iter;
h_iter_init(&iter, _heap_);
h_iter_to_start(&iter);
return iter;
}
static heap_iter h_impl_it_end(heap *_heap_)
{
heap_iter iter;
h_iter_init(&iter, _heap_);
h_iter_to_end(&iter);
return iter;
}
+479
View File
@@ -0,0 +1,479 @@
#include "cmc/linkedlist.h"
typedef struct linkedlist_s
{
struct linkedlist_node_s *head;
struct linkedlist_node_s *tail;
size_t count;
struct linkedlist_iter_s (*it_start)(struct linkedlist_s *);
struct linkedlist_iter_s (*it_end)(struct linkedlist_s *);
} linkedlist, *linkedlist_ptr;
typedef struct linkedlist_node_s
{
size_t data;
struct linkedlist_node_s *next;
struct linkedlist_node_s *prev;
} linkedlist_node, *linkedlist_node_ptr;
typedef struct linkedlist_iter_s
{
struct linkedlist_s *target;
struct linkedlist_node_s *cursor;
size_t index;
bool start;
bool end;
} linkedlist_iter, *linkedlist_iter_ptr;
linkedlist *ll_new(void);
void ll_clear(linkedlist *_list_);
void ll_free(linkedlist *_list_);
bool ll_push_front(linkedlist *_list_, size_t element);
bool ll_push(linkedlist *_list_, size_t element, size_t index);
bool ll_push_back(linkedlist *_list_, size_t element);
bool ll_pop_front(linkedlist *_list_);
bool ll_pop(linkedlist *_list_, size_t index);
bool ll_pop_back(linkedlist *_list_);
bool ll_push_if(linkedlist *_list_, size_t element, size_t index, bool condition);
bool ll_pop_if(linkedlist *_list_, size_t index, bool condition);
size_t ll_front(linkedlist *_list_);
size_t ll_get(linkedlist *_list_, size_t index);
size_t *ll_get_ref(linkedlist *_list_, size_t index);
size_t ll_back(linkedlist *_list_);
bool ll_contains(linkedlist *_list_, size_t element, int (*comparator)(size_t, size_t));
bool ll_empty(linkedlist *_list_);
size_t ll_count(linkedlist *_list_);
linkedlist_node *ll_new_node(size_t element);
void ll_free_node(linkedlist_node *_node_);
linkedlist_node *ll_head(linkedlist *_list_);
linkedlist_node *ll_get_node(linkedlist *_list_, size_t index);
linkedlist_node *ll_tail(linkedlist *_list_);
bool ll_insert_after(linkedlist *_owner_, linkedlist_node *_node_, size_t element);
bool ll_insert_before(linkedlist *_owner_, linkedlist_node *_node_, size_t element);
bool ll_remove_after(linkedlist *_owner_, linkedlist_node *_node_);
bool ll_remove_current(linkedlist *_owner_, linkedlist_node *_node_);
bool ll_remove_before(linkedlist *_owner_, linkedlist_node *_node_);
linkedlist_node *ll_next_node(linkedlist_node *_node_);
linkedlist_node *ll_prev_node(linkedlist_node *_node_);
linkedlist_iter *ll_iter_new(linkedlist *target);
void ll_iter_free(linkedlist_iter *iter);
void ll_iter_init(linkedlist_iter *iter, linkedlist *target);
bool ll_iter_start(linkedlist_iter *iter);
bool ll_iter_end(linkedlist_iter *iter);
void ll_iter_to_start(linkedlist_iter *iter);
void ll_iter_to_end(linkedlist_iter *iter);
bool ll_iter_next(linkedlist_iter *iter);
bool ll_iter_prev(linkedlist_iter *iter);
size_t ll_iter_value(linkedlist_iter *iter);
size_t *ll_iter_rvalue(linkedlist_iter *iter);
size_t ll_iter_index(linkedlist_iter *iter);
linkedlist_node *ll_iter_node(linkedlist_iter *iter);
static inline size_t ll_impl_default_value(void)
{
size_t _empty_value_;
memset(&_empty_value_, 0, sizeof(size_t));
return _empty_value_;
}
static linkedlist_iter ll_impl_it_start(linkedlist *_list_);
static linkedlist_iter ll_impl_it_end(linkedlist *_list_);
linkedlist *ll_new(void)
{
linkedlist *_list_ = malloc(sizeof(linkedlist));
if (!_list_)
return NULL;
_list_->count = 0;
_list_->head = NULL;
_list_->tail = NULL;
_list_->it_start = ll_impl_it_start;
_list_->it_end = ll_impl_it_end;
return _list_;
}
void ll_clear(linkedlist *_list_)
{
linkedlist_node *scan = _list_->head;
while (_list_->head != NULL)
{
_list_->head = _list_->head->next;
free(scan);
scan = _list_->head;
}
_list_->count = 0;
_list_->head = NULL;
_list_->tail = NULL;
}
void ll_free(linkedlist *_list_)
{
ll_clear(_list_);
free(_list_);
}
bool ll_push_front(linkedlist *_list_, size_t element)
{
linkedlist_node *_node_ = ll_new_node(element);
if (!_node_)
return false;
if (ll_empty(_list_))
{
_list_->head = _node_;
_list_->tail = _node_;
}
else
{
_node_->next = _list_->head;
_list_->head->prev = _node_;
_list_->head = _node_;
}
_list_->count++;
return true;
}
bool ll_push(linkedlist *_list_, size_t element, size_t index)
{
if (index > _list_->count)
return false;
if (index == 0)
{
return ll_push_front(_list_, element);
}
else if (index == _list_->count)
{
return ll_push_back(_list_, element);
}
linkedlist_node *_node_ = ll_new_node(element);
if (!_node_)
return false;
linkedlist_node *scan = ll_get_node(_list_, index - 1);
_node_->next = scan->next;
_node_->prev = scan;
_node_->next->prev = _node_;
_node_->prev->next = _node_;
_list_->count++;
return true;
}
bool ll_push_back(linkedlist *_list_, size_t element)
{
linkedlist_node *_node_ = ll_new_node(element);
if (!_node_)
return false;
if (ll_empty(_list_))
{
_list_->head = _node_;
_list_->tail = _node_;
}
else
{
_node_->prev = _list_->tail;
_list_->tail->next = _node_;
_list_->tail = _node_;
}
_list_->count++;
return true;
}
bool ll_pop_front(linkedlist *_list_)
{
if (ll_empty(_list_))
return false;
linkedlist_node *_node_ = _list_->head;
_list_->head = _list_->head->next;
free(_node_);
if (_list_->head == NULL)
_list_->tail = NULL;
else
_list_->head->prev = NULL;
_list_->count--;
return true;
}
bool ll_pop(linkedlist *_list_, size_t index)
{
if (ll_empty(_list_))
return false;
if (index >= _list_->count)
return false;
if (index == 0)
{
return ll_pop_front(_list_);
}
else if (index == _list_->count - 1)
{
return ll_pop_back(_list_);
}
linkedlist_node *_node_ = ll_get_node(_list_, index);
if (!_node_)
return false;
_node_->next->prev = _node_->prev;
_node_->prev->next = _node_->next;
free(_node_);
_list_->count--;
return true;
}
bool ll_pop_back(linkedlist *_list_)
{
if (ll_empty(_list_))
return false;
linkedlist_node *_node_ = _list_->tail;
_list_->tail = _list_->tail->prev;
free(_node_);
if (_list_->tail == NULL)
_list_->head = NULL;
else
_list_->tail->next = NULL;
_list_->count--;
return true;
}
bool ll_push_if(linkedlist *_list_, size_t element, size_t index, bool condition)
{
if (condition)
return ll_push(_list_, element, index);
return false;
}
bool ll_pop_if(linkedlist *_list_, size_t index, bool condition)
{
if (condition)
return ll_pop(_list_, index);
return false;
}
size_t ll_front(linkedlist *_list_)
{
if (ll_empty(_list_))
return ll_impl_default_value();
return _list_->head->data;
}
size_t ll_get(linkedlist *_list_, size_t index)
{
if (index >= _list_->count || ll_empty(_list_))
return ll_impl_default_value();
linkedlist_node *scan = ll_get_node(_list_, index);
if (scan == NULL)
return ll_impl_default_value();
return scan->data;
}
size_t *ll_get_ref(linkedlist *_list_, size_t index)
{
if (index >= _list_->count)
return NULL;
if (ll_empty(_list_))
return NULL;
linkedlist_node *scan = ll_get_node(_list_, index);
if (scan == NULL)
return NULL;
return &(scan->data);
}
size_t ll_back(linkedlist *_list_)
{
if (ll_empty(_list_))
return ll_impl_default_value();
return _list_->tail->data;
}
bool ll_contains(linkedlist *_list_, size_t element, int (*comparator)(size_t, size_t))
{
linkedlist_node *scan = _list_->head;
while (scan != NULL)
{
if (comparator(scan->data, element) == 0)
return true;
scan = scan->next;
}
return false;
}
bool ll_empty(linkedlist *_list_) { return _list_->count == 0; }
size_t ll_count(linkedlist *_list_) { return _list_->count; }
linkedlist_node *ll_new_node(size_t element)
{
linkedlist_node *_node_ = malloc(sizeof(linkedlist_node));
if (!_node_)
return NULL;
_node_->data = element;
_node_->next = NULL;
_node_->prev = NULL;
return _node_;
}
void ll_free_node(linkedlist_node *_node_) { free(_node_); }
linkedlist_node *ll_head(linkedlist *_list_) { return _list_->head; }
linkedlist_node *ll_get_node(linkedlist *_list_, size_t index)
{
if (index >= _list_->count)
return NULL;
if (ll_empty(_list_))
return NULL;
linkedlist_node *_node_ = NULL;
if (index <= _list_->count / 2)
{
_node_ = _list_->head;
for (size_t i = 0; i < index; i++)
{
_node_ = _node_->next;
}
}
else
{
_node_ = _list_->tail;
for (size_t i = _list_->count - 1; i > index; i--)
{
_node_ = _node_->prev;
}
}
return _node_;
}
linkedlist_node *ll_tail(linkedlist *_list_) { return _list_->tail; }
bool ll_insert_after(linkedlist *_owner_, linkedlist_node *_node_, size_t element)
{
linkedlist_node *new_node = ll_new_node(element);
if (!new_node)
return false;
new_node->next = _node_->next;
if (_node_->next != NULL)
_node_->next->prev = new_node;
else
_owner_->tail = new_node;
new_node->prev = _node_;
_node_->next = new_node;
_owner_->count++;
return true;
}
bool ll_insert_before(linkedlist *_owner_, linkedlist_node *_node_, size_t element)
{
linkedlist_node *new_node = ll_new_node(element);
if (!new_node)
return false;
new_node->prev = _node_->prev;
if (_node_->prev != NULL)
_node_->prev->next = new_node;
else
_owner_->head = new_node;
new_node->next = _node_;
_node_->prev = new_node;
_owner_->count++;
return true;
}
bool ll_remove_after(linkedlist *_owner_, linkedlist_node *_node_)
{
if (_node_->next == NULL)
return false;
linkedlist_node *tmp = _node_->next;
if (tmp->next != NULL)
{
_node_->next = _node_->next->next;
_node_->next->prev = _node_;
}
else
_owner_->tail = _node_;
free(tmp);
_owner_->count--;
return true;
}
bool ll_remove_current(linkedlist *_owner_, linkedlist_node *_node_)
{
if (_node_->prev != NULL)
_node_->prev->next = _node_->next;
else
_owner_->head = _node_->next;
if (_node_->next != NULL)
_node_->next->prev = _node_->prev;
else
_owner_->tail = _node_->prev;
free(_node_);
_owner_->count--;
return true;
}
bool ll_remove_before(linkedlist *_owner_, linkedlist_node *_node_)
{
if (_node_->prev == NULL)
return false;
linkedlist_node *tmp = _node_->prev;
if (tmp->prev != NULL)
{
_node_->prev = _node_->prev->prev;
_node_->prev->next = _node_;
}
else
_owner_->head = _node_;
free(tmp);
_owner_->count--;
return true;
}
linkedlist_node *ll_next_node(linkedlist_node *_node_) { return _node_->next; }
linkedlist_node *ll_prev_node(linkedlist_node *_node_) { return _node_->prev; }
linkedlist_iter *ll_iter_new(linkedlist *target)
{
linkedlist_iter *iter = malloc(sizeof(linkedlist_iter));
if (!iter)
return NULL;
ll_iter_init(iter, target);
return iter;
}
void ll_iter_free(linkedlist_iter *iter) { free(iter); }
void ll_iter_init(linkedlist_iter *iter, linkedlist *target)
{
iter->target = target;
iter->cursor = target->head;
iter->index = 0;
iter->start = true;
iter->end = ll_empty(target);
}
bool ll_iter_start(linkedlist_iter *iter) { return ll_empty(iter->target) || iter->start; }
bool ll_iter_end(linkedlist_iter *iter) { return ll_empty(iter->target) || iter->end; }
void ll_iter_to_start(linkedlist_iter *iter)
{
iter->cursor = iter->target->head;
iter->index = 0;
iter->start = true;
iter->end = ll_empty(iter->target);
}
void ll_iter_to_end(linkedlist_iter *iter)
{
iter->cursor = iter->target->tail;
iter->index = iter->target->count - 1;
iter->start = ll_empty(iter->target);
iter->end = true;
}
bool ll_iter_next(linkedlist_iter *iter)
{
if (iter->end)
return false;
iter->start = ll_empty(iter->target);
if (iter->cursor->next == NULL)
iter->end = true;
else
{
iter->cursor = iter->cursor->next;
iter->index++;
}
return true;
}
bool ll_iter_prev(linkedlist_iter *iter)
{
if (iter->start)
return false;
iter->end = ll_empty(iter->target);
if (iter->cursor->prev == NULL)
iter->start = true;
else
{
iter->cursor = iter->cursor->prev;
iter->index--;
}
return true;
}
size_t ll_iter_value(linkedlist_iter *iter)
{
if (ll_empty(iter->target))
return ll_impl_default_value();
return iter->cursor->data;
}
size_t *ll_iter_rvalue(linkedlist_iter *iter)
{
if (ll_empty(iter->target))
return NULL;
return &(iter->cursor->data);
}
size_t ll_iter_index(linkedlist_iter *iter) { return iter->index; }
linkedlist_node *ll_iter_node(linkedlist_iter *iter) { return iter->cursor; }
static linkedlist_iter ll_impl_it_start(linkedlist *_list_)
{
linkedlist_iter iter;
ll_iter_init(&iter, _list_);
ll_iter_to_start(&iter);
return iter;
}
static linkedlist_iter ll_impl_it_end(linkedlist *_list_)
{
linkedlist_iter iter;
ll_iter_init(&iter, _list_);
ll_iter_to_end(&iter);
return iter;
}
+422
View File
@@ -0,0 +1,422 @@
#include "cmc/list.h"
typedef struct list_s
{
size_t *buffer;
size_t capacity;
size_t count;
struct list_iter_s (*it_start)(struct list_s *);
struct list_iter_s (*it_end)(struct list_s *);
} list, *list_ptr;
typedef struct list_iter_s
{
struct list_s *target;
size_t cursor;
bool start;
bool end;
} list_iter, *list_iter_ptr;
list *l_new(size_t capacity);
list *l_new_from(size_t *elements, size_t size);
void l_clear(list *_list_);
void l_free(list *_list_);
bool l_push_front(list *_list_, size_t element);
bool l_push(list *_list_, size_t element, size_t index);
bool l_push_back(list *_list_, size_t element);
bool l_pop_front(list *_list_);
bool l_pop(list *_list_, size_t index);
bool l_pop_back(list *_list_);
bool l_push_if(list *_list_, size_t element, size_t index, bool condition);
bool l_pop_if(list *_list_, size_t index, bool condition);
bool l_prepend(list *_list_, size_t *elements, size_t size);
bool l_insert(list *_list_, size_t *elements, size_t size, size_t index);
bool l_append(list *_list_, size_t *elements, size_t size);
bool l_remove(list *_list_, size_t from, size_t to);
list *l_extract(list *_list_, size_t from, size_t to);
size_t l_front(list *_list_);
size_t l_get(list *_list_, size_t index);
size_t *l_get_ref(list *_list_, size_t index);
size_t l_back(list *_list_);
size_t l_indexof(list *_list_, size_t element, int (*comparator)(size_t, size_t), bool from_start);
bool l_contains(list *_list_, size_t element, int (*comparator)(size_t, size_t));
bool l_empty(list *_list_);
bool l_full(list *_list_);
size_t l_count(list *_list_);
bool l_fits(list *_list_, size_t size);
size_t l_capacity(list *_list_);
list_iter *l_iter_new(list *target);
void l_iter_free(list_iter *iter);
void l_iter_init(list_iter *iter, list *target);
bool l_iter_start(list_iter *iter);
bool l_iter_end(list_iter *iter);
void l_iter_to_start(list_iter *iter);
void l_iter_to_end(list_iter *iter);
bool l_iter_next(list_iter *iter);
bool l_iter_prev(list_iter *iter);
size_t l_iter_value(list_iter *iter);
size_t *l_iter_rvalue(list_iter *iter);
size_t l_iter_index(list_iter *iter);
static inline size_t l_impl_default_value(void)
{
size_t _empty_value_;
memset(&_empty_value_, 0, sizeof(size_t));
return _empty_value_;
}
static bool l_impl_grow(list *_list_, size_t required);
static list_iter l_impl_it_start(list *_list_);
static list_iter l_impl_it_end(list *_list_);
list *l_new(size_t capacity)
{
if (capacity < 1)
return NULL;
list *_list_ = malloc(sizeof(list));
if (!_list_)
return NULL;
_list_->buffer = malloc(capacity * sizeof(size_t));
if (!_list_->buffer)
{
free(_list_);
return NULL;
}
memset(_list_->buffer, 0, capacity * sizeof(size_t));
_list_->capacity = capacity;
_list_->count = 0;
_list_->it_start = l_impl_it_start;
_list_->it_end = l_impl_it_end;
return _list_;
}
list *l_new_from(size_t *elements, size_t size)
{
if (size == 0)
return NULL;
list *_list_ = l_new(size + size / 2);
if (!_list_)
return NULL;
memcpy(_list_->buffer, elements, size * sizeof(size_t));
_list_->count = size;
return _list_;
}
void l_clear(list *_list_)
{
memset(_list_->buffer, 0, sizeof(size_t) * _list_->capacity);
_list_->count = 0;
}
void l_free(list *_list_)
{
free(_list_->buffer);
free(_list_);
}
bool l_push_front(list *_list_, size_t element)
{
if (l_full(_list_))
{
if (!l_impl_grow(_list_, _list_->count + 1))
return false;
}
if (!l_empty(_list_))
{
memmove(_list_->buffer + 1, _list_->buffer, _list_->count * sizeof(size_t));
}
_list_->buffer[0] = element;
_list_->count++;
return true;
}
bool l_push(list *_list_, size_t element, size_t index)
{
if (index > _list_->count)
return false;
if (index == 0)
{
return l_push_front(_list_, element);
}
else if (index == _list_->count)
{
return l_push_back(_list_, element);
}
if (l_full(_list_))
{
if (!l_impl_grow(_list_, _list_->count + 1))
return false;
}
memmove(_list_->buffer + index + 1, _list_->buffer + index, (_list_->count - index) * sizeof(size_t));
_list_->buffer[index] = element;
_list_->count++;
return true;
}
bool l_push_back(list *_list_, size_t element)
{
if (l_full(_list_))
{
if (!l_impl_grow(_list_, _list_->count + 1))
return false;
}
_list_->buffer[_list_->count++] = element;
return true;
}
bool l_pop_front(list *_list_)
{
if (l_empty(_list_))
return false;
memmove(_list_->buffer, _list_->buffer + 1, _list_->count * sizeof(size_t));
_list_->buffer[--_list_->count] = l_impl_default_value();
return true;
}
bool l_pop(list *_list_, size_t index)
{
if (l_empty(_list_))
return false;
if (index >= _list_->count)
return false;
if (index == 0)
{
return l_pop_front(_list_);
}
else if (index == _list_->count - 1)
{
return l_pop_back(_list_);
}
memmove(_list_->buffer + index, _list_->buffer + index + 1, (_list_->count - index) * sizeof(size_t));
_list_->buffer[--_list_->count] = l_impl_default_value();
return true;
}
bool l_pop_back(list *_list_)
{
if (l_empty(_list_))
return false;
_list_->buffer[--_list_->count] = l_impl_default_value();
return true;
}
bool l_push_if(list *_list_, size_t element, size_t index, bool condition)
{
if (condition)
return l_push(_list_, element, index);
return false;
}
bool l_pop_if(list *_list_, size_t index, bool condition)
{
if (condition)
return l_pop(_list_, index);
return false;
}
bool l_prepend(list *_list_, size_t *elements, size_t size)
{
if (size == 0)
return false;
if (!l_fits(_list_, size))
{
if (!l_impl_grow(_list_, _list_->count + size))
return false;
}
memmove(_list_->buffer + size, _list_->buffer, _list_->count * sizeof(size_t));
memcpy(_list_->buffer, elements, size * sizeof(size_t));
_list_->count += size;
return true;
}
bool l_insert(list *_list_, size_t *elements, size_t size, size_t index)
{
if (size == 0 || index > _list_->count)
return false;
if (index == 0)
return l_prepend(_list_, elements, size);
else if (index == _list_->count)
return l_append(_list_, elements, size);
else
{
if (!l_fits(_list_, size))
{
if (!l_impl_grow(_list_, _list_->count + size))
return false;
}
memmove(_list_->buffer + index + size, _list_->buffer + index, (_list_->count - index) * sizeof(size_t));
memcpy(_list_->buffer + index, elements, size * sizeof(size_t));
_list_->count += size;
}
return true;
}
bool l_append(list *_list_, size_t *elements, size_t size)
{
if (size == 0)
return false;
if (!l_fits(_list_, size))
{
if (!l_impl_grow(_list_, _list_->count + size))
return false;
}
memcpy(_list_->buffer + _list_->count, elements, size * sizeof(size_t));
_list_->count += size;
return true;
}
bool l_remove(list *_list_, size_t from, size_t to)
{
if (from > to || to >= _list_->count)
return false;
size_t length = (to - from + 1);
memmove(_list_->buffer + from, _list_->buffer + to + 1, (_list_->count - to - 1) * sizeof(size_t));
memset(_list_->buffer + _list_->count - length, 0, length * sizeof(size_t));
_list_->count -= to - from + 1;
return true;
}
list *l_extract(list *_list_, size_t from, size_t to)
{
if (from > to || to >= _list_->count)
return false;
size_t length = to - from + 1;
list *result = l_new_from(_list_->buffer + from, length);
if (!result)
return NULL;
memmove(_list_->buffer + from, _list_->buffer + to + 1, (_list_->count - to - 1) * sizeof(size_t));
memset(_list_->buffer + _list_->count - length, 0, length * sizeof(size_t));
_list_->count -= length;
return result;
}
size_t l_front(list *_list_)
{
if (l_empty(_list_))
return l_impl_default_value();
return _list_->buffer[0];
}
size_t l_get(list *_list_, size_t index)
{
if (index >= _list_->count || l_empty(_list_))
return l_impl_default_value();
return _list_->buffer[index];
}
size_t *l_get_ref(list *_list_, size_t index)
{
if (index >= _list_->count)
return NULL;
if (l_empty(_list_))
return NULL;
return &(_list_->buffer[index]);
}
size_t l_back(list *_list_)
{
if (l_empty(_list_))
return l_impl_default_value();
return _list_->buffer[_list_->count - 1];
}
size_t l_indexof(list *_list_, size_t element, int (*comparator)(size_t, size_t), bool from_start)
{
if (from_start)
{
for (size_t i = 0; i < _list_->count; i++)
{
if (comparator(_list_->buffer[i], element) == 0)
return i;
}
}
else
{
for (size_t i = _list_->count; i > 0; i--)
{
if (comparator(_list_->buffer[i - 1], element) == 0)
return i - 1;
}
}
return _list_->count;
}
bool l_contains(list *_list_, size_t element, int (*comparator)(size_t, size_t))
{
for (size_t i = 0; i < _list_->count; i++)
{
if (comparator(_list_->buffer[i], element) == 0)
return true;
}
return false;
}
bool l_empty(list *_list_) { return _list_->count == 0; }
bool l_full(list *_list_) { return _list_->count >= _list_->capacity; }
size_t l_count(list *_list_) { return _list_->count; }
bool l_fits(list *_list_, size_t size) { return _list_->count + size <= _list_->capacity; }
size_t l_capacity(list *_list_) { return _list_->capacity; }
list_iter *l_iter_new(list *target)
{
list_iter *iter = malloc(sizeof(list_iter));
if (!iter)
return NULL;
l_iter_init(iter, target);
return iter;
}
void l_iter_free(list_iter *iter) { free(iter); }
void l_iter_init(list_iter *iter, list *target)
{
iter->target = target;
iter->cursor = 0;
iter->start = true;
iter->end = l_empty(target);
}
bool l_iter_start(list_iter *iter) { return l_empty(iter->target) || iter->start; }
bool l_iter_end(list_iter *iter) { return l_empty(iter->target) || iter->end; }
void l_iter_to_start(list_iter *iter)
{
iter->cursor = 0;
iter->start = true;
iter->end = l_empty(iter->target);
}
void l_iter_to_end(list_iter *iter)
{
iter->start = l_empty(iter->target);
iter->cursor = l_empty(iter->target) ? 0 : iter->target->count - 1;
iter->end = true;
}
bool l_iter_next(list_iter *iter)
{
if (iter->end)
return false;
iter->start = l_empty(iter->target);
if (iter->cursor == iter->target->count - 1)
iter->end = true;
else
iter->cursor++;
return true;
}
bool l_iter_prev(list_iter *iter)
{
if (iter->start)
return false;
iter->end = l_empty(iter->target);
if (iter->cursor == 0)
iter->start = true;
else
iter->cursor--;
return true;
}
size_t l_iter_value(list_iter *iter)
{
if (l_empty(iter->target))
return l_impl_default_value();
return iter->target->buffer[iter->cursor];
}
size_t *l_iter_rvalue(list_iter *iter)
{
if (l_empty(iter->target))
return NULL;
return &(iter->target->buffer[iter->cursor]);
}
size_t l_iter_index(list_iter *iter) { return iter->cursor; }
static bool l_impl_grow(list *_list_, size_t required)
{
size_t new_capacity = _list_->capacity * 2;
if (new_capacity < required)
new_capacity = required;
size_t *new_buffer = realloc(_list_->buffer, sizeof(size_t) * new_capacity);
if (!new_buffer)
return false;
_list_->buffer = new_buffer;
_list_->capacity = new_capacity;
return true;
}
static list_iter l_impl_it_start(list *_list_)
{
list_iter iter;
l_iter_init(&iter, _list_);
l_iter_to_start(&iter);
return iter;
}
static list_iter l_impl_it_end(list *_list_)
{
list_iter iter;
l_iter_init(&iter, _list_);
l_iter_to_end(&iter);
return iter;
}
+248
View File
@@ -0,0 +1,248 @@
#include "cmc/queue.h"
typedef struct queue_s
{
size_t *buffer;
size_t capacity;
size_t count;
size_t front;
size_t rear;
struct queue_iter_s (*it_start)(struct queue_s *);
struct queue_iter_s (*it_end)(struct queue_s *);
} queue, *queue_ptr;
typedef struct queue_iter_s
{
struct queue_s *target;
size_t cursor;
size_t index;
bool start;
bool end;
} queue_iter, *queue_iter_ptr;
queue *q_new(size_t capacity);
void q_clear(queue *_queue_);
void q_free(queue *_queue_);
bool q_enqueue(queue *_queue_, size_t element);
bool q_dequeue(queue *_queue_);
bool q_enqueue_if(queue *_queue_, size_t element, bool condition);
bool q_dequeue_if(queue *_queue_, bool condition);
size_t q_peek(queue *_queue_);
bool q_contains(queue *_queue_, size_t element, int (*comparator)(size_t, size_t));
bool q_empty(queue *_queue_);
bool q_full(queue *_queue_);
size_t q_count(queue *_queue_);
size_t q_capacity(queue *_queue_);
queue_iter *q_iter_new(queue *target);
void q_iter_free(queue_iter *iter);
void q_iter_init(queue_iter *iter, queue *target);
bool q_iter_start(queue_iter *iter);
bool q_iter_end(queue_iter *iter);
void q_iter_to_start(queue_iter *iter);
void q_iter_to_end(queue_iter *iter);
bool q_iter_next(queue_iter *iter);
bool q_iter_prev(queue_iter *iter);
size_t q_iter_value(queue_iter *iter);
size_t *q_iter_rvalue(queue_iter *iter);
size_t q_iter_index(queue_iter *iter);
static inline size_t q_impl_default_value(void)
{
size_t _empty_value_;
memset(&_empty_value_, 0, sizeof(size_t));
return _empty_value_;
}
static bool q_impl_grow(queue *_queue_);
static queue_iter q_impl_it_start(queue *_queue_);
static queue_iter q_impl_it_end(queue *_queue_);
queue *q_new(size_t capacity)
{
if (capacity < 1)
return NULL;
queue *_queue_ = malloc(sizeof(queue));
if (!_queue_)
return NULL;
_queue_->buffer = malloc(sizeof(size_t) * capacity);
if (!_queue_->buffer)
{
free(_queue_);
return NULL;
}
memset(_queue_->buffer, 0, sizeof(size_t) * capacity);
_queue_->capacity = capacity;
_queue_->count = 0;
_queue_->front = 0;
_queue_->rear = 0;
_queue_->it_start = q_impl_it_start;
_queue_->it_end = q_impl_it_end;
return _queue_;
}
void q_clear(queue *_queue_)
{
memset(_queue_->buffer, 0, sizeof(size_t) * _queue_->capacity);
_queue_->count = 0;
_queue_->front = 0;
_queue_->rear = 0;
}
void q_free(queue *_queue_)
{
free(_queue_->buffer);
free(_queue_);
}
bool q_enqueue(queue *_queue_, size_t element)
{
if (q_full(_queue_))
{
if (!q_impl_grow(_queue_))
return false;
}
_queue_->buffer[_queue_->rear] = element;
_queue_->rear = (_queue_->rear == _queue_->capacity - 1) ? 0 : _queue_->rear + 1;
_queue_->count++;
return true;
}
bool q_dequeue(queue *_queue_)
{
if (q_empty(_queue_))
return false;
_queue_->buffer[_queue_->front] = q_impl_default_value();
_queue_->front = (_queue_->front == _queue_->capacity - 1) ? 0 : _queue_->front + 1;
_queue_->count--;
return true;
}
bool q_enqueue_if(queue *_queue_, size_t element, bool condition)
{
if (condition)
return q_enqueue(_queue_, element);
return false;
}
bool q_dequeue_if(queue *_queue_, bool condition)
{
if (condition)
return q_dequeue(_queue_);
return false;
}
size_t q_peek(queue *_queue_)
{
if (q_empty(_queue_))
return q_impl_default_value();
return _queue_->buffer[_queue_->front];
}
bool q_contains(queue *_queue_, size_t element, int (*comparator)(size_t, size_t))
{
for (size_t i = _queue_->front, j = 0; j < _queue_->count; i = (i + 1) % _queue_->count, j++)
{
if (comparator(_queue_->buffer[i], element) == 0)
return true;
}
return false;
}
bool q_empty(queue *_queue_) { return _queue_->count == 0; }
bool q_full(queue *_queue_) { return _queue_->count >= _queue_->capacity; }
size_t q_count(queue *_queue_) { return _queue_->count; }
size_t q_capacity(queue *_queue_) { return _queue_->capacity; }
queue_iter *q_iter_new(queue *target)
{
queue_iter *iter = malloc(sizeof(queue_iter));
if (!iter)
return NULL;
q_iter_init(iter, target);
return iter;
}
void q_iter_free(queue_iter *iter) { free(iter); }
void q_iter_init(queue_iter *iter, queue *target)
{
iter->target = target;
iter->cursor = target->front;
iter->index = 0;
iter->start = true;
iter->end = q_empty(target);
}
bool q_iter_start(queue_iter *iter) { return q_empty(iter->target) || iter->start; }
bool q_iter_end(queue_iter *iter) { return q_empty(iter->target) || iter->end; }
void q_iter_to_start(queue_iter *iter)
{
iter->cursor = iter->target->front;
iter->index = 0;
iter->start = true;
iter->end = q_empty(iter->target);
}
void q_iter_to_end(queue_iter *iter)
{
if (q_empty(iter->target))
iter->cursor = 0;
else
iter->cursor = (iter->target->rear == 0) ? iter->target->capacity - 1 : iter->target->rear - 1;
iter->index = iter->target->count - 1;
iter->start = q_empty(iter->target);
iter->end = true;
}
bool q_iter_next(queue_iter *iter)
{
if (iter->end)
return false;
iter->start = q_empty(iter->target);
if (iter->index == iter->target->count - 1)
iter->end = true;
else
{
iter->cursor = (iter->cursor + 1) % (iter->target->capacity);
iter->index++;
}
return true;
}
bool q_iter_prev(queue_iter *iter)
{
if (iter->start)
return false;
iter->end = q_empty(iter->target);
if (iter->index == 0)
iter->start = true;
else
{
iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1;
iter->index--;
}
return true;
}
size_t q_iter_value(queue_iter *iter)
{
if (q_empty(iter->target))
return q_impl_default_value();
return iter->target->buffer[iter->cursor];
}
size_t *q_iter_rvalue(queue_iter *iter)
{
if (q_empty(iter->target))
return NULL;
return &(iter->target->buffer[iter->cursor]);
}
size_t q_iter_index(queue_iter *iter) { return iter->index; }
static bool q_impl_grow(queue *_queue_)
{
size_t new_capacity = _queue_->capacity * 2;
size_t *new_buffer = malloc(sizeof(size_t) * new_capacity);
if (!new_buffer)
return false;
for (size_t i = _queue_->front, j = 0; j < _queue_->count; i = (i + 1) % _queue_->capacity, j++)
{
new_buffer[j] = _queue_->buffer[i];
}
free(_queue_->buffer);
_queue_->buffer = new_buffer;
_queue_->capacity = new_capacity;
_queue_->front = 0;
_queue_->rear = _queue_->count;
return true;
}
static queue_iter q_impl_it_start(queue *_queue_)
{
queue_iter iter;
q_iter_init(&iter, _queue_);
q_iter_to_start(&iter);
return iter;
}
static queue_iter q_impl_it_end(queue *_queue_)
{
queue_iter iter;
q_iter_init(&iter, _queue_);
q_iter_to_end(&iter);
return iter;
}
+218
View File
@@ -0,0 +1,218 @@
#include "cmc/stack.h"
typedef struct stack_s
{
size_t *buffer;
size_t capacity;
size_t count;
struct stack_iter_s (*it_start)(struct stack_s *);
struct stack_iter_s (*it_end)(struct stack_s *);
} stack, *stack_ptr;
typedef struct stack_iter_s
{
struct stack_s *target;
size_t cursor;
bool start;
bool end;
} stack_iter, *stack_iter_ptr;
stack *s_new(size_t capacity);
void s_clear(stack *_stack_);
void s_free(stack *_stack_);
bool s_push(stack *_stack_, size_t element);
bool s_pop(stack *_stack_);
bool s_push_if(stack *_stack_, size_t element, bool condition);
bool s_pop_if(stack *_stack_, bool condition);
size_t s_top(stack *_stack_);
bool s_contains(stack *_stack_, size_t element, int (*comparator)(size_t, size_t));
bool s_empty(stack *_stack_);
bool s_full(stack *_stack_);
size_t s_count(stack *_stack_);
size_t s_capacity(stack *_stack_);
stack_iter *s_iter_new(stack *target);
void s_iter_free(stack_iter *iter);
void s_iter_init(stack_iter *iter, stack *target);
bool s_iter_start(stack_iter *iter);
bool s_iter_end(stack_iter *iter);
void s_iter_to_start(stack_iter *iter);
void s_iter_to_end(stack_iter *iter);
bool s_iter_next(stack_iter *iter);
bool s_iter_prev(stack_iter *iter);
size_t s_iter_value(stack_iter *iter);
size_t *s_iter_rvalue(stack_iter *iter);
size_t s_iter_index(stack_iter *iter);
static inline size_t s_impl_default_value(void)
{
size_t _empty_value_;
memset(&_empty_value_, 0, sizeof(size_t));
return _empty_value_;
}
static bool s_impl_grow(stack *_stack_);
static stack_iter s_impl_it_start(stack *_stack_);
static stack_iter s_impl_it_end(stack *_stack_);
stack *s_new(size_t capacity)
{
if (capacity < 1)
return NULL;
stack *_stack_ = malloc(sizeof(stack));
if (!_stack_)
return NULL;
_stack_->buffer = malloc(sizeof(size_t) * capacity);
if (!_stack_->buffer)
{
free(_stack_);
return NULL;
}
memset(_stack_->buffer, 0, sizeof(size_t) * capacity);
_stack_->capacity = capacity;
_stack_->count = 0;
_stack_->it_start = s_impl_it_start;
_stack_->it_end = s_impl_it_end;
return _stack_;
}
void s_clear(stack *_stack_)
{
memset(_stack_->buffer, 0, sizeof(size_t) * _stack_->capacity);
_stack_->count = 0;
}
void s_free(stack *_stack_)
{
free(_stack_->buffer);
free(_stack_);
}
bool s_push(stack *_stack_, size_t element)
{
if (s_full(_stack_))
{
if (!s_impl_grow(_stack_))
return false;
}
_stack_->buffer[_stack_->count++] = element;
return true;
}
bool s_pop(stack *_stack_)
{
if (s_empty(_stack_))
return false;
_stack_->buffer[--_stack_->count] = s_impl_default_value();
return true;
}
bool s_push_if(stack *_stack_, size_t element, bool condition)
{
if (condition)
return s_push(_stack_, element);
return false;
}
bool s_pop_if(stack *_stack_, bool condition)
{
if (condition)
return s_pop(_stack_);
return false;
}
size_t s_top(stack *_stack_)
{
if (s_empty(_stack_))
return s_impl_default_value();
return _stack_->buffer[_stack_->count - 1];
}
bool s_contains(stack *_stack_, size_t element, int (*comparator)(size_t, size_t))
{
for (size_t i = 0; i < _stack_->count; i++)
{
if (comparator(_stack_->buffer[i], element) == 0)
return true;
}
return false;
}
bool s_empty(stack *_stack_) { return _stack_->count == 0; }
bool s_full(stack *_stack_) { return _stack_->count >= _stack_->capacity; }
size_t s_count(stack *_stack_) { return _stack_->count; }
size_t s_capacity(stack *_stack_) { return _stack_->capacity; }
stack_iter *s_iter_new(stack *target)
{
stack_iter *iter = malloc(sizeof(stack_iter));
if (!iter)
return NULL;
s_iter_init(iter, target);
return iter;
}
void s_iter_free(stack_iter *iter) { free(iter); }
void s_iter_init(stack_iter *iter, stack *target)
{
iter->target = target;
iter->cursor = iter->target->count - 1;
iter->start = true;
iter->end = s_empty(target);
}
bool s_iter_start(stack_iter *iter) { return s_empty(iter->target) || iter->start; }
bool s_iter_end(stack_iter *iter) { return s_empty(iter->target) || iter->end; }
void s_iter_to_start(stack_iter *iter)
{
iter->cursor = iter->target->count - 1;
iter->start = true;
iter->end = s_empty(iter->target);
}
void s_iter_to_end(stack_iter *iter)
{
iter->cursor = 0;
iter->start = s_empty(iter->target);
iter->end = true;
}
bool s_iter_next(stack_iter *iter)
{
if (iter->end)
return false;
iter->start = s_empty(iter->target);
if (iter->cursor == 0)
iter->end = true;
else
iter->cursor--;
return true;
}
bool s_iter_prev(stack_iter *iter)
{
if (iter->start)
return false;
iter->end = s_empty(iter->target);
if (iter->cursor == iter->target->count - 1)
iter->start = true;
else
iter->cursor++;
return true;
}
size_t s_iter_value(stack_iter *iter)
{
if (s_empty(iter->target))
return s_impl_default_value();
return iter->target->buffer[iter->cursor];
}
size_t *s_iter_rvalue(stack_iter *iter)
{
if (s_empty(iter->target))
return NULL;
return &(iter->target->buffer[iter->cursor]);
}
size_t s_iter_index(stack_iter *iter) { return iter->target->count - 1 - iter->cursor; }
static bool s_impl_grow(stack *_stack_)
{
size_t new_capacity = _stack_->capacity * 2;
size_t *new_buffer = realloc(_stack_->buffer, sizeof(size_t) * new_capacity);
if (!new_buffer)
return false;
_stack_->buffer = new_buffer;
_stack_->capacity = new_capacity;
return true;
}
static stack_iter s_impl_it_start(stack *_stack_)
{
stack_iter iter;
s_iter_init(&iter, _stack_);
s_iter_to_start(&iter);
return iter;
}
static stack_iter s_impl_it_end(stack *_stack_)
{
stack_iter iter;
s_iter_init(&iter, _stack_);
s_iter_to_end(&iter);
return iter;
}
+597
View File
@@ -0,0 +1,597 @@
#include "cmc/treemap.h"
typedef struct treemap_s
{
struct treemap_node_s *root;
size_t count;
int (*cmp)(size_t, size_t);
struct treemap_iter_s (*it_start)(struct treemap_s *);
struct treemap_iter_s (*it_end)(struct treemap_s *);
} treemap, *treemap_ptr;
typedef struct treemap_node_s
{
size_t key;
size_t value;
unsigned char height;
struct treemap_node_s *right;
struct treemap_node_s *left;
struct treemap_node_s *parent;
} treemap_node, *treemap_node_ptr;
typedef struct treemap_iter_s
{
struct treemap_s *target;
struct treemap_node_s *cursor;
struct treemap_node_s *first;
struct treemap_node_s *last;
size_t index;
bool start;
bool end;
} treemap_iter, *treemap_iter_ptr;
treemap *tm_new(int (*compare)(size_t, size_t));
void tm_clear(treemap *_map_);
void tm_free(treemap *_map_);
bool tm_insert(treemap *_map_, size_t key, size_t value);
bool tm_remove(treemap *_map_, size_t key, size_t *value);
bool tm_insert_if(treemap *_map_, size_t key, size_t value, bool condition);
bool tm_remove_if(treemap *_map_, size_t key, size_t *value, bool condition);
bool tm_max(treemap *_map_, size_t *key, size_t *value);
bool tm_min(treemap *_map_, size_t *key, size_t *value);
size_t tm_get(treemap *_map_, size_t key);
size_t *tm_get_ref(treemap *_map_, size_t key);
bool tm_contains(treemap *_map_, size_t key);
bool tm_empty(treemap *_map_);
size_t tm_count(treemap *_map_);
treemap_iter *tm_iter_new(treemap *target);
void tm_iter_free(treemap_iter *iter);
void tm_iter_init(treemap_iter *iter, treemap *target);
bool tm_iter_start(treemap_iter *iter);
bool tm_iter_end(treemap_iter *iter);
void tm_iter_to_start(treemap_iter *iter);
void tm_iter_to_end(treemap_iter *iter);
bool tm_iter_next(treemap_iter *iter);
bool tm_iter_prev(treemap_iter *iter);
size_t tm_iter_key(treemap_iter *iter);
size_t tm_iter_value(treemap_iter *iter);
size_t *tm_iter_rvalue(treemap_iter *iter);
size_t tm_iter_index(treemap_iter *iter);
static inline size_t tm_impl_default_key(void)
{
size_t _empty_key_;
memset(&_empty_key_, 0, sizeof(size_t));
return _empty_key_;
}
static inline size_t tm_impl_default_value(void)
{
size_t _empty_value_;
memset(&_empty_value_, 0, sizeof(size_t));
return _empty_value_;
}
static treemap_node *tm_impl_new_node(size_t key, size_t value);
static treemap_node *tm_impl_get_node(treemap *_map_, size_t key);
static unsigned char tm_impl_h(treemap_node *node);
static unsigned char tm_impl_hupdate(treemap_node *node);
static void tm_impl_rotate_right(treemap_node **Z);
static void tm_impl_rotate_left(treemap_node **Z);
static void tm_impl_rebalance(treemap *_map_, treemap_node *node);
static treemap_iter tm_impl_it_start(treemap *_map_);
static treemap_iter tm_impl_it_end(treemap *_map_);
treemap *tm_new(int (*compare)(size_t, size_t))
{
treemap *_map_ = malloc(sizeof(treemap));
if (!_map_)
return NULL;
_map_->count = 0;
_map_->root = NULL;
_map_->cmp = compare;
_map_->it_start = tm_impl_it_start;
_map_->it_end = tm_impl_it_end;
return _map_;
}
void tm_clear(treemap *_map_)
{
treemap_node *scan = _map_->root;
treemap_node *up = NULL;
while (scan != NULL)
{
if (scan->left != NULL)
{
treemap_node *left = scan->left;
scan->left = up;
up = scan;
scan = left;
}
else if (scan->right != NULL)
{
treemap_node *right = scan->right;
scan->left = up;
scan->right = NULL;
up = scan;
scan = right;
}
else
{
if (up == NULL)
{
free(scan);
scan = NULL;
}
while (up != NULL)
{
free(scan);
if (up->right != NULL)
{
scan = up->right;
up->right = NULL;
break;
}
else
{
scan = up;
up = up->left;
}
}
}
}
_map_->count = 0;
_map_->root = NULL;
}
void tm_free(treemap *_map_)
{
tm_clear(_map_);
free(_map_);
}
bool tm_insert(treemap *_map_, size_t key, size_t value)
{
if (tm_empty(_map_))
{
_map_->root = tm_impl_new_node(key, value);
if (!_map_->root)
return false;
}
else
{
treemap_node *scan = _map_->root;
treemap_node *parent = scan;
while (scan != NULL)
{
parent = scan;
if (_map_->cmp(scan->key, key) > 0)
scan = scan->left;
else if (_map_->cmp(scan->key, key) < 0)
scan = scan->right;
else
return false;
}
treemap_node *node;
if (_map_->cmp(parent->key, key) > 0)
{
parent->left = tm_impl_new_node(key, value);
if (!parent->left)
return false;
parent->left->parent = parent;
node = parent->left;
}
else
{
parent->right = tm_impl_new_node(key, value);
if (!parent->right)
return false;
parent->right->parent = parent;
node = parent->right;
}
tm_impl_rebalance(_map_, node);
}
_map_->count++;
return true;
}
bool tm_remove(treemap *_map_, size_t key, size_t *value)
{
treemap_node *node = tm_impl_get_node(_map_, key);
if (!node)
return false;
*value = node->value;
treemap_node *temp = NULL, *unbalanced = NULL;
bool is_root = node->parent == NULL;
if (node->left == NULL && node->right == NULL)
{
if (is_root)
_map_->root = NULL;
else
{
unbalanced = node->parent;
if (node->parent->right == node)
node->parent->right = NULL;
else
node->parent->left = NULL;
}
free(node);
}
else if (node->left == NULL)
{
if (is_root)
{
_map_->root = node->right;
_map_->root->parent = NULL;
}
else
{
unbalanced = node->parent;
node->right->parent = node->parent;
if (node->parent->right == node)
node->parent->right = node->right;
else
node->parent->left = node->right;
}
free(node);
}
else if (node->right == NULL)
{
if (is_root)
{
_map_->root = node->left;
_map_->root->parent = NULL;
}
else
{
unbalanced = node->parent;
node->left->parent = node->parent;
if (node->parent->right == node)
node->parent->right = node->left;
else
node->parent->left = node->left;
}
free(node);
}
else
{
temp = node->right;
while (temp->left != NULL)
temp = temp->left;
size_t temp_key = temp->key;
size_t temp_val = temp->value;
unbalanced = temp->parent;
if (temp->left == NULL && temp->right == NULL)
{
if (temp->parent->right == temp)
temp->parent->right = NULL;
else
temp->parent->left = NULL;
}
else if (temp->left == NULL)
{
temp->right->parent = temp->parent;
if (temp->parent->right == temp)
temp->parent->right = temp->right;
else
temp->parent->left = temp->right;
}
else if (temp->right == NULL)
{
temp->left->parent = temp->parent;
if (temp->parent->right == temp)
temp->parent->right = temp->left;
else
temp->parent->left = temp->left;
}
free(temp);
node->key = temp_key;
node->value = temp_val;
}
if (unbalanced != NULL)
tm_impl_rebalance(_map_, unbalanced);
_map_->count--;
if (_map_->count == 0)
_map_->root = NULL;
return true;
}
bool tm_insert_if(treemap *_map_, size_t key, size_t value, bool condition)
{
if (condition)
return tm_insert(_map_, key, value);
return false;
}
bool tm_remove_if(treemap *_map_, size_t key, size_t *value, bool condition)
{
if (condition)
return tm_remove(_map_, key, value);
return false;
}
bool tm_max(treemap *_map_, size_t *key, size_t *value)
{
if (tm_empty(_map_))
return false;
treemap_node *scan = _map_->root;
while (scan->right != NULL)
scan = scan->right;
*key = scan->key;
*value = scan->value;
return true;
}
bool tm_min(treemap *_map_, size_t *key, size_t *value)
{
if (tm_empty(_map_))
return false;
treemap_node *scan = _map_->root;
while (scan->left != NULL)
scan = scan->left;
*key = scan->key;
*value = scan->value;
return true;
}
size_t tm_get(treemap *_map_, size_t key)
{
treemap_node *node = tm_impl_get_node(_map_, key);
if (!node)
return tm_impl_default_value();
return node->value;
}
size_t *tm_get_ref(treemap *_map_, size_t key)
{
treemap_node *node = tm_impl_get_node(_map_, key);
if (!node)
return NULL;
return &(node->value);
}
bool tm_contains(treemap *_map_, size_t key)
{
treemap_node *scan = _map_->root;
while (scan != NULL)
{
if (_map_->cmp(scan->key, key) > 0)
scan = scan->left;
else if (_map_->cmp(scan->key, key) < 0)
scan = scan->right;
else
return true;
}
return false;
}
bool tm_empty(treemap *_map_) { return _map_->count == 0; }
size_t tm_count(treemap *_map_) { return _map_->count; }
treemap_iter *tm_iter_new(treemap *target)
{
treemap_iter *iter = malloc(sizeof(treemap_iter));
if (!iter)
return NULL;
tm_iter_init(iter, target);
return iter;
}
void tm_iter_free(treemap_iter *iter) { free(iter); }
void tm_iter_init(treemap_iter *iter, treemap *target)
{
iter->target = target;
iter->index = 0;
iter->start = true;
iter->end = tm_empty(target);
iter->cursor = target->root;
while (iter->cursor->left != NULL)
iter->cursor = iter->cursor->left;
iter->first = iter->cursor;
iter->last = target->root;
while (iter->last->right != NULL)
iter->last = iter->last->right;
}
bool tm_iter_start(treemap_iter *iter) { return tm_empty(iter->target) || iter->start; }
bool tm_iter_end(treemap_iter *iter) { return tm_empty(iter->target) || iter->end; }
void tm_iter_to_start(treemap_iter *iter)
{
iter->index = 0;
iter->start = true;
iter->end = tm_empty(iter->target);
iter->cursor = iter->first;
}
void tm_iter_to_end(treemap_iter *iter)
{
iter->index = iter->target->count - 1;
iter->start = tm_empty(iter->target);
iter->end = true;
iter->cursor = iter->last;
}
bool tm_iter_next(treemap_iter *iter)
{
if (iter->end)
return false;
iter->start = false;
if (iter->cursor->right != NULL)
{
iter->cursor = iter->cursor->right;
while (iter->cursor->left != NULL)
iter->cursor = iter->cursor->left;
iter->index++;
return true;
}
while (true)
{
if (iter->cursor == iter->last)
{
iter->end = true;
return true;
}
if (iter->cursor->parent->left == iter->cursor)
{
iter->cursor = iter->cursor->parent;
iter->index++;
return true;
}
iter->cursor = iter->cursor->parent;
}
}
bool tm_iter_prev(treemap_iter *iter)
{
if (iter->start)
return false;
iter->end = false;
if (iter->cursor->left != NULL)
{
iter->cursor = iter->cursor->left;
while (iter->cursor->right != NULL)
iter->cursor = iter->cursor->right;
iter->index--;
return true;
}
while (true)
{
if (iter->cursor == iter->first)
{
iter->start = true;
return true;
}
if (iter->cursor->parent->right == iter->cursor)
{
iter->cursor = iter->cursor->parent;
iter->index--;
return true;
}
iter->cursor = iter->cursor->parent;
}
}
size_t tm_iter_key(treemap_iter *iter)
{
if (tm_empty(iter->target))
return tm_impl_default_key();
return iter->cursor->key;
}
size_t tm_iter_value(treemap_iter *iter)
{
if (tm_empty(iter->target))
return tm_impl_default_value();
return iter->cursor->value;
}
size_t *tm_iter_rvalue(treemap_iter *iter)
{
if (tm_empty(iter->target))
return NULL;
return &(iter->cursor->value);
}
size_t tm_iter_index(treemap_iter *iter) { return iter->index; }
static treemap_node *tm_impl_new_node(size_t key, size_t value)
{
treemap_node *node = malloc(sizeof(treemap_node));
if (!node)
return NULL;
node->key = key;
node->value = value;
node->right = NULL;
node->left = NULL;
node->parent = NULL;
node->height = 0;
return node;
}
static treemap_node *tm_impl_get_node(treemap *_map_, size_t key)
{
if (tm_empty(_map_))
return NULL;
treemap_node *scan = _map_->root;
while (scan != NULL)
{
if (_map_->cmp(scan->key, key) > 0)
scan = scan->left;
else if (_map_->cmp(scan->key, key) < 0)
scan = scan->right;
else
return scan;
}
return NULL;
}
static unsigned char tm_impl_h(treemap_node *node)
{
if (node == NULL)
return 0;
return node->height;
}
static unsigned char tm_impl_hupdate(treemap_node *node)
{
if (node == NULL)
return 0;
unsigned char h_l = tm_impl_h(node->left);
unsigned char h_r = tm_impl_h(node->right);
return 1 + (h_l > h_r ? h_l : h_r);
}
static void tm_impl_rotate_right(treemap_node **Z)
{
treemap_node *root = *Z;
treemap_node *new_root = root->left;
if (root->parent != NULL)
{
if (root->parent->left == root)
root->parent->left = new_root;
else
root->parent->right = new_root;
}
new_root->parent = root->parent;
root->parent = new_root;
root->left = new_root->right;
if (root->left)
root->left->parent = root;
new_root->right = root;
root->height = tm_impl_hupdate(root);
new_root->height = tm_impl_hupdate(new_root);
*Z = new_root;
}
static void tm_impl_rotate_left(treemap_node **Z)
{
treemap_node *root = *Z;
treemap_node *new_root = root->right;
if (root->parent != NULL)
{
if (root->parent->right == root)
root->parent->right = new_root;
else
root->parent->left = new_root;
}
new_root->parent = root->parent;
root->parent = new_root;
root->right = new_root->left;
if (root->right)
root->right->parent = root;
new_root->left = root;
root->height = tm_impl_hupdate(root);
new_root->height = tm_impl_hupdate(new_root);
*Z = new_root;
}
static void tm_impl_rebalance(treemap *_map_, treemap_node *node)
{
treemap_node *scan = node, *child = NULL;
int balance;
bool is_root = false;
while (scan != NULL)
{
if (scan->parent == NULL)
is_root = true;
scan->height = tm_impl_hupdate(scan);
balance = tm_impl_h(scan->right) - tm_impl_h(scan->left);
if (balance >= 2)
{
child = scan->right;
if (tm_impl_h(child->right) < tm_impl_h(child->left))
tm_impl_rotate_right(&(scan->right));
tm_impl_rotate_left(&scan);
}
else if (balance <= -2)
{
child = scan->left;
if (tm_impl_h(child->left) < tm_impl_h(child->right))
tm_impl_rotate_left(&(scan->left));
tm_impl_rotate_right(&scan);
}
if (is_root)
{
_map_->root = scan;
is_root = false;
}
scan = scan->parent;
}
}
static treemap_iter tm_impl_it_start(treemap *_map_)
{
treemap_iter iter;
tm_iter_init(&iter, _map_);
return iter;
}
static treemap_iter tm_impl_it_end(treemap *_map_)
{
treemap_iter iter;
tm_iter_init(&iter, _map_);
tm_iter_to_end(&iter);
return iter;
}
+688
View File
@@ -0,0 +1,688 @@
#include "cmc/treeset.h"
typedef struct treeset_s
{
struct treeset_node_s *root;
size_t count;
int (*cmp)(size_t, size_t);
struct treeset_iter_s (*it_start)(struct treeset_s *);
struct treeset_iter_s (*it_end)(struct treeset_s *);
} treeset, *treeset_ptr;
typedef struct treeset_node_s
{
size_t value;
unsigned char height;
struct treeset_node_s *right;
struct treeset_node_s *left;
struct treeset_node_s *parent;
} treeset_node, *treeset_node_ptr;
typedef struct treeset_iter_s
{
struct treeset_s *target;
struct treeset_node_s *cursor;
struct treeset_node_s *first;
struct treeset_node_s *last;
size_t index;
bool start;
bool end;
} treeset_iter, *treeset_iter_ptr;
treeset *ts_new(int (*compare)(size_t, size_t));
void ts_clear(treeset *_set_);
void ts_free(treeset *_set_);
bool ts_insert(treeset *_set_, size_t element);
bool ts_remove(treeset *_set_, size_t element);
bool ts_insert_if(treeset *_set_, size_t element, bool condition);
bool ts_remove_if(treeset *_set_, size_t element, bool condition);
bool ts_max(treeset *_set_, size_t *value);
bool ts_min(treeset *_set_, size_t *value);
bool ts_contains(treeset *_set_, size_t element);
bool ts_empty(treeset *_set_);
size_t ts_count(treeset *_set_);
treeset *ts_union(treeset *_set1_, treeset *_set2_);
treeset *ts_intersection(treeset *_set1_, treeset *_set2_);
treeset *ts_difference(treeset *_set1_, treeset *_set2_);
treeset *ts_symmetric_difference(treeset *_set1_, treeset *_set2_);
bool ts_is_subset(treeset *_set1_, treeset *_set2_);
bool ts_is_superset(treeset *_set1_, treeset *_set2_);
bool ts_is_proper_subset(treeset *_set1_, treeset *_set2_);
bool ts_is_proper_superset(treeset *_set1_, treeset *_set2_);
bool ts_is_disjointset(treeset *_set1_, treeset *_set2_);
treeset_iter *ts_iter_new(treeset *target);
void ts_iter_free(treeset_iter *iter);
void ts_iter_init(treeset_iter *iter, treeset *target);
bool ts_iter_start(treeset_iter *iter);
bool ts_iter_end(treeset_iter *iter);
void ts_iter_to_start(treeset_iter *iter);
void ts_iter_to_end(treeset_iter *iter);
bool ts_iter_next(treeset_iter *iter);
bool ts_iter_prev(treeset_iter *iter);
size_t ts_iter_value(treeset_iter *iter);
size_t ts_iter_index(treeset_iter *iter);
static inline size_t ts_impl_default_value(void)
{
size_t _empty_value_;
memset(&_empty_value_, 0, sizeof(size_t));
return _empty_value_;
}
static treeset_node *ts_impl_new_node(size_t element);
static treeset_node *ts_impl_get_node(treeset *_set_, size_t element);
static unsigned char ts_impl_h(treeset_node *node);
static unsigned char ts_impl_hupdate(treeset_node *node);
static void ts_impl_rotate_right(treeset_node **Z);
static void ts_impl_rotate_left(treeset_node **Z);
static void ts_impl_rebalance(treeset *_set_, treeset_node *node);
static treeset_iter ts_impl_it_start(treeset *_set_);
static treeset_iter ts_impl_it_end(treeset *_set_);
treeset *ts_new(int (*compare)(size_t, size_t))
{
treeset *_set_ = malloc(sizeof(treeset));
if (!_set_)
return NULL;
_set_->count = 0;
_set_->root = NULL;
_set_->cmp = compare;
_set_->it_start = ts_impl_it_start;
_set_->it_end = ts_impl_it_end;
return _set_;
}
void ts_clear(treeset *_set_)
{
treeset_node *scan = _set_->root;
treeset_node *up = NULL;
while (scan != NULL)
{
if (scan->left != NULL)
{
treeset_node *left = scan->left;
scan->left = up;
up = scan;
scan = left;
}
else if (scan->right != NULL)
{
treeset_node *right = scan->right;
scan->left = up;
scan->right = NULL;
up = scan;
scan = right;
}
else
{
if (up == NULL)
{
free(scan);
scan = NULL;
}
while (up != NULL)
{
free(scan);
if (up->right != NULL)
{
scan = up->right;
up->right = NULL;
break;
}
else
{
scan = up;
up = up->left;
}
}
}
}
_set_->count = 0;
_set_->root = NULL;
}
void ts_free(treeset *_set_)
{
ts_clear(_set_);
free(_set_);
}
bool ts_insert(treeset *_set_, size_t element)
{
if (ts_empty(_set_))
{
_set_->root = ts_impl_new_node(element);
if (!_set_->root)
return false;
}
else
{
treeset_node *scan = _set_->root;
treeset_node *parent = scan;
while (scan != NULL)
{
parent = scan;
if (_set_->cmp(scan->value, element) > 0)
scan = scan->left;
else if (_set_->cmp(scan->value, element) < 0)
scan = scan->right;
else
return false;
}
treeset_node *node;
if (_set_->cmp(parent->value, element) > 0)
{
parent->left = ts_impl_new_node(element);
if (!parent->left)
return false;
parent->left->parent = parent;
node = parent->left;
}
else
{
parent->right = ts_impl_new_node(element);
if (!parent->right)
return false;
parent->right->parent = parent;
node = parent->right;
}
ts_impl_rebalance(_set_, node);
}
_set_->count++;
return true;
}
bool ts_remove(treeset *_set_, size_t element)
{
treeset_node *node = ts_impl_get_node(_set_, element);
if (!node)
return false;
treeset_node *temp = NULL, *unbalanced = NULL;
bool is_root = node->parent == NULL;
if (node->left == NULL && node->right == NULL)
{
if (is_root)
_set_->root = NULL;
else
{
unbalanced = node->parent;
if (node->parent->right == node)
node->parent->right = NULL;
else
node->parent->left = NULL;
}
free(node);
}
else if (node->left == NULL)
{
if (is_root)
{
_set_->root = node->right;
_set_->root->parent = NULL;
}
else
{
unbalanced = node->parent;
node->right->parent = node->parent;
if (node->parent->right == node)
node->parent->right = node->right;
else
node->parent->left = node->right;
}
free(node);
}
else if (node->right == NULL)
{
if (is_root)
{
_set_->root = node->left;
_set_->root->parent = NULL;
}
else
{
unbalanced = node->parent;
node->left->parent = node->parent;
if (node->parent->right == node)
node->parent->right = node->left;
else
node->parent->left = node->left;
}
free(node);
}
else
{
temp = node->right;
while (temp->left != NULL)
temp = temp->left;
size_t temp_value = temp->value;
unbalanced = temp->parent;
if (temp->left == NULL && temp->right == NULL)
{
if (temp->parent->right == temp)
temp->parent->right = NULL;
else
temp->parent->left = NULL;
}
else if (temp->left == NULL)
{
temp->right->parent = temp->parent;
if (temp->parent->right == temp)
temp->parent->right = temp->right;
else
temp->parent->left = temp->right;
}
else if (temp->right == NULL)
{
temp->left->parent = temp->parent;
if (temp->parent->right == temp)
temp->parent->right = temp->left;
else
temp->parent->left = temp->left;
}
free(temp);
node->value = temp_value;
}
if (unbalanced != NULL)
ts_impl_rebalance(_set_, unbalanced);
_set_->count--;
if (_set_->count == 0)
_set_->root = NULL;
return true;
}
bool ts_insert_if(treeset *_set_, size_t element, bool condition)
{
if (condition)
return ts_insert(_set_, element);
return false;
}
bool ts_remove_if(treeset *_set_, size_t element, bool condition)
{
if (condition)
return ts_remove(_set_, element);
return false;
}
bool ts_max(treeset *_set_, size_t *value)
{
if (ts_empty(_set_))
return false;
treeset_node *scan = _set_->root;
while (scan->right != NULL)
scan = scan->right;
*value = scan->value;
return true;
}
bool ts_min(treeset *_set_, size_t *value)
{
if (ts_empty(_set_))
return false;
treeset_node *scan = _set_->root;
while (scan->left != NULL)
scan = scan->left;
*value = scan->value;
return true;
}
bool ts_contains(treeset *_set_, size_t element)
{
treeset_node *scan = _set_->root;
while (scan != NULL)
{
if (_set_->cmp(scan->value, element) > 0)
scan = scan->left;
else if (_set_->cmp(scan->value, element) < 0)
scan = scan->right;
else
return true;
}
return false;
}
bool ts_empty(treeset *_set_) { return _set_->count == 0; }
size_t ts_count(treeset *_set_) { return _set_->count; }
treeset *ts_union(treeset *_set1_, treeset *_set2_)
{
treeset *_set_r_ = ts_new(_set1_->cmp);
if (!_set_r_)
return false;
treeset_iter iter1, iter2;
ts_iter_init(&iter1, _set1_);
ts_iter_init(&iter2, _set2_);
for (ts_iter_to_start(&iter1); !ts_iter_end(&iter1); ts_iter_next(&iter1))
{
ts_insert(_set_r_, ts_iter_value(&iter1));
}
for (ts_iter_to_start(&iter2); !ts_iter_end(&iter2); ts_iter_next(&iter2))
{
ts_insert(_set_r_, ts_iter_value(&iter2));
}
return _set_r_;
}
treeset *ts_intersection(treeset *_set1_, treeset *_set2_)
{
treeset *_set_r_ = ts_new(_set1_->cmp);
if (!_set_r_)
return false;
treeset *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_;
treeset *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_;
treeset_iter iter;
ts_iter_init(&iter, _set_A_);
for (ts_iter_to_start(&iter); !ts_iter_end(&iter); ts_iter_next(&iter))
{
size_t value = ts_iter_value(&iter);
if (ts_impl_get_node(_set_B_, value) != NULL)
ts_insert(_set_r_, value);
}
return _set_r_;
}
treeset *ts_difference(treeset *_set1_, treeset *_set2_)
{
treeset *_set_r_ = ts_new(_set1_->cmp);
if (!_set_r_)
return false;
treeset_iter iter;
ts_iter_init(&iter, _set1_);
for (ts_iter_to_start(&iter); !ts_iter_end(&iter); ts_iter_next(&iter))
{
size_t value = ts_iter_value(&iter);
if (ts_impl_get_node(_set2_, value) == NULL)
ts_insert(_set_r_, value);
}
return _set_r_;
}
treeset *ts_symmetric_difference(treeset *_set1_, treeset *_set2_)
{
treeset *_set_r_ = ts_new(_set1_->cmp);
if (!_set_r_)
return false;
treeset_iter iter1, iter2;
ts_iter_init(&iter1, _set1_);
ts_iter_init(&iter2, _set2_);
for (ts_iter_to_start(&iter1); !ts_iter_end(&iter1); ts_iter_next(&iter1))
{
size_t value = ts_iter_value(&iter1);
if (ts_impl_get_node(_set2_, value) == NULL)
ts_insert(_set_r_, value);
}
for (ts_iter_to_start(&iter2); !ts_iter_end(&iter2); ts_iter_next(&iter2))
{
size_t value = ts_iter_value(&iter2);
if (ts_impl_get_node(_set1_, value) == NULL)
ts_insert(_set_r_, value);
}
return _set_r_;
}
bool ts_is_subset(treeset *_set1_, treeset *_set2_)
{
if (ts_count(_set1_) > ts_count(_set2_))
return false;
if (ts_empty(_set1_))
return true;
treeset_iter iter;
ts_iter_init(&iter, _set1_);
for (ts_iter_to_start(&iter); !ts_iter_end(&iter); ts_iter_next(&iter))
{
size_t value = ts_iter_value(&iter);
if (!ts_contains(_set2_, value))
return false;
}
return true;
}
bool ts_is_superset(treeset *_set1_, treeset *_set2_) { return ts_is_subset(_set2_, _set1_); }
bool ts_is_proper_subset(treeset *_set1_, treeset *_set2_)
{
if (ts_count(_set1_) >= ts_count(_set2_))
return false;
if (ts_empty(_set1_))
{
if (!ts_empty(_set2_))
return true;
else
return false;
}
treeset_iter iter;
ts_iter_init(&iter, _set1_);
for (ts_iter_to_start(&iter); !ts_iter_end(&iter); ts_iter_next(&iter))
{
size_t value = ts_iter_value(&iter);
if (!ts_contains(_set2_, value))
return false;
}
return true;
}
bool ts_is_proper_superset(treeset *_set1_, treeset *_set2_) { return ts_is_proper_subset(_set2_, _set1_); }
bool ts_is_disjointset(treeset *_set1_, treeset *_set2_)
{
if (ts_empty(_set1_))
return true;
treeset_iter iter;
ts_iter_init(&iter, _set1_);
for (ts_iter_to_start(&iter); !ts_iter_end(&iter); ts_iter_next(&iter))
{
size_t value = ts_iter_value(&iter);
if (ts_contains(_set2_, value))
return false;
}
return true;
}
treeset_iter *ts_iter_new(treeset *target)
{
treeset_iter *iter = malloc(sizeof(treeset_iter));
if (!iter)
return NULL;
ts_iter_init(iter, target);
return iter;
}
void ts_iter_free(treeset_iter *iter) { free(iter); }
void ts_iter_init(treeset_iter *iter, treeset *target)
{
iter->target = target;
iter->index = 0;
iter->start = true;
iter->end = ts_empty(target);
iter->cursor = target->root;
while (iter->cursor->left != NULL)
iter->cursor = iter->cursor->left;
iter->first = iter->cursor;
iter->last = target->root;
while (iter->last->right != NULL)
iter->last = iter->last->right;
}
bool ts_iter_start(treeset_iter *iter) { return ts_empty(iter->target) || iter->start; }
bool ts_iter_end(treeset_iter *iter) { return ts_empty(iter->target) || iter->end; }
void ts_iter_to_start(treeset_iter *iter)
{
iter->index = 0;
iter->start = true;
iter->end = ts_empty(iter->target);
iter->cursor = iter->first;
}
void ts_iter_to_end(treeset_iter *iter)
{
iter->index = iter->target->count - 1;
iter->start = ts_empty(iter->target);
iter->end = true;
iter->cursor = iter->last;
}
bool ts_iter_next(treeset_iter *iter)
{
if (iter->end)
return false;
iter->start = ts_empty(iter->target);
if (iter->cursor->right != NULL)
{
iter->cursor = iter->cursor->right;
while (iter->cursor->left != NULL)
iter->cursor = iter->cursor->left;
iter->index++;
return true;
}
while (true)
{
if (iter->cursor == iter->last)
{
iter->end = true;
return true;
}
if (iter->cursor->parent->left == iter->cursor)
{
iter->cursor = iter->cursor->parent;
iter->index++;
return true;
}
iter->cursor = iter->cursor->parent;
}
}
bool ts_iter_prev(treeset_iter *iter)
{
if (iter->start)
return false;
iter->end = ts_empty(iter->target);
if (iter->cursor->left != NULL)
{
iter->cursor = iter->cursor->left;
while (iter->cursor->right != NULL)
iter->cursor = iter->cursor->right;
iter->index--;
return true;
}
while (true)
{
if (iter->cursor == iter->first)
{
iter->start = true;
return true;
}
if (iter->cursor->parent->right == iter->cursor)
{
iter->cursor = iter->cursor->parent;
iter->index--;
return true;
}
iter->cursor = iter->cursor->parent;
}
}
size_t ts_iter_value(treeset_iter *iter)
{
if (ts_empty(iter->target))
return ts_impl_default_value();
return iter->cursor->value;
}
size_t ts_iter_index(treeset_iter *iter) { return iter->index; }
static treeset_node *ts_impl_new_node(size_t element)
{
treeset_node *node = malloc(sizeof(treeset_node));
if (!node)
return NULL;
node->value = element;
node->right = NULL;
node->left = NULL;
node->parent = NULL;
node->height = 0;
return node;
}
static treeset_node *ts_impl_get_node(treeset *_set_, size_t element)
{
if (ts_empty(_set_))
return NULL;
treeset_node *scan = _set_->root;
while (scan != NULL)
{
if (_set_->cmp(scan->value, element) > 0)
scan = scan->left;
else if (_set_->cmp(scan->value, element) < 0)
scan = scan->right;
else
return scan;
}
return NULL;
}
static unsigned char ts_impl_h(treeset_node *node)
{
if (node == NULL)
return 0;
return node->height;
}
static unsigned char ts_impl_hupdate(treeset_node *node)
{
if (node == NULL)
return 0;
unsigned char h_l = ts_impl_h(node->left);
unsigned char h_r = ts_impl_h(node->right);
return 1 + (h_l > h_r ? h_l : h_r);
}
static void ts_impl_rotate_right(treeset_node **Z)
{
treeset_node *root = *Z;
treeset_node *new_root = root->left;
if (root->parent != NULL)
{
if (root->parent->left == root)
root->parent->left = new_root;
else
root->parent->right = new_root;
}
new_root->parent = root->parent;
root->parent = new_root;
root->left = new_root->right;
if (root->left)
root->left->parent = root;
new_root->right = root;
root->height = ts_impl_hupdate(root);
new_root->height = ts_impl_hupdate(new_root);
*Z = new_root;
}
static void ts_impl_rotate_left(treeset_node **Z)
{
treeset_node *root = *Z;
treeset_node *new_root = root->right;
if (root->parent != NULL)
{
if (root->parent->right == root)
root->parent->right = new_root;
else
root->parent->left = new_root;
}
new_root->parent = root->parent;
root->parent = new_root;
root->right = new_root->left;
if (root->right)
root->right->parent = root;
new_root->left = root;
root->height = ts_impl_hupdate(root);
new_root->height = ts_impl_hupdate(new_root);
*Z = new_root;
}
static void ts_impl_rebalance(treeset *_set_, treeset_node *node)
{
treeset_node *scan = node, *child = NULL;
int balance;
bool is_root = false;
while (scan != NULL)
{
if (scan->parent == NULL)
is_root = true;
scan->height = ts_impl_hupdate(scan);
balance = ts_impl_h(scan->right) - ts_impl_h(scan->left);
if (balance >= 2)
{
child = scan->right;
if (ts_impl_h(child->right) < ts_impl_h(child->left))
ts_impl_rotate_right(&(scan->right));
ts_impl_rotate_left(&scan);
}
else if (balance <= -2)
{
child = scan->left;
if (ts_impl_h(child->left) < ts_impl_h(child->right))
ts_impl_rotate_left(&(scan->left));
ts_impl_rotate_right(&scan);
}
if (is_root)
{
_set_->root = scan;
is_root = false;
}
scan = scan->parent;
}
}
static treeset_iter ts_impl_it_start(treeset *_set_)
{
treeset_iter iter;
ts_iter_init(&iter, _set_);
return iter;
}
static treeset_iter ts_impl_it_end(treeset *_set_)
{
treeset_iter iter;
ts_iter_init(&iter, _set_);
ts_iter_to_end(&iter);
return iter;
}
+74
View File
@@ -0,0 +1,74 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/deque.c"
CMC_CREATE_UNIT(deque_test, true, {
CMC_CREATE_TEST(new, {
deque *d = d_new(1000000);
cmc_assert_not_equals(ptr, NULL, d);
bool passed = d->capacity == 1000000 && d->count == 0 && d->buffer;
cmc_assert_equals(size_t, 1000000, d->capacity);
cmc_assert_equals(size_t, 0, d_count(d));
cmc_assert_not_equals(ptr, NULL, d->buffer);
CMC_TEST_PASS_ELSE_FAIL(passed);
d_free(d);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
deque *d = d_new(0);
cmc_assert_equals(ptr, NULL, d);
CMC_TEST_PASS_ELSE_FAIL(d == NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
deque *d = d_new(UINT64_MAX);
cmc_assert_equals(ptr, NULL, d);
CMC_TEST_PASS_ELSE_FAIL(d == NULL);
});
CMC_CREATE_TEST(clear[count capacity], {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
for (size_t i = 0; i < 50; i++)
d_push_back(d, i);
cmc_assert_equals(size_t, 50, d_count(d));
d_clear(d);
cmc_assert_equals(size_t, 0, d_count(d));
cmc_assert_equals(size_t, 100, d_capacity(d));
CMC_TEST_PASS_ELSE_FAIL(d_count(d) == 0 && d_capacity(d) == 100);
d_free(d);
});
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
deque *d = d_new(1);
cmc_assert_not_equals(ptr, NULL, d);
for (size_t i = 0; i < 50; i++)
d_push_back(d, i);
cmc_assert_equals(size_t, 50, d_count(d));
cmc_assert_lesser_equals(size_t, d_capacity(d), d_count(d));
CMC_TEST_PASS_ELSE_FAIL(d_count(d) == 50 && d_count(d) <= d_capacity(d));
d_free(d);
});
});
+56
View File
@@ -0,0 +1,56 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/hashmap.c"
#include "utl.c"
CMC_CREATE_UNIT(hashmap_test, true, {
CMC_CREATE_TEST(new, {
hashmap *map = hm_new(943722, 0.6, cmp, hash);
bool passed = (map->capacity >= (943722 / 0.6)) && map->count == 0 && map->buffer;
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_greater_equals(size_t, (943722 / 0.6), hm_capacity(map));
CMC_TEST_PASS_ELSE_FAIL(passed);
hm_free(map);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
hashmap *map = hm_new(0, 0.6, cmp, hash);
cmc_assert_equals(ptr, NULL, map);
CMC_TEST_PASS_ELSE_FAIL(map == NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
hashmap *map = hm_new(UINT64_MAX, 0.6, cmp, hash);
cmc_assert_equals(ptr, NULL, map);
CMC_TEST_PASS_ELSE_FAIL(map == NULL);
});
CMC_CREATE_TEST(clear[count capacity], {
hashmap *map = hm_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 50; i++)
hm_insert(map, i, i);
cmc_assert_equals(size_t, 50, hm_count(map));
hm_clear(map);
cmc_assert_equals(size_t, 0, hm_count(map));
CMC_TEST_PASS_ELSE_FAIL(hm_count(map) == 0);
hm_free(map);
});
});
+56
View File
@@ -0,0 +1,56 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/hashset.c"
#include "utl.c"
CMC_CREATE_UNIT(hashset_test, true, {
CMC_CREATE_TEST(new, {
hashset *set = hs_new(943722, 0.6, cmp, hash);
bool passed = (set->capacity >= (943722 / 0.6)) && set->count == 0 && set->buffer;
cmc_assert_not_equals(ptr, NULL, set);
cmc_assert(hs_capacity(set) > (943722 / 0.6));
CMC_TEST_PASS_ELSE_FAIL(passed);
hs_free(set);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
hashset *set = hs_new(0, 0.6, cmp, hash);
cmc_assert_equals(ptr, NULL, set);
CMC_TEST_PASS_ELSE_FAIL(set == NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
hashset *set = hs_new(UINT64_MAX, 0.6, cmp, hash);
cmc_assert_equals(ptr, NULL, set);
CMC_TEST_PASS_ELSE_FAIL(set == NULL);
});
CMC_CREATE_TEST(clear[count capacity], {
hashset *set = hs_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
for (size_t i = 0; i < 50; i++)
hs_insert(set, i);
cmc_assert_equals(size_t, 50, hs_count(set));
hs_clear(set);
cmc_assert_equals(size_t, 0, hs_count(set));
CMC_TEST_PASS_ELSE_FAIL(hs_count(set) == 0);
hs_free(set);
});
});
+75
View File
@@ -0,0 +1,75 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/heap.c"
#include "utl.c"
CMC_CREATE_UNIT(heap_test, true, {
CMC_CREATE_TEST(new, {
heap *h = h_new(1000000, MaxHeap, cmp);
cmc_assert_not_equals(ptr, NULL, h);
bool passed = h->capacity == 1000000 && h->count == 0 && h->buffer;
cmc_assert_equals(size_t, 1000000, h->capacity);
cmc_assert_equals(size_t, 0, h_count(h));
cmc_assert_not_equals(ptr, NULL, h->buffer);
CMC_TEST_PASS_ELSE_FAIL(passed);
h_free(h);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
heap *h = h_new(0, MaxHeap, cmp);
cmc_assert_equals(ptr, NULL, h);
CMC_TEST_PASS_ELSE_FAIL(h == NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
heap *h = h_new(UINT64_MAX, MaxHeap, cmp);
cmc_assert_equals(ptr, NULL, h);
CMC_TEST_PASS_ELSE_FAIL(h == NULL);
});
CMC_CREATE_TEST(clear[count capacity], {
heap *h = h_new(100, MaxHeap, cmp);
cmc_assert_not_equals(ptr, NULL, h);
for (size_t i = 0; i < 50; i++)
h_insert(h, i);
cmc_assert_equals(size_t, 50, h_count(h));
h_clear(h);
cmc_assert_equals(size_t, 0, h_count(h));
cmc_assert_equals(size_t, 100, h_capacity(h));
CMC_TEST_PASS_ELSE_FAIL(h_count(h) == 0 && h_capacity(h) == 100);
h_free(h);
});
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
heap *h = h_new(1, MaxHeap, cmp);
cmc_assert_not_equals(ptr, NULL, h);
for (size_t i = 0; i < 50; i++)
h_insert(h, i);
cmc_assert_equals(size_t, 50, h_count(h));
CMC_TEST_PASS_ELSE_FAIL(h_count(h) == 50);
h_free(h);
});
});
+93
View File
@@ -0,0 +1,93 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/linkedlist.c"
CMC_CREATE_UNIT(linkedlist_test, true, {
CMC_CREATE_TEST(new, {
linkedlist *ll = ll_new();
cmc_assert_not_equals(ptr, NULL, ll);
bool passed = ll->count == 0 && ll->head == NULL && ll->tail == NULL;
cmc_assert_equals(size_t, 0, ll_count(ll));
cmc_assert_equals(ptr, NULL, ll->head);
cmc_assert_equals(ptr, NULL, ll->tail);
CMC_TEST_PASS_ELSE_FAIL(passed);
ll_free(ll);
});
CMC_CREATE_TEST(clear[count capacity], {
linkedlist *ll = ll_new();
cmc_assert_not_equals(ptr, NULL, ll);
for (size_t i = 0; i < 50; i++)
ll_push_back(ll, i);
cmc_assert_equals(size_t, 50, ll_count(ll));
ll_clear(ll);
cmc_assert_equals(size_t, 0, ll_count(ll));
CMC_TEST_PASS_ELSE_FAIL(ll_count(ll) == 0);
ll_free(ll);
});
CMC_CREATE_TEST(clear[edge_case:count = 0], {
linkedlist *ll = ll_new();
cmc_assert_not_equals(ptr, NULL, ll);
ll_clear(ll);
cmc_assert_equals(size_t, 0, ll_count(ll));
CMC_TEST_PASS_ELSE_FAIL(ll_count(ll) == 0);
ll_free(ll);
});
CMC_CREATE_TEST(push_front[count], {
linkedlist *ll = ll_new();
cmc_assert_not_equals(ptr, NULL, ll);
ll_push_front(ll, 1);
cmc_assert_not_equals(ptr, NULL, ll->head);
cmc_assert_not_equals(ptr, NULL, ll->tail);
cmc_assert_equals(size_t, 1, ll_count(ll));
CMC_TEST_PASS_ELSE_FAIL(ll->head && ll->tail && ll_count(ll) == 1);
ll_free(ll);
});
CMC_CREATE_TEST(push_front[item_preservation], {
linkedlist *ll = ll_new();
cmc_assert_not_equals(ptr, NULL, ll);
for (size_t i = 0; i < 200; i++)
ll_push_front(ll, i);
bool passed = true;
for (size_t i = 0; i < ll_count(ll); i++)
{
passed = passed && ll_get(ll, i) == (ll_count(ll) - i - 1);
cmc_assert_equals(size_t, ll_get(ll, i), ll_count(ll) - i - 1);
}
CMC_TEST_PASS_ELSE_FAIL(passed && ll_count(ll) == 200);
ll_free(ll);
});
});
+420
View File
@@ -0,0 +1,420 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/list.c"
CMC_CREATE_UNIT(list_test, true, {
CMC_CREATE_TEST(new, {
list *l = l_new(1000000);
cmc_assert_not_equals(ptr, NULL, l);
bool passed = l->capacity == 1000000 && l->count == 0 && l->buffer;
cmc_assert_equals(size_t, 1000000, l->capacity);
cmc_assert_equals(size_t, 0, l_count(l));
cmc_assert_not_equals(ptr, NULL, l->buffer);
CMC_TEST_PASS_ELSE_FAIL(passed);
l_free(l);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
list *l = l_new(0);
cmc_assert_equals(ptr, NULL, l);
CMC_TEST_PASS_ELSE_FAIL(l == NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
list *l = l_new(UINT64_MAX);
cmc_assert_equals(ptr, NULL, l);
CMC_TEST_PASS_ELSE_FAIL(l == NULL);
});
CMC_CREATE_TEST(new_from[count item_preservation], {
size_t v[5];
for (size_t i = 0; i < 5; i++)
{
v[i] = i;
}
list *l = l_new_from(v, 5);
cmc_assert_not_equals(ptr, NULL, l);
bool passed = true;
for (size_t i = 0; i < 5; i++)
{
cmc_assert_equals(size_t, i, l_get(l, i));
passed = passed && l_get(l, i) == i;
}
CMC_TEST_PASS_ELSE_FAIL(passed && l_count(l) == 5);
l_free(l);
});
CMC_CREATE_TEST(new_from[edge_case:size = 1], {
size_t a = 10;
size_t *values = &a;
list *l = l_new_from(values, 1);
cmc_assert_not_equals(ptr, NULL, l);
CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 1);
l_free(l);
});
CMC_CREATE_TEST(clear[count capacity], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 50; i++)
l_push_back(l, i);
cmc_assert_equals(size_t, 50, l_count(l));
l_clear(l);
cmc_assert_equals(size_t, 0, l_count(l));
cmc_assert_equals(size_t, 100, l_capacity(l));
CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 0 && l_capacity(l) == 100);
l_free(l);
});
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
list *l = l_new(1);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 100; i++)
l_push_back(l, i);
cmc_assert_equals(size_t, 100, l_count(l));
bool passed = true;
for (size_t i = 0; i < 100; i++)
{
passed = passed && l_get(l, i) == i;
cmc_assert_equals(size_t, i, l_get(l, i));
}
CMC_TEST_PASS_ELSE_FAIL(passed);
l_free(l);
});
CMC_CREATE_TEST(push_front[count], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 250; i++)
cmc_assert(l_push_front(l, i));
cmc_assert_equals(size_t, 250, l_count(l));
CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 250);
l_free(l);
});
CMC_CREATE_TEST(push_front[capacity], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 250; i++)
cmc_assert(l_push_front(l, i));
cmc_assert_lesser_equals(size_t, l_capacity(l), l_count(l));
CMC_TEST_PASS_ELSE_FAIL(l_count(l) <= l_capacity(l));
l_free(l);
});
CMC_CREATE_TEST(push_front[item_preservation], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 250; i++)
cmc_assert(l_push_front(l, i));
bool passed = true;
for (size_t i = 0; i < l_count(l); i++)
{
passed = passed && l_get(l, i) == (l_count(l) - i - 1);
cmc_assert_equals(size_t, l_get(l, i), l_count(l) - i - 1);
}
CMC_TEST_PASS_ELSE_FAIL(passed);
l_free(l);
});
CMC_CREATE_TEST(push[count], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(l_push_back(l, 0));
cmc_assert(l_push_back(l, 249));
for (size_t i = 1; i < 249; i++)
cmc_assert(l_push(l, i, l_count(l) - 1));
cmc_assert_equals(size_t, 250, l_count(l));
CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 250);
l_free(l);
});
CMC_CREATE_TEST(push[capacity], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(l_push_back(l, 0));
cmc_assert(l_push_back(l, 249));
for (size_t i = 1; i < 249; i++)
cmc_assert(l_push(l, i, l_count(l) - 1));
cmc_assert_lesser_equals(size_t, l_capacity(l), l_count(l));
CMC_TEST_PASS_ELSE_FAIL(l_count(l) <= l_capacity(l));
l_free(l);
});
CMC_CREATE_TEST(push[item_preservation], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(l_push_back(l, 0));
cmc_assert(l_push_back(l, 249));
for (size_t i = 1; i < 249; i++)
cmc_assert(l_push(l, i, l_count(l) - 1));
bool passed = true;
for (size_t i = 0; i < l_count(l); i++)
{
passed = passed && l_get(l, i) == i;
cmc_assert_equals(size_t, l_get(l, i), i);
}
CMC_TEST_PASS_ELSE_FAIL(passed);
l_free(l);
});
CMC_CREATE_TEST(push_back[count], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 250; i++)
cmc_assert(l_push_back(l, i));
cmc_assert_equals(size_t, 250, l_count(l));
CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 250);
l_free(l);
});
CMC_CREATE_TEST(push_back[capacity], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 250; i++)
cmc_assert(l_push_back(l, i));
cmc_assert_lesser_equals(size_t, l_capacity(l), l_count(l));
CMC_TEST_PASS_ELSE_FAIL(l_count(l) <= l_capacity(l));
l_free(l);
});
CMC_CREATE_TEST(push_back[item_preservation], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 250; i++)
cmc_assert(l_push_back(l, i));
bool passed = true;
for (size_t i = 0; i < l_count(l); i++)
{
passed = passed && l_get(l, i) == i;
cmc_assert_equals(size_t, l_get(l, i), i);
}
CMC_TEST_PASS_ELSE_FAIL(passed);
l_free(l);
});
CMC_CREATE_TEST(pop_front[count], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 250; i++)
l_push_back(l, i);
cmc_assert(l_pop_front(l));
CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 250 - 1);
l_free(l);
});
CMC_CREATE_TEST(pop_front[item_preservation], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 250; i++)
l_push_back(l, i);
bool passed = l_pop_front(l);
for (size_t i = 0; i < l_count(l); i++)
{
passed = passed && l_get(l, i) == i + 1;
cmc_assert_equals(size_t, l_get(l, i), i + 1);
}
CMC_TEST_PASS_ELSE_FAIL(passed);
l_free(l);
});
CMC_CREATE_TEST(pop_front[edge_case:count = 0], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(!l_pop_front(l));
CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 0);
l_free(l);
});
CMC_CREATE_TEST(pop_front[edge_case:count = 1], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(l_push_back(l, 10));
cmc_assert(l_pop_front(l));
CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 0);
l_free(l);
});
CMC_CREATE_TEST(pop_front[buffer_clear], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(l_push_back(l, 1));
cmc_assert(l_push_front(l, 2));
bool passed = l_pop_front(l) && l->buffer[1] == 0;
cmc_assert_equals(size_t, 0, l->buffer[1]);
CMC_TEST_PASS_ELSE_FAIL(passed && l_count(l) == 1);
l_free(l);
});
CMC_CREATE_TEST(pop[edge_case:count = 0], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(!l_pop(l, 1));
CMC_TEST_PASS_ELSE_FAIL(!l_pop(l, 1));
l_free(l);
});
CMC_CREATE_TEST(pop[edge_case:count = 1], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(l_push_back(l, 1));
CMC_TEST_PASS_ELSE_FAIL(l_pop(l, 0));
cmc_assert_equals(size_t, 0, l->buffer[0]);
l_free(l);
});
CMC_CREATE_TEST(pop[buffer_clear], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(l_push_back(l, 1));
cmc_assert(l_push_back(l, 2));
cmc_assert(l_push_back(l, 3));
cmc_assert(l_pop(l, 1));
CMC_TEST_PASS_ELSE_FAIL(0 == l->buffer[2]);
l_free(l);
});
CMC_CREATE_TEST(pop_back[edge_case:count = 0], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(!l_pop_back(l));
CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 0);
l_free(l);
});
CMC_CREATE_TEST(pop_back[edge_case:count = 1], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(l_push_back(l, 10));
cmc_assert(l_pop_back(l));
CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 0);
l_free(l);
});
})
+73
View File
@@ -0,0 +1,73 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/queue.c"
CMC_CREATE_UNIT(queue_test, true, {
CMC_CREATE_TEST(new, {
queue *q = q_new(1000000);
cmc_assert_not_equals(ptr, NULL, q);
bool passed = q->capacity == 1000000 && q->count == 0 && q->buffer;
cmc_assert_equals(size_t, 1000000, q->capacity);
cmc_assert_equals(size_t, 0, q_count(q));
cmc_assert_not_equals(ptr, NULL, q->buffer);
CMC_TEST_PASS_ELSE_FAIL(passed);
q_free(q);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
queue *q = q_new(0);
cmc_assert_equals(ptr, NULL, q);
CMC_TEST_PASS_ELSE_FAIL(q == NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
queue *q = q_new(UINT64_MAX);
cmc_assert_equals(ptr, NULL, q);
CMC_TEST_PASS_ELSE_FAIL(q == NULL);
});
CMC_CREATE_TEST(clear[count capacity], {
queue *q = q_new(100);
cmc_assert_not_equals(ptr, NULL, q);
for (size_t i = 0; i < 50; i++)
q_enqueue(q, i);
cmc_assert_equals(size_t, 50, q_count(q));
q_clear(q);
cmc_assert_equals(size_t, 0, q_count(q));
cmc_assert_equals(size_t, 100, q_capacity(q));
CMC_TEST_PASS_ELSE_FAIL(q_count(q) == 0 && q_capacity(q) == 100);
q_free(q);
});
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
queue *q = q_new(1);
cmc_assert_not_equals(ptr, NULL, q);
for (size_t i = 0; i < 50; i++)
q_enqueue(q, i);
cmc_assert_equals(size_t, 50, q_count(q));
CMC_TEST_PASS_ELSE_FAIL(q_count(q) == 50);
q_free(q);
});
});
+335
View File
@@ -0,0 +1,335 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/stack.c"
CMC_CREATE_UNIT(stack_test, true, {
CMC_CREATE_TEST(new, {
stack *s = s_new(1000000);
cmc_assert_not_equals(ptr, NULL, s);
bool passed = s->capacity == 1000000 && s->count == 0 && s->buffer;
cmc_assert_equals(size_t, 1000000, s->capacity);
cmc_assert_equals(size_t, 0, s_count(s));
cmc_assert_not_equals(ptr, NULL, s->buffer);
CMC_TEST_PASS_ELSE_FAIL(passed);
s_free(s);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
stack *s = s_new(0);
cmc_assert_equals(ptr, NULL, s);
CMC_TEST_PASS_ELSE_FAIL(s == NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
stack *s = s_new(UINT64_MAX);
cmc_assert_equals(ptr, NULL, s);
CMC_TEST_PASS_ELSE_FAIL(s == NULL);
});
CMC_CREATE_TEST(clear[count capacity], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 50; i++)
cmc_assert(s_push(s, i));
cmc_assert_equals(size_t, 50, s_count(s));
s_clear(s);
cmc_assert_equals(size_t, 0, s_count(s));
cmc_assert_equals(size_t, 100, s_capacity(s));
CMC_TEST_PASS_ELSE_FAIL(s_count(s) == 0 && s_capacity(s) == 100);
s_free(s);
});
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
stack *s = s_new(1);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 50; i++)
cmc_assert(s_push(s, i));
cmc_assert_equals(size_t, 50, s_count(s));
cmc_assert_lesser_equals(size_t, s_capacity(s), s_count(s));
CMC_TEST_PASS_ELSE_FAIL(s_count(s) == 50 && s_count(s) <= s_capacity(s));
s_free(s);
});
CMC_CREATE_TEST(push[count], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
cmc_assert_equals(size_t, 250, s_count(s));
CMC_TEST_PASS_ELSE_FAIL(s_count(s) == 250);
s_free(s);
});
CMC_CREATE_TEST(push[capacity], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
cmc_assert_lesser_equals(size_t, s_capacity(s), s_count(s));
CMC_TEST_PASS_ELSE_FAIL(s_count(s) <= s_capacity(s));
s_free(s);
});
CMC_CREATE_TEST(push[item_preservation], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
bool passed = true;
for (size_t i = 0; i < s_count(s); i++)
{
passed = s->buffer[i] == i;
cmc_assert_equals(size_t, i, s->buffer[i]);
}
CMC_TEST_PASS_ELSE_FAIL(passed);
s_free(s);
});
CMC_CREATE_TEST(pop[count], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
cmc_assert(s_pop(s));
cmc_assert_equals(size_t, 249, s_count(s));
CMC_TEST_PASS_ELSE_FAIL(s_count(s) == 249);
s_free(s);
});
CMC_CREATE_TEST(pop[capacity], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
cmc_assert(s_pop(s));
cmc_assert_lesser_equals(size_t, s_capacity(s), s_count(s));
CMC_TEST_PASS_ELSE_FAIL(s_count(s) <= s_capacity(s));
s_free(s);
});
CMC_CREATE_TEST(pop[item_preservation], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
cmc_assert(s_pop(s));
cmc_assert(s_pop(s));
bool passed = true;
for (size_t i = 0; i < s_count(s); i++)
{
passed = s->buffer[i] == i;
cmc_assert_equals(size_t, i, s->buffer[i]);
}
CMC_TEST_PASS_ELSE_FAIL(passed);
s_free(s);
});
CMC_CREATE_TEST(push_if, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
s_push_if(s, i, i % 2 == 0);
bool passed = true;
for (size_t i = 0; i < s_count(s); i++)
{
passed = passed && s->buffer[i] % 2 == 0;
cmc_assert(s->buffer[i] % 2 == 0);
}
CMC_TEST_PASS_ELSE_FAIL(passed);
s_free(s);
});
CMC_CREATE_TEST(pop_if, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
{
s_push(s, i);
s_pop_if(s, s_top(s) % 2 == 0);
}
bool passed = true;
for (size_t i = 0; i < s_count(s); i++)
{
passed = passed && !(s->buffer[i] % 2 == 0);
cmc_assert(!(s->buffer[i] % 2 == 0));
}
CMC_TEST_PASS_ELSE_FAIL(passed);
s_free(s);
});
CMC_CREATE_TEST(top, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
cmc_assert(s_pop(s));
cmc_assert(s_pop(s));
cmc_assert_equals(size_t, 247, s_top(s));
CMC_TEST_PASS_ELSE_FAIL(247 == s_top(s));
s_free(s);
});
CMC_CREATE_TEST(top[edge_case:count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert(s_push(s, 1));
cmc_assert(s_pop(s));
cmc_assert_equals(size_t, s_impl_default_value(), s_top(s));
CMC_TEST_PASS_ELSE_FAIL(s_impl_default_value() == s_top(s));
s_free(s);
});
CMC_CREATE_TEST(top[edge_case:count = 1], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert(s_push(s, 10));
cmc_assert_equals(size_t, 1, s_count(s));
cmc_assert_equals(size_t, 10, s_top(s));
CMC_TEST_PASS_ELSE_FAIL(10 == s_top(s));
s_free(s);
});
CMC_CREATE_TEST(empty, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert(s_empty(s));
CMC_TEST_PASS_ELSE_FAIL(s_empty(s));
s_free(s);
});
CMC_CREATE_TEST(empty[after_io], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert(s_push(s, 10));
cmc_assert(s_pop(s));
cmc_assert(s_empty(s));
CMC_TEST_PASS_ELSE_FAIL(s_empty(s));
s_free(s);
});
CMC_CREATE_TEST(full, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < s_capacity(s); i++)
cmc_assert(s_push(s, i));
cmc_assert(s_full(s));
CMC_TEST_PASS_ELSE_FAIL(s_full(s));
s_free(s);
});
CMC_CREATE_TEST(full[edge_case:capacity = 1], {
stack *s = s_new(1);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert(s_push(s, 10));
cmc_assert(s_full(s));
CMC_TEST_PASS_ELSE_FAIL(s_full(s));
s_free(s);
});
});
+38
View File
@@ -0,0 +1,38 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/treemap.c"
#include "utl.c"
CMC_CREATE_UNIT(treemap_test, true, {
CMC_CREATE_TEST(new, {
treemap *map = tm_new(cmp);
cmc_assert_not_equals(ptr, NULL, map);
CMC_TEST_PASS_ELSE_FAIL(map);
tm_free(map);
});
CMC_CREATE_TEST(clear[count], {
treemap *map = tm_new(cmp);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 50; i++)
tm_insert(map, i, i);
cmc_assert_equals(size_t, 50, tm_count(map));
tm_clear(map);
cmc_assert_equals(size_t, 0, tm_count(map));
cmc_assert_equals(ptr, NULL, map->root);
CMC_TEST_PASS_ELSE_FAIL(tm_count(map) == 0);
tm_free(map);
});
});
Loaded 100 of 107 files, more files were not shown because too many files have changed in this diff. Show more