61 Commits
Author SHA1 Message Date
Leonardo 5b39676d79 v1.4.0 2019-05-16 14:58:31 -03:00
Leonardo 5e2b841e9e Added CHANGELOG and TODO 2019-05-16 14:49:50 -03:00
Leonardo 3ec32bd57b changed pointertype test to be a pointer to a struct not a char 2019-05-16 14:25:28 -03:00
Leonardo Vencovsky 9531f7b5da Merge pull request #1 from LeoVen/iter
Merge iter to master
2019-05-16 13:44:48 -03:00
Leonardo 5f39eb011c Final update - fixed foreach, tests and benchmark 2019-05-16 13:41:35 -03:00
Leonardo 22e84db11a Tenth update on iterators - TREESET 2019-05-16 01:18:26 -03:00
Leonardo 8410111eab Ninth update on iterators - TREEMAP 2019-05-16 00:04:54 -03:00
Leonardo 490936bddd Eighth update on iterators - STACK 2019-05-15 20:42:28 -03:00
Leonardo f956094178 Seventh update on iterators - QUEUE 2019-05-15 19:57:35 -03:00
Leonardo 812d0240e3 Sixth update on iterators - LINKEDLIST 2019-05-15 18:49:40 -03:00
Leonardo 918b73ad51 Fifth update on iterators - HEAP 2019-05-15 15:22:59 -03:00
Leonardo ae5241a6fb Fourth update on iterators - HASHSET 2019-05-14 23:22:52 -03:00
Leonardo d3e7d64d2a Third update on iterators - HASHMAP 2019-05-14 00:52:20 -03:00
Leonardo 226e4ec817 Update Documentation.md 2019-05-13 23:06:30 -03:00
Leonardo 221c55cf2a Second update on iterators - DEQUE 2019-05-13 23:01:27 -03:00
Leonardo 444f597a98 First update on iterators - LIST 2019-05-11 00:24:48 -03:00
Leonardo 8843a8fb7a Update Documentation.md 2019-05-10 00:05:03 -03:00
Leonardo bc350611fc Update benchmark
Added Mersenne Twister utility as the function rand() was not random enough
2019-05-09 16:40:04 -03:00
Leonardo c61ac2e347 Changed iter_new to inter_init and added new iter_new that allocates the iterator on the heap 2019-05-08 11:47:00 -03:00
Leonardo 6002650f06 v1.3.0 2019-05-07 17:35:02 -03:00
Leonardo 21ab3eeb07 Changed linkedlist IO relative to a node 2019-05-07 17:20:01 -03:00
Leonardo 2f767f7623 v1.2.4 2019-05-04 00:12:28 -03:00
Leonardo d89972c621 Fixing hashset and hashmap error with a pointer data type and adding a test to address that 2019-05-04 00:06:27 -03:00
Leonardo f0b763afba Hashmap example 2019-05-03 23:57:58 -03:00
Leonardo 661455abe4 TreeSet documentation 2019-04-29 23:24:24 -03:00
Leonardo 71fb0a52c5 v1.2.3 2019-04-26 23:36:16 -03:00
Leonardo d715ea70a8 Added treemap example 2019-04-26 23:35:28 -03:00
Leonardo a37207e9d7 Added get_ref
Gets the reference of a value. Useful for primitive values like int, char, double, size_t, etc.
The only collections with this function are associative collections (when getting the value) and lists (working as an update method).
Other collections have not received this function because they are either sorted by the values so changing it would break the structure or because removing and adding back again the element is done instantaneously.
2019-04-26 23:35:09 -03:00
Leonardo be9c5af7cb v1.2.2 2019-04-24 17:21:29 -03:00
Leonardo 73171f5068 Removing unnecessary modulo in hashtable functions 2019-04-24 17:20:56 -03:00
Leonardo f07efbd828 Update Documentation.md 2019-04-23 16:53:08 -03:00
Leonardo 8cc5ef1f90 Update Documentation.md 2019-04-17 22:56:13 -03:00
Leonardo fbf020c784 v1.2.1 2019-04-16 23:46:08 -03:00
Leonardo b6d0424bb4 Update Documentation.md 2019-04-16 23:42:43 -03:00
Leonardo e2916aedb4 Update example 2019-04-16 23:42:38 -03:00
Leonardo 8966cd5e7d List optimization and indexof function
Replaced all for loops with memcpy, memmove and memset.
2019-04-16 23:41:51 -03:00
Leonardo 58bb89086e Update Documentation.md 2019-04-15 21:44:23 -03:00
Leonardo 763ea5dbd5 v1.2.0 2019-04-14 23:22:48 -03:00
Leonardo 0413da5c12 Update .travis.yml 2019-04-14 23:03:13 -03:00
Leonardo fe57443433 Added contains test and benchmark and updated example and tests 2019-04-14 20:29:48 -03:00
Leonardo e4d5687907 Added contains functions to all collections 2019-04-14 18:12:58 -03:00
Leonardo ae5c745ef8 Unified Benchmark 2019-04-13 00:03:42 -03:00
Leonardo e8cfd9131b v1.1.3 2019-04-12 00:42:35 -03:00
Leonardo 8625a6a411 Revamped benchmarks and sorted alphabetically foreach tests 2019-04-12 00:42:01 -03:00
Leonardo bd8d745d7d Renaming deque's rear to back to be consistent with function names 2019-04-12 00:33:02 -03:00
Leonardo 469cddb515 Example quickfix 2019-04-11 14:59:39 -03:00
Leonardo 00fe35810b v.1.1.2 2019-04-11 14:58:04 -03:00
Leonardo 9b632895b1 Update .travis.yml 2019-04-11 14:46:17 -03:00
Leonardo 032d34a6bd Revamped iterator test and added examples 2019-04-11 14:45:23 -03:00
Leonardo bddb9252f3 Fixing iterators 2019-04-11 14:43:28 -03:00
Leonardo 213fa25a3a Removed all Complexity sections from documentation 2019-04-10 16:18:35 -03:00
Leonardo a208b4d41b v1.1.1 2019-04-09 23:52:17 -03:00
Leonardo 1741e77c33 Reordering functions
All implementation detail functions are at the end of source their source file
2019-04-09 23:52:02 -03:00
Leonardo ad93db4203 v1.1.0 2019-04-08 18:35:25 -03:00
Leonardo bc46ace086 Added more list functions and examples 2019-04-08 18:34:52 -03:00
Leonardo 964ececf0b v1.0.1 2019-04-07 19:41:56 -03:00
Leonardo c449025e52 Minor fix in hashset 2019-04-06 23:55:05 -03:00
Leonardo 44a29874eb Update Documentation.md 2019-04-05 23:24:48 -03:00
Leonardo 2b18531478 Update README, CONTRIBUTING and templates 2019-04-04 18:35:00 -03:00
Leonardo 2d533c2db5 Update .travis.yml 2019-04-04 17:22:47 -03:00
Leonardo 0b07829041 Update .travis.yml 2019-04-04 17:17:42 -03:00
77 changed files with 10363 additions and 4284 deletions

No files matched your search

+1 -1
View File
@@ -4,7 +4,7 @@
A clear and concise description of what the bug is.
### To Reproduce
### How to Reproduce
Steps to reproduce the behavior:
+6
View File
@@ -1,5 +1,11 @@
# Feature Request Template
### What is the nature of this request?
* New functionalities
* Change in standards
* Change in source code details (names of variables, functions, parameters, etc)
### Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+8 -4
View File
@@ -11,8 +11,12 @@ addons:
script:
- sudo ln -s /usr/bin/gcc-6 /usr/local/bin/gcc
- export CC=gcc-7
- cd ./C-Macro-Containers/tests
- gcc foreach.c -Wall -Wextra -o foreach
- cd ./tests
- gcc foreach.c -Wall -Wextra -o foreach -std=c11
- ./foreach
after_success:
- bash <(curl -s https://codecov.io/bash)
- 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
+85
View File
@@ -0,0 +1,85 @@
# MAJOR.MINOR.ADJUSTMENTS
1.0.0
First stable version
Includes the following collections:
- deque
- hashmap
- hashset
- heap
- linkedlist
- list
- queue
- stack
- treemap
- treeset
Two-way iterators
Benchmarks
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
+6 -2
View File
@@ -2,11 +2,15 @@
Two simple steps:
* Fork this repository
* Fork this repository to your github account
* Clone it to your machine
Now you can start working on the project.
## Open Issues
Check out `bug_report.md` and `feature_request.md` templates in the `.github` folder to know how to make a bug report or feature request.
## Here are things you could work on:
1. New features, new functions, new stuff!
@@ -34,7 +38,7 @@ Now you can start working on the project.
4. All source files (`.c`, `.h`, etc) must contain a header with the following template:
* Complete file name.
* First commit date in `dd/mm/yyyy`.
* Authors name with (optional) github link to his page.
* Authors name with (optional) link to github page.
```
/**
+1560 -276
View File
File diff suppressed because it is too large. Load diff
+41 -103
View File
@@ -3,7 +3,7 @@
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.0.0-orange.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)
## Available Collections
@@ -19,11 +19,32 @@ Generate Simple Data Structures of any type in C for you to use in your projects
* HashSet
* HashMap
Check out **Documentation.md** for more information about each data structure.
## Available Collections in future updates
* Multimap
* Multiset
* Treehashmap
* Heap will be a MinMaxHeap
Check out **Documentation.md** for more information about each collection.
## 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).
* **Ideal** - The collection implements correctly the abstract data type;
* **Not Ideal** - The implementation is fulfilled but some functionalities are either not part of the ADT or not present;
* **Bad** - It can be done, but its a bad idea.
![DataStructuresDiagram](https://i.imgur.com/hFqBSlC.png)
![GoodColor](https://img.shields.io/badge/Ideal_Implementation-%236abf69.svg)
![AverageColor](https://img.shields.io/badge/Not_Ideal_Implementation-%2363a4ff.svg)
![BadColor](https://img.shields.io/badge/Bad_Implementation-%23ff6659.svg)
## How to use
To generate the data structures, all you need to do is to include the necessary header files. You can include the containers you want to use individually or you can include the master header, `macro_collections.h`, that comes with all collections and other functionalities like the `FOR_EACH` macro.
To generate the collection, all you need to do is to include the necessary header files. You can include the containers you want to use individually or you can include the master header, `macro_collections.h`, that comes with all collections and other functionalities like the `FOR_EACH` macro.
There are three C standard headers that all collections use:
@@ -35,46 +56,37 @@ With the last one being used only by array based containers. These headers are a
### Macros
> Note here that `SNAME` represents the uppercase name of the data structure.
> Note here that `SNAME` represents the uppercase name of the collection.
Every collection is separated by three parts:
Every collection is separated by two parts:
* `STRUCT` - Contains all structure definitions.
* `HEADER` - Contains all functions definitions.
* `SOURCE` - Contains all functions implementations.
* `HEADER` - Contains all struct definitions and function definitions.
* `SOURCE` - Contains all function implementations.
All collections have five main macros:
All collections have three main macros:
* PUBLIC
* `SNAME_GENERATE_HEADER_PUBLIC` - Generates both `STRUCT` and `HEADER`
* `SNAME_GENERATE_SOURCE_PUBLIC` - Generates `SOURCE`
* PRIVATE
* `SNAME_GENERATE_HEADER_PRIVATE` - Generates `HEADER`
* `SNAME_GENERATE_SOURCE_PRIVATE` - Generates both `STRUCT` and `SOURCE`
* Standalone
* `SNAME_GENERATE` - Generates `STRUCT`, `HEADER` and `SOURCE`.
* `SNAME_GENERATE` - Generates `SNAME_GENERATE_HEADER` and `SNAME_GENERATE_SOURCE`.
Or you can generate each part individually:
* `SNAME_GENERATE_STRUCT` - Generates all structure definitions.
* `SNAME_GENERATE_HEADER` - Generates all functions definitions.
* `SNAME_GENERATE_SOURCE` - Generates all functions implementations.
* `SNAME_GENERATE_HEADER` - Generates all struct definitions and function definitions.
* `SNAME_GENERATE_SOURCE` - Generates all function implementations.
### For Each
There are 4 for-each macros:
There are 2 for-each macros:
* `FOR_EACH` - Starts at the start of the data structure towards the end.
* `FOR_EACH_REV` - Starts at the end of the data structure towards the start.
* `FOR_EACH_MAP` - Like `FOR_EACH` but for associative data structures like *TREEMAP* and *HASHMAP*.
* `FOR_EACH_MAP_REV` - Like `FOR_EACH_REV` but for associative data structures like *TREEMAP* and *HASHMAP*.
* `FOR_EACH` - Starts at the start of the collection towards the end.
* `FOR_EACH_REV` - Starts at the end of the collection towards the start.
Check out the **Documentation.md** to know exactly what represents the *end* and the *start* of each data structure.
Check out the **Documentation.md** to know exactly what represents the *end* and the *start* of each collection.
### Parameters
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.
@@ -83,7 +95,7 @@ When including `macro_collections.h` in your source code you gain access to a ma
* \*__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 data structures, or value to be mapped by *HASHMAP* and *TREEMAP*.
* \*__V__ - Value type. Primary type for most collections, or value to be mapped by *HASHMAP* and *TREEMAP*.
\* Required parameters
@@ -95,81 +107,7 @@ When including `foreach.h` in your source code you gain access to all for-each m
* __PFX__ - Functions prefix or namespace.
* __SNAME__ - Structure name.
* __V__ - Value type.
* \*__K__ - Key type.
* __TARGET__ - The variable name of the data structure you wish to iterate over.
* __TARGET__ - The variable name of the collection you wish to iterate over.
* __BODY__ - Block of code.
\* Only available for `FOR_EACH_MAP` and `FOR_EACH_MAP_REV`.
Inside body you will have access to three new variables:
* `iter` - Represents the iterator.
* \*`key` - Represents the resulting key on each iteration.
* `value` - Represents the resulting value on each iteration.
\* Only available in `FOR_EACH_MAP` and `FOR_EACH_MAP_REV`.
### Separate Header and Source
Below is an example of how to hide the struct members when using a separate source file.
**header.h**
```c
#include "macro_collection.h"
COLLECTION_GENERATE_HEADER(LIST, PRIVATE, l, list, , , int)
```
**source.c**
```c
#include "header.h"
COLLECTION_GENERATE_SOURCE(LIST, PRIVATE, l, list, , , int)
```
**main.c**
```c
#include "header.h"
int main(void)
{
list *my_list = l_new(100);
// Valid code
size_t len1 = l_count(my_list);
// Invalid code
size_t len2 = my_list->count;
l_free(my_list);
}
```
**Compilation process**
```
gcc -c source.c -I ./path/to/source
gcc -c main.c -I ./path/to/source
gcc source.o main.o
```
The container members won't be visible to the file `main.c`. For this to work, all parameters must be identical, with the only difference being the macro name.
## What to use
The following table shows how each data structure is implemented and how well they do when using as common [abstract data types](https://en.wikipedia.org/wiki/Abstract_data_type).
* **Ideal** - The data structure implements correctly the abstract data type;
* **Not Ideal** - The implementation is fulfilled but some functionalities are either not part of the ADT or not present;
* **Bad** - It can be done, but its a bad idea.
![DataStructuresDiagram](https://i.imgur.com/hFqBSlC.png)
![GoodColor](https://img.shields.io/badge/Ideal_Implementation-%236abf69.svg)
![AverageColor](https://img.shields.io/badge/Not_Ideal_Implementation-%2363a4ff.svg)
![BadColor](https://img.shields.io/badge/Bad_Implementation-%23ff6659.svg)
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.
+56
View File
@@ -0,0 +1,56 @@
TODO
[ ] Finish Documentation
[ ] Simplify PUBLIC and PRIVATE
[ ] Add multiset
[ ] Add multimap
[ ] Upgrade heap to a min-max heap
[ ] Add dispose function
[ ] Serialization
[ ] Iterator based functions (like C++ collections)
MAYBE
[ ] Add conditional code generation based on variadic macros
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
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
2.0
Add multiset, multimap and new heap implementation
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
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
+232
View File
@@ -0,0 +1,232 @@
/**
* benchmark.c
*
* Creation Date: 13/04/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
* Benchmarks:
* - Input
* - Search
* - Iteration
* - Output
*/
#include "macro_collections.h"
#include "util/timer.h"
#include "util/twister.c"
#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#include <math.h>
#include <inttypes.h>
#define NTOTAL UINT64_C(10000000)
#define NMIN UINT64_C(100)
// Percentage % macro
#define PC(x) x * 100.0
static int intcmp(int a, int b)
{
return a - b;
}
static 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;
}
size_t randsize(size_t min, size_t max, mt_state_ptr st)
{
return (size_t)floor(twist_real(st) * ((double)max - (double)min + 1.0) + (double)min);
}
void shuffle(int *array, mt_state_ptr st)
{
for (size_t i = 0; i < NTOTAL; i++)
{
size_t j = randsize(0, NTOTAL - 1, st);
int tmp = array[j];
array[j] = array[i];
array[i] = tmp;
}
}
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)
#define BENCHMARK(NAME, PFX, sname, initfunc, insertbody, removebody, searchbody) \
void NAME##_io_benchmark(int *array, int *sarray, size_t s) \
{ \
printf("+------------------------------------------------------------ %10s\n", #NAME); \
printf("+------------------------------------------------------------ \n"); \
timer_t timer, total; \
int r, k, v; \
size_t j; \
\
sname *coll = initfunc; \
\
TIMER_START(total) \
TIMER_START(timer) \
\
for (size_t i = 0; i < NTOTAL; i++) \
{ \
insertbody; \
} \
\
TIMER_STOP(timer) \
\
TIMER_CALC(timer) \
\
size_t s1 = PFX##_count(coll); \
\
printf(" INPUT %10s TOOK %8.0lf milliseconds for %8" PRIuMAX " elements\n", #NAME, timer.result, s1); \
\
double input_time = timer.result; \
\
TIMER_START(timer) \
\
for (size_t i = 0; i < s; i++) \
{ \
searchbody; \
} \
\
TIMER_STOP(timer) \
\
TIMER_CALC(timer) \
\
printf(" SEARCH %10s TOOK %8.0lf milliseconds for %8" PRIuMAX " elements\n", #NAME, timer.result, s); \
\
double search_time = timer.result; \
\
sname##_iter iter; \
\
TIMER_START(timer) \
\
for (PFX##_iter_init(&iter, coll); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
{ \
} \
\
TIMER_STOP(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); \
\
for (size_t i = 0; i < NTOTAL; i++) \
{ \
removebody; \
} \
\
TIMER_STOP(timer) \
\
TIMER_CALC(timer) \
\
size_t s2 = PFX##_count(coll); \
\
printf(" OUTPUT %10s TOOK %8.0lf milliseconds for %8" PRIuMAX " elements\n", #NAME, timer.result, s1); \
\
double output_time = timer.result; \
\
TIMER_STOP(total) \
TIMER_CALC(total) \
\
PFX##_free(coll); \
\
double adj_search_time = (total.result - search_time) + (search_time * (double)NTOTAL) / (double)s; \
double no_search = input_time + iter_time + output_time; \
\
printf("+------------------------------------------------------------ \n"); \
printf("TOTAL TIME : %.0lf milliseconds\n", total.result); \
printf("ADJUSTED TIME : %.0lf milliseconds\n", adj_search_time); \
\
printf("+------------------------------------------------------------ \n"); \
printf(" INPUT : %5.2lf%% (%5.2f%%)\n", PC(input_time / total.result), PC(input_time / no_search)); \
printf(" SEARCH : %5.2lf%%\n", PC(search_time / total.result)); \
printf("ITERATION : %5.2lf%% (%5.2f%%)\n", PC(iter_time / total.result), PC(iter_time / no_search)); \
printf(" OUTPUT : %5.2lf%% (%5.2f%%)\n", PC(output_time / total.result), PC(output_time / no_search)); \
printf("+------------------------------------------------------------ \n"); \
\
assert(s1 == NTOTAL && s2 == 0); \
\
printf("+------------------------------------------------------------ %10s\n\n", #NAME); \
}
BENCHMARK(DEQUE, d, deque, d_new(NTOTAL), d_push_back(coll, array[i]), d_pop_back(coll), d_contains(coll, sarray[i], intcmp))
BENCHMARK(HASHMAP, hm, hmap, hm_new(NTOTAL, 0.8, intcmp, inthash), hm_insert(coll, array[i], array[i]), hm_remove(coll, array[i], &r), hm_contains(coll, sarray[i]))
BENCHMARK(HASHSET, hs, hset, hs_new(NTOTAL, 0.8, intcmp, inthash), hs_insert(coll, array[i]), hs_remove(coll, array[i]), hs_contains(coll, sarray[i]))
BENCHMARK(HEAP, h, heap, h_new(NTOTAL, MinHeap, intcmp), h_insert(coll, array[i]), h_remove(coll, &r), h_contains(coll, sarray[i]))
BENCHMARK(LINKEDLIST, ll, linked, ll_new(), ll_push_back(coll, array[i]), ll_pop_back(coll), ll_contains(coll, sarray[i], intcmp))
BENCHMARK(LIST, l, list, l_new(NTOTAL), l_push_back(coll, array[i]), l_pop_back(coll), l_contains(coll, sarray[i], intcmp))
BENCHMARK(QUEUE, q, queue, q_new(NTOTAL), q_enqueue(coll, array[i]), q_dequeue(coll), q_contains(coll, sarray[i], intcmp))
BENCHMARK(STACK, s, stack, s_new(NTOTAL), s_push(coll, array[i]), s_pop(coll), s_contains(coll, sarray[i], intcmp))
BENCHMARK(TREEMAP, tm, tmap, tm_new(intcmp), tm_insert(coll, array[i], array[i]), tm_remove(coll, array[i], &r), tm_contains(coll, sarray[i]))
BENCHMARK(TREESET, ts, tset, ts_new(intcmp), ts_insert(coll, array[i]), ts_remove(coll, array[i]), ts_contains(coll, sarray[i]))
int main(void)
{
// Using the Mersenne Twister to generate random numbers. This seed
// guarantees that everytime this program runs it will generate the same
// random numbers. The random numbers influence on the shuffling of the
// array.
mt_state st;
twist_init(&st, UINT64_C(12604951237));
int *array = malloc(NTOTAL * sizeof(int));
int *sarray = malloc(NTOTAL * sizeof(int));
if (!array)
{
printf("Allocation failed\n");
return 1;
}
for (int i = -5000000; i < 5000000; i++)
array[i + 5000000] = i;
shuffle(array, &st);
memcpy(sarray, array, NTOTAL * sizeof(int));
shuffle(sarray, &st);
printf("\nNote: Adjusted Time refers to if the container had done a search over all %" PRIuMAX " elements.\n\n", NTOTAL);
// Linear containers have to search for NMIN elements and non-linear (hash
// and tree) have to search for all elements.
DEQUE_io_benchmark(array, sarray, NMIN);
HASHMAP_io_benchmark(array, sarray, NTOTAL);
HASHSET_io_benchmark(array, sarray, NTOTAL);
HEAP_io_benchmark(array, sarray, NMIN);
LINKEDLIST_io_benchmark(array, sarray, NMIN);
LIST_io_benchmark(array, sarray, NMIN);
QUEUE_io_benchmark(array, sarray, NMIN);
STACK_io_benchmark(array, sarray, NMIN);
TREEMAP_io_benchmark(array, sarray, NTOTAL);
TREESET_io_benchmark(array, sarray, NTOTAL);
free(array);
free(sarray);
return 0;
}
-44
View File
@@ -1,44 +0,0 @@
#include <stdio.h>
#include "../src/macro_collections.h"
int intcmp(int a, int b)
{
return a - b;
}
size_t inthash(int t)
{
size_t a = t;
a += ~(a << 15);
a ^= (a >> 10);
a += (a << 3);
a ^= (a >> 6);
a += ~(a << 11);
a ^= (a >> 16);
return a;
}
COLLECTION_GENERATE(HASHSET, PUBLIC, set, hash_set, static, , int)
int main(int argc, char const *argv[])
{
hash_set *set = set_new(50000, 0.9, intcmp, inthash);
//hash_set *set = set_new(intcmp);
for (int i = -1000000; i <= 1000000; i++)
set_insert(set, i);
hash_set_iter iter;
size_t index;
int result, total_sum = 0;
for (set_iter_new(&iter, set); !set_iter_end(&iter);)
{
set_iter_next(&iter, &result, &index);
total_sum += result;
}
set_free(set);
return 0;
}
-44
View File
@@ -1,44 +0,0 @@
#include <stdio.h>
#include "../src/macro_collections.h"
int intcmp(int a, int b)
{
return a - b;
}
size_t inthash(int t)
{
size_t a = t;
a += ~(a << 15);
a ^= (a >> 10);
a += (a << 3);
a ^= (a >> 6);
a += ~(a << 11);
a ^= (a >> 16);
return a;
}
COLLECTION_GENERATE(TREESET, PUBLIC, set, hash_set, static, , int)
int main(int argc, char const *argv[])
{
//hash_set *set = set_new(50000, 0.9, intcmp, inthash);
hash_set *set = set_new(intcmp);
for (int i = -1000000; i <= 1000000; i++)
set_insert(set, i);
hash_set_iter iter;
size_t index;
int result, total_sum = 0;
for (set_iter_new(&iter, set); !set_iter_end(&iter);)
{
set_iter_next(&iter, &result, &index);
total_sum += result;
}
set_free(set);
return 0;
}
+27
View File
@@ -0,0 +1,27 @@
/**
* 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);
+102
View File
@@ -0,0 +1,102 @@
/**
* twister.c
*
* Creation Date: 09/05/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
* Mersenne Twister PRNG utility
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define NN 312
#define MM 156
#define MATRIX_A UINT64_C(0xB5026F5AA96619E9)
#define UM UINT64_C(0xFFFFFFFF80000000) // Most significant 33 bits
#define LM UINT64_C(0x7FFFFFFF) // Least significant 31 bits
// State vector
typedef struct mt_state_s
{
uint64_t mt[NN];
int mti;
} mt_state, *mt_state_ptr;
// Initializes mt[NN] with a seed
void twist_init(mt_state_ptr st, uint64_t seed);
// Generates a random uint64_t in [0, 2^64-1] interval
uint64_t twist_uint64(mt_state_ptr st);
// Generates a double in [0, 1) interval
double twist_real(mt_state_ptr st);
//
// Implementation
//
// Initialize a state mt[NN] with a seed
void twist_init(mt_state_ptr st, uint64_t seed)
{
st->mti = NN + 1;
st->mt[0] = seed;
for (st->mti = 1; st->mti < NN; st->mti++)
{
st->mt[st->mti] = (UINT64_C(6364136223846793005) * (st->mt[st->mti - 1] ^ (st->mt[st->mti - 1] >> 62)) + st->mti);
}
}
// Generates a random uint64_t in [0, 2^64-1] interval
uint64_t twist_uint64(mt_state_ptr st)
{
int i;
uint64_t x;
static uint64_t mag01[2] = {UINT64_C(0), MATRIX_A};
if (st->mti >= NN)
{
// Generate NN words at one time if twist_init() has not been called
// A default initial seed is used
if (st->mti == NN + 1)
twist_init(st, UINT64_C(5489));
for (i = 0; i < NN - MM; i++)
{
x = (st->mt[i] & UM) | (st->mt[i + 1] & LM);
st->mt[i] = st->mt[i + MM] ^ (x >> 1) ^ mag01[(int)(x & UINT64_C(1))];
}
for (; i < NN - 1; i++)
{
x = (st->mt[i] & UM) | (st->mt[i + 1] & LM);
st->mt[i] = st->mt[i + (MM - NN)] ^ (x >> 1) ^ mag01[(int)(x & UINT64_C(1))];
}
x = (st->mt[NN - 1] & UM) | (st->mt[0] & LM);
st->mt[NN - 1] = st->mt[MM - 1] ^ (x >> 1) ^ mag01[(int)(x & UINT64_C(1))];
st->mti = 0;
}
x = st->mt[st->mti++];
x ^= (x >> 29) & UINT64_C(0x5555555555555555);
x ^= (x << 17) & UINT64_C(0x71D67FFFEDA60000);
x ^= (x << 37) & UINT64_C(0xFFF7EEE000000000);
x ^= (x >> 43);
return x;
}
// Generates a double in [0, 1) interval
double twist_real(mt_state_ptr st)
{
return (twist_uint64(st) >> 11) * (1.0 / 9007199254740992.0);
}
+1
View File
@@ -1,3 +1,4 @@
# Deque examples
* even_odd.c - separates odd numbers to one end of the deque and even number to the other. Sum only half of it to give the total sum of even numbers.
* iterator.c - A complete example of the deque iterator
+4 -3
View File
@@ -29,13 +29,14 @@ int main(int argc, char const *argv[])
}
deque_iter iter;
d_iter_new(&iter, numbers);
d_iter_init(&iter, numbers);
size_t result, index, sum = 0;
for (d_iter_toend(&iter); !d_iter_start(&iter);)
for (d_iter_to_end(&iter); !d_iter_start(&iter); d_iter_prev(&iter))
{
d_iter_prev(&iter, &result, &index);
result = d_iter_value(&iter);
index = d_iter_index(&iter);
if ((double)index < (double)d_count(numbers) / 2.0)
break;
+199
View File
@@ -0,0 +1,199 @@
/**
* iterator.c
*
* Creation Date: 13/05/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
* Iterator Example
*/
#include "deque.h"
#include <stdio.h>
#include <inttypes.h>
// Creates a deque of integers
DEQUE_GENERATE(d, deque, /* FMOD */, int)
int main(int argc, char const *argv[])
{
// Create a new deque with an initial capacity of 100
deque *my_deque = d_new(100);
// Add elements to the deque
for (int i = 0; i < 20; i++)
{
// Add odd numbers to the front
d_push_front_if(my_deque, i, !(i % 2 == 0));
// And even numbers to the back
d_push_back_if(my_deque, i, i % 2 == 0);
}
// Iterate from the start (front index) to the end (rear index) of the deque
for (deque_iter it = my_deque->it_start(my_deque); // Initialize iterator 'it' to the start of the deque
!d_iter_end(&it); // Conditional stop (until it is not at the end)
d_iter_next(&it)) // Iterator goes one position forward
{
// Access the current element
int e = d_iter_value(&it);
// Access the current index (index is relative to all the elements in the iteration)
size_t i = d_iter_index(&it);
// Print deque
// Index is useful in situations like this
// If it is the first element
if (i == 0)
printf("[ %d, ", e);
// If it is the last element
else if (i == d_count(my_deque) - 1)
printf("%d ]\n", e);
// For elements at the middle
else
printf("%d, ", e);
}
// Index can also be used to iterate over a certain portion of a collection
size_t limit = d_count(my_deque) / 2;
for (deque_iter it = my_deque->it_start(my_deque); !d_iter_end(&it); d_iter_next(&it))
{
// Access the current element
int e = d_iter_value(&it);
// Access the current index (index is relative to all the elements in the iteration)
size_t i = d_iter_index(&it);
// Print deque up until limit
// If it is the first element
if (i == 0)
printf("[ %d, ", e);
// If it is the last element
else if (i == limit - 1) // -1 because index is 0 based and we want half of the deque
{
printf("%d ]\n", e);
break;
}
// For elements at the middle
else
printf("%d, ", e);
}
// Going backwards
for (deque_iter it = my_deque->it_end(my_deque); // Initialize iterator 'it' to the end of the deque
!d_iter_start(&it); // Conditional stop (until it is not at the start)
d_iter_prev(&it)) // Iterator goes one position backwards
{
// Access the current element
int e = d_iter_value(&it);
// Access the current index (index is relative to all the elements in the iteration)
size_t i = d_iter_index(&it);
// Print deque
// Note how the conditions for the first and last elements are simply swapped
// Because iterating backwards make the first element be the index count - 1
// and the last one be the index 0
// If it is the first element
if (i == d_count(my_deque) - 1)
printf("[ %d, ", e);
// If it is the last element
else if (i == 0)
printf("%d ]\n", e);
// For elements at the middle
else
printf("%d, ", e);
}
// You can also use iterators in a while loop
// But to do so you must declare the iterator struct outside the loop first
deque_iter it;
// You have three options:
// - Initialize it using the functions provided by the deque [ my_deque->it_start() and my_deque->it_end() ]
// - Initialize it using the init() function (when the iterator is already allocated)
// - Initialize it using the new() function (allocates on the heap, pointers only)
it = my_deque->it_start(my_deque);
it = my_deque->it_end(my_deque);
// This is equivalent to it_start()
d_iter_init(&it, my_deque);
// For pointers
// Also equivalent to it_start()
deque_iter *iter = d_iter_new(my_deque);
// The actual while loop
while (!d_iter_end(iter))
{
// Accessing elements
int e = d_iter_value(iter);
size_t i = d_iter_index(iter);
// Print index and element
printf("deque[%2" PRIuMAX "] = %2d\n", i, e);
// Move iterator forwards
d_iter_next(iter);
}
// Send the iterator to the start of the deque
d_iter_to_start(iter);
// Send the iterator to the end of the deque
d_iter_to_end(iter);
// Backwards loop
while (!d_iter_start(iter))
{
// Accessing elements
int e = d_iter_value(iter);
size_t i = d_iter_index(iter);
// Print index and element
printf("deque[%2" PRIuMAX "] = %2d\n", i, e);
// Move iterator backwards
d_iter_prev(iter);
}
// Certain iterators also allow you to modify the contents it is iterating over
// Exceptions are collections that depend of the current state of the element
// like tree-based collections and heap (collections that have some kind of ordering).
// You also can't change the keys of an associative collection
// Change every element that is divisible by 3 to the number 7
for (d_iter_to_start(&it); !d_iter_end(&it); d_iter_next(&it))
{
// Get a reference to the current value
int *r = d_iter_rvalue(&it);
if (r != NULL && *r % 3 == 0)
*r = 7;
}
// Now print it to see the difference
for (deque_iter it = my_deque->it_start(my_deque); !d_iter_end(&it); d_iter_next(&it))
{
int e = d_iter_value(&it);
size_t i = d_iter_index(&it);
if (i == 0)
printf("[ %d, ", e);
else if (i == d_count(my_deque) - 1)
printf("%d ]\n", e);
else
printf("%d, ", e);
}
// Dispose the iterator called by d_iter_new()
d_iter_free(iter);
// Dispose the deque created
d_free(my_deque);
return 0;
}
+2 -1
View File
@@ -1,3 +1,4 @@
# Hashmap examples
Currently none
* countries - Uses a hashmap to map the country name to its population
* iterator.c - A complete example of the hashmap iterator
+216
View File
@@ -0,0 +1,216 @@
Afghanistan,34656032
Albania,2876101
Algeria,40606052
American Samoa,55599
Andorra,77281
Angola,28813463
Antigua and Barbuda,100963
Argentina,43847430
Armenia,2924816
Aruba,104822
Australia,24127159
Austria,8747358
Azerbaijan,9762274
Bahamas; The,391232
Bahrain,1425171
Bangladesh,162951560
Barbados,284996
Belarus,9507120
Belgium,11348159
Belize,366954
Benin,10872298
Bermuda,65331
Bhutan,797765
Bolivia,10887882
Bosnia and Herzegovina,3516816
Botswana,2250260
Brazil,207652865
British Virgin Islands,30661
Brunei Darussalam,423196
Bulgaria,7127822
Burkina Faso,18646433
Burundi,10524117
Cabo Verde,539560
Cambodia,15762370
Cameroon,23439189
Canada,36286425
Cayman Islands,60765
Central African Republic,4594621
Chad,14452543
Channel Islands,164541
Chile,17909754
China,1378665000
Colombia,48653419
Comoros,795601
Congo; Dem. Rep.,78736153
Congo; Rep.,5125821
Costa Rica,4857274
Cote d'Ivoire,23695919
Croatia,4170600
Cuba,11475982
Curacao,159999
Cyprus,1170125
Czech Republic,10561633
Denmark,5731118
Djibouti,942333
Dominica,73543
Dominican Republic,10648791
Ecuador,16385068
Egypt; Arab Rep.,95688681
El Salvador,6344722
Equatorial Guinea,1221490
Estonia,1316481
Ethiopia,102403196
Faroe Islands,49117
Fiji,898760
Finland,5495096
France,66896109
French Polynesia,280208
Gabon,1979786
Gambia; The,2038501
Georgia,3719300
Germany,82667685
Ghana,28206728
Gibraltar,34408
Greece,10746740
Greenland,56186
Grenada,107317
Guam,162896
Guatemala,16582469
Guinea,12395924
Guinea-Bissau,1815698
Guyana,773303
Haiti,10847334
Honduras,9112867
Hong Kong SAR; China,7346700
Hungary,9817958
Iceland,334252
India,1324171354
Indonesia,261115456
Iran; Islamic Rep.,80277428
Iraq,37202572
Ireland,4773095
Isle of Man,83737
Israel,8547100
Italy,60600590
Jamaica,2881355
Japan,126994511
Jordan,9455802
Kazakhstan,17797032
Kenya,48461567
Kiribati,114395
Korea; Dem. People’s Rep.,25368620
Korea; Rep.,51245707
Kosovo,1816200
Kuwait,4052584
Kyrgyz Republic,6082700
Lao PDR,6758353
Latvia,1960424
Lebanon,6006668
Lesotho,2203821
Liberia,4613823
Libya,6293253
Liechtenstein,37666
Lithuania,2872298
Luxembourg,582972
Macao SAR; China,612167
Macedonia; FYR,2081206
Madagascar,24894551
Malawi,18091575
Malaysia,31187265
Maldives,417492
Mali,17994837
Malta,436947
Marshall Islands,53066
Mauritania,4301018
Mauritius,1263473
Mexico,127540423
Micronesia; Fed. Sts.,104937
Moldova,3552000
Monaco,38499
Mongolia,3027398
Montenegro,622781
Morocco,35276786
Mozambique,28829476
Myanmar,52885223
Namibia,2479713
Nauru,13049
Nepal,28982771
Netherlands,17018408
New Caledonia,278000
New Zealand,4692700
Nicaragua,6149928
Niger,20672987
Nigeria,185989640
Northern Mariana Islands,55023
Norway,5232929
Oman,4424762
Pakistan,193203476
Palau,21503
Panama,4034119
Papua New Guinea,8084991
Paraguay,6725308
Peru,31773839
Philippines,103320222
Poland,37948016
Portugal,10324611
Puerto Rico,3411307
Qatar,2569804
Romania,19705301
Russian Federation,144342396
Rwanda,11917508
Samoa,195125
San Marino,33203
Sao Tome and Principe,199910
Saudi Arabia,32275687
Senegal,15411614
Serbia,7057412
Seychelles,94677
Sierra Leone,7396190
Singapore,5607283
Sint Maarten (Dutch part),40005
Slovak Republic,5428704
Slovenia,2064845
Solomon Islands,599419
Somalia,14317996
South Africa,55908865
South Sudan,12230730
Spain,46443959
Sri Lanka,21203000
St. Kitts and Nevis,54821
St. Lucia,178015
St. Martin (French part),31949
St. Vincent and the Grenadines,109643
Sudan,39578828
Suriname,558368
Swaziland,1343098
Sweden,9903122
Switzerland,8372098
Syrian Arab Republic,18430453
Tajikistan,8734951
Tanzania,55572201
Thailand,68863514
Timor-Leste,1268671
Togo,7606374
Tonga,107122
Trinidad and Tobago,1364962
Tunisia,11403248
Turkey,79512426
Turkmenistan,5662544
Turks and Caicos Islands,34900
Tuvalu,11097
Uganda,41487965
Ukraine,45004645
United Arab Emirates,9269612
United Kingdom,65637239
United States,323127513
Uruguay,3444006
Uzbekistan,31848200
Vanuatu,270402
Venezuela; RB,31568179
Vietnam,92701100
Virgin Islands (U.S.),102951
West Bank and Gaza,4551566
Yemen; Rep.,27584213
Zambia,16591390
Zimbabwe,16150362
1 Afghanistan 34656032
2 Albania 2876101
3 Algeria 40606052
4 American Samoa 55599
5 Andorra 77281
6 Angola 28813463
7 Antigua and Barbuda 100963
8 Argentina 43847430
9 Armenia 2924816
10 Aruba 104822
11 Australia 24127159
12 Austria 8747358
13 Azerbaijan 9762274
14 Bahamas; The 391232
15 Bahrain 1425171
16 Bangladesh 162951560
17 Barbados 284996
18 Belarus 9507120
19 Belgium 11348159
20 Belize 366954
21 Benin 10872298
22 Bermuda 65331
23 Bhutan 797765
24 Bolivia 10887882
25 Bosnia and Herzegovina 3516816
26 Botswana 2250260
27 Brazil 207652865
28 British Virgin Islands 30661
29 Brunei Darussalam 423196
30 Bulgaria 7127822
31 Burkina Faso 18646433
32 Burundi 10524117
33 Cabo Verde 539560
34 Cambodia 15762370
35 Cameroon 23439189
36 Canada 36286425
37 Cayman Islands 60765
38 Central African Republic 4594621
39 Chad 14452543
40 Channel Islands 164541
41 Chile 17909754
42 China 1378665000
43 Colombia 48653419
44 Comoros 795601
45 Congo; Dem. Rep. 78736153
46 Congo; Rep. 5125821
47 Costa Rica 4857274
48 Cote d'Ivoire 23695919
49 Croatia 4170600
50 Cuba 11475982
51 Curacao 159999
52 Cyprus 1170125
53 Czech Republic 10561633
54 Denmark 5731118
55 Djibouti 942333
56 Dominica 73543
57 Dominican Republic 10648791
58 Ecuador 16385068
59 Egypt; Arab Rep. 95688681
60 El Salvador 6344722
61 Equatorial Guinea 1221490
62 Estonia 1316481
63 Ethiopia 102403196
64 Faroe Islands 49117
65 Fiji 898760
66 Finland 5495096
67 France 66896109
68 French Polynesia 280208
69 Gabon 1979786
70 Gambia; The 2038501
71 Georgia 3719300
72 Germany 82667685
73 Ghana 28206728
74 Gibraltar 34408
75 Greece 10746740
76 Greenland 56186
77 Grenada 107317
78 Guam 162896
79 Guatemala 16582469
80 Guinea 12395924
81 Guinea-Bissau 1815698
82 Guyana 773303
83 Haiti 10847334
84 Honduras 9112867
85 Hong Kong SAR; China 7346700
86 Hungary 9817958
87 Iceland 334252
88 India 1324171354
89 Indonesia 261115456
90 Iran; Islamic Rep. 80277428
91 Iraq 37202572
92 Ireland 4773095
93 Isle of Man 83737
94 Israel 8547100
95 Italy 60600590
96 Jamaica 2881355
97 Japan 126994511
98 Jordan 9455802
99 Kazakhstan 17797032
100 Kenya 48461567
101 Kiribati 114395
102 Korea; Dem. People’s Rep. 25368620
103 Korea; Rep. 51245707
104 Kosovo 1816200
105 Kuwait 4052584
106 Kyrgyz Republic 6082700
107 Lao PDR 6758353
108 Latvia 1960424
109 Lebanon 6006668
110 Lesotho 2203821
111 Liberia 4613823
112 Libya 6293253
113 Liechtenstein 37666
114 Lithuania 2872298
115 Luxembourg 582972
116 Macao SAR; China 612167
117 Macedonia; FYR 2081206
118 Madagascar 24894551
119 Malawi 18091575
120 Malaysia 31187265
121 Maldives 417492
122 Mali 17994837
123 Malta 436947
124 Marshall Islands 53066
125 Mauritania 4301018
126 Mauritius 1263473
127 Mexico 127540423
128 Micronesia; Fed. Sts. 104937
129 Moldova 3552000
130 Monaco 38499
131 Mongolia 3027398
132 Montenegro 622781
133 Morocco 35276786
134 Mozambique 28829476
135 Myanmar 52885223
136 Namibia 2479713
137 Nauru 13049
138 Nepal 28982771
139 Netherlands 17018408
140 New Caledonia 278000
141 New Zealand 4692700
142 Nicaragua 6149928
143 Niger 20672987
144 Nigeria 185989640
145 Northern Mariana Islands 55023
146 Norway 5232929
147 Oman 4424762
148 Pakistan 193203476
149 Palau 21503
150 Panama 4034119
151 Papua New Guinea 8084991
152 Paraguay 6725308
153 Peru 31773839
154 Philippines 103320222
155 Poland 37948016
156 Portugal 10324611
157 Puerto Rico 3411307
158 Qatar 2569804
159 Romania 19705301
160 Russian Federation 144342396
161 Rwanda 11917508
162 Samoa 195125
163 San Marino 33203
164 Sao Tome and Principe 199910
165 Saudi Arabia 32275687
166 Senegal 15411614
167 Serbia 7057412
168 Seychelles 94677
169 Sierra Leone 7396190
170 Singapore 5607283
171 Sint Maarten (Dutch part) 40005
172 Slovak Republic 5428704
173 Slovenia 2064845
174 Solomon Islands 599419
175 Somalia 14317996
176 South Africa 55908865
177 South Sudan 12230730
178 Spain 46443959
179 Sri Lanka 21203000
180 St. Kitts and Nevis 54821
181 St. Lucia 178015
182 St. Martin (French part) 31949
183 St. Vincent and the Grenadines 109643
184 Sudan 39578828
185 Suriname 558368
186 Swaziland 1343098
187 Sweden 9903122
188 Switzerland 8372098
189 Syrian Arab Republic 18430453
190 Tajikistan 8734951
191 Tanzania 55572201
192 Thailand 68863514
193 Timor-Leste 1268671
194 Togo 7606374
195 Tonga 107122
196 Trinidad and Tobago 1364962
197 Tunisia 11403248
198 Turkey 79512426
199 Turkmenistan 5662544
200 Turks and Caicos Islands 34900
201 Tuvalu 11097
202 Uganda 41487965
203 Ukraine 45004645
204 United Arab Emirates 9269612
205 United Kingdom 65637239
206 United States 323127513
207 Uruguay 3444006
208 Uzbekistan 31848200
209 Vanuatu 270402
210 Venezuela; RB 31568179
211 Vietnam 92701100
212 Virgin Islands (U.S.) 102951
213 West Bank and Gaza 4551566
214 Yemen; Rep. 27584213
215 Zambia 16591390
216 Zimbabwe 16150362
+90
View File
@@ -0,0 +1,90 @@
#include "hashmap.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <inttypes.h>
#include "util.c"
HASHMAP_GENERATE(hm, hmap, , char *, size_t)
hmap *load(const char *fname);
int main(int argc, char const *argv[])
{
hmap *map = load("data.csv");
if (!map)
return 1;
printf("+--------------------------------------------------+\n");
printf("| Search Country Population by Country Name |\n");
printf("| |\n");
printf("| - Type 'exit' to exit |\n");
printf("| - Type country name to search its population |\n");
printf("+--------------------------------------------------+\n\n");
// If you wish to list all items
// char *key;
// size_t value, index;
// hmap_iter iter;
// for (hm_iter_new(&iter, map); !hm_iter_end(&iter);)
// {
// hm_iter_next(&iter, &key, &value, &index);
// printf("%30s : %" PRIuMAX "\n", key, value);
// free(key);
// }
char sbuffer[1000];
while (1)
{
printf("Query > ");
fflush(stdin);
scanf("%[^\n]s", sbuffer);
if (strcmp(sbuffer, "exit") == 0)
break;
size_t *result = hm_get_ref(map, sbuffer);
if (result == NULL)
printf("Result > %s Not Found\n", sbuffer);
else
printf("Result > %" PRIuMAX "\n", *result);
}
hm_free(map);
return 0;
}
hmap *load(const char *fname)
{
FILE *fptr = fopen(fname, "r");
if (!fptr)
return NULL;
hmap *map = hm_new(10000, 0.7, chrcmp, chrhash);
char buff[400];
size_t value;
while (fscanf(fptr, "%[^,],%" PRIuMAX "\n", buff, &value) != EOF)
{
char *name = strdup(buff);
if (!hm_insert(map, name, value))
{
printf("\n\n\nERROR\n");
printf("%s : %" PRIuMAX "", name, value);
exit(2);
}
}
return map;
}
+17
View File
@@ -0,0 +1,17 @@
#include <stdlib.h>
int chrcmp(char *a, char *b)
{
return strcmp(a, b);
}
size_t chrhash(char *str)
{
size_t hash = 5381;
int c;
while ((c = *str++))
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
return hash;
}
+230
View File
@@ -0,0 +1,230 @@
/**
* iterator.c
*
* Creation Date: 14/05/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
* Iterator Example
*/
#include "hashmap.h"
#include <stdio.h>
#include <inttypes.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;
}
// Creates a hashmap of integers
HASHMAP_GENERATE(hm, hashmap, /* FMOD */, int, double)
int main(int argc, char const *argv[])
{
// Create a new hashmap with an initial capacity of 100 and load factor of 0.6
hashmap *my_map = hm_new(100, 0.6, intcmp, inthash);
// Add pairs to the hashmap
for (int i = 0; i < 20; i++)
{
// Map integers to doubles
hm_insert(my_map, i, (double)i / 10.0);
}
// Iterate from the start (index 0) to the end (index count - 1) of the hashmap
for (hashmap_iter it = my_map->it_start(my_map); // Initialize iterator 'it' to the start of the hashmap
!hm_iter_end(&it); // Conditional stop (until it is not at the end)
hm_iter_next(&it)) // Iterator goes one position forward
{
// Access the current key
int k = hm_iter_key(&it);
// Access the current value
double v = hm_iter_value(&it);
// Access the current index (index is relative to all the pairs in the iteration)
size_t i = hm_iter_index(&it);
// Print hashmap
// Index is useful in situations like this
// If it is the first pair
if (i == 0)
printf("[ {%d:%.2lf}, ", k, v);
// If it is the last pair
else if (i == hm_count(my_map) - 1)
printf("{%d:%.2lf} ]\n", k, v);
// For pairs at the middle
else
printf("{%d:%.2lf}, ", k, v);
}
// Index can also be used to iterate over a certain portion of a collection
size_t limit = hm_count(my_map) / 2;
for (hashmap_iter it = my_map->it_start(my_map); !hm_iter_end(&it); hm_iter_next(&it))
{
// Access the current key
int k = hm_iter_key(&it);
// Access the current value
double v = hm_iter_value(&it);
// Access the current index (index is relative to all the pairs in the iteration)
size_t i = hm_iter_index(&it);
// Print hashmap up until limit
// If it is the first pair
if (i == 0)
printf("[ {%d:%.2lf}, ", k, v);
// If it is the last pair
else if (i == limit - 1) // -1 because index is 0 based and we want half of the hashmap
{
printf("{%d:%.2lf} ]\n", k, v);
break;
}
// For pairs at the middle
else
printf("{%d:%.2lf}, ", k, v);
}
// Going backwards
for (hashmap_iter it = my_map->it_end(my_map); // Initialize iterator 'it' to the end of the hashmap
!hm_iter_start(&it); // Conditional stop (until it is not at the start)
hm_iter_prev(&it)) // Iterator goes one position backwards
{
// Access the current key
int k = hm_iter_key(&it);
// Access the current value
double v = hm_iter_value(&it);
// Access the current index (index is relative to all the pairs in the iteration)
size_t i = hm_iter_index(&it);
// Print hashmap
// Note how the conditions for the first and last pairs are simply swapped
// Because iterating backwards make the first pair be the index count - 1
// and the last one be the index 0
// If it is the first pair
if (i == hm_count(my_map) - 1)
printf("[ {%d:%.2lf}, ", k, v);
// If it is the last pair
else if (i == 0)
printf("{%d:%.2lf} ]\n", k, v);
// For pairs at the middle
else
printf("{%d:%.2lf}, ", k, v);
}
// You can also use iterators in a while loop
// But to do so you must declare the iterator struct outside the loop first
hashmap_iter it;
// You have three options:
// - Initialize it using the functions provided by the hashmap [ my_map->it_start() and my_map->it_end() ]
// - Initialize it using the init() function (when the iterator is already allocated)
// - Initialize it using the new() function (allocates on the heap, pointers only)
it = my_map->it_start(my_map);
it = my_map->it_end(my_map);
// This is equivalent to it_start()
hm_iter_init(&it, my_map);
// For pointers
// Also equivalent to it_start()
hashmap_iter *iter = hm_iter_new(my_map);
// The actual while loop
while (!hm_iter_end(iter))
{
// Accessing pairs
int k = hm_iter_key(iter);
double v = hm_iter_value(iter);
size_t i = hm_iter_index(iter);
// Print index and key value pair
printf("hashmap[%2" PRIuMAX "] = { %2d : %.2lf }\n", i, k, v);
// Move iterator forwards
hm_iter_next(iter);
}
// Send the iterator to the start of the hashmap
hm_iter_to_start(iter);
// Send the iterator to the end of the hashmap
hm_iter_to_end(iter);
// Backwards loop
while (!hm_iter_start(iter))
{
// Accessing pairs
int k = hm_iter_key(iter);
double v = hm_iter_value(iter);
size_t i = hm_iter_index(iter);
// Print index and the key value pair
printf("hashmap[%2" PRIuMAX "] = { %2d : %.2lf }\n", i, k, v);
// Move iterator backwards
hm_iter_prev(iter);
}
// Certain iterators also allow you to modify the contents it is iterating over
// Exceptions are collections that depend of the current state of the pair
// like tree-based collections and heap (collections that have some kind of ordering).
// You also can't change the keys of an associative collection
// Change every value where its key is divisible by 3 to the number 7
for (hm_iter_to_start(&it); !hm_iter_end(&it); hm_iter_next(&it))
{
// Get current key
int k = hm_iter_key(&it);
// Get a reference to the current value
double *v = hm_iter_rvalue(&it);
if (k % 3 == 0)
*v = 7;
}
// Now print it to see the difference
for (hashmap_iter it = my_map->it_start(my_map); !hm_iter_end(&it); hm_iter_next(&it))
{
int k = hm_iter_key(&it);
double v = hm_iter_value(&it);
size_t i = hm_iter_index(&it);
if (i == 0)
printf("[ {%d:%.2lf}, ", k, v);
else if (i == hm_count(my_map) - 1)
printf("{%d:%.2lf} ]\n", k, v);
else
printf("{%d:%.2lf}, ", k, v);
}
// Dispose the iterator called by hm_iter_new()
hm_iter_free(iter);
// Dispose the hashmap created
hm_free(my_map);
return 0;
}
+1
View File
@@ -1,3 +1,4 @@
# Hashset examples
* iterator.c - A complete example of the hashset iterator
* set_ops.c - Demonstrates common set operations like *union*, *intersection*, *difference* and *symmetric difference*.
+194
View File
@@ -0,0 +1,194 @@
/**
* iterator.c
*
* Creation Date: 15/05/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
* Iterator Example
*/
#include "hashset.h"
#include <stdio.h>
#include <inttypes.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;
}
// Creates a hashset of integers
HASHSET_GENERATE(hs, hashset, /* FMOD */, int)
int main(int argc, char const *argv[])
{
// Create a new hashset with an initial capacity of 100 and load factor of 0.6
hashset *my_hashset = hs_new(100, 0.6, intcmp, inthash);
// Add elements to the hashset
for (int i = 0; i < 20; i++)
{
hs_insert(my_hashset, i);
}
// Iterate from the start (index 0) to the end (index count - 1) of the hashset
for (hashset_iter it = my_hashset->it_start(my_hashset); // Initialize iterator 'it' to the start of the hashset
!hs_iter_end(&it); // Conditional stop (until it is not at the end)
hs_iter_next(&it)) // Iterator goes one position forward
{
// Access the current element
int e = hs_iter_value(&it);
// Access the current index (index is relative to all the elements in the iteration)
size_t i = hs_iter_index(&it);
// Print hashset
// Index is useful in situations like this
// If it is the first element
if (i == 0)
printf("[ %d, ", e);
// If it is the last element
else if (i == hs_count(my_hashset) - 1)
printf("%d ]\n", e);
// For elements at the middle
else
printf("%d, ", e);
}
// Index can also be used to iterate over a certain portion of a collection
size_t limit = hs_count(my_hashset) / 2;
for (hashset_iter it = my_hashset->it_start(my_hashset); !hs_iter_end(&it); hs_iter_next(&it))
{
// Access the current element
int e = hs_iter_value(&it);
// Access the current index (index is relative to all the elements in the iteration)
size_t i = hs_iter_index(&it);
// Print hashset up until limit
// If it is the first element
if (i == 0)
printf("[ %d, ", e);
// If it is the last element
else if (i == limit - 1) // -1 because index is 0 based and we want half of the hashset
{
printf("%d ]\n", e);
break;
}
// For elements at the middle
else
printf("%d, ", e);
}
// Going backwards
for (hashset_iter it = my_hashset->it_end(my_hashset); // Initialize iterator 'it' to the end of the hashset
!hs_iter_start(&it); // Conditional stop (until it is not at the start)
hs_iter_prev(&it)) // Iterator goes one position backwards
{
// Access the current element
int e = hs_iter_value(&it);
// Access the current index (index is relative to all the elements in the iteration)
size_t i = hs_iter_index(&it);
// Print hashset
// Note how the conditions for the first and last elements are simply swapped
// Because iterating backwards make the first element be the index count - 1
// and the last one be the index 0
// If it is the first element
if (i == hs_count(my_hashset) - 1)
printf("[ %d, ", e);
// If it is the last element
else if (i == 0)
printf("%d ]\n", e);
// For elements at the middle
else
printf("%d, ", e);
}
// You can also use iterators in a while loop
// But to do so you must declare the iterator struct outside the loop first
hashset_iter it;
// You have three options:
// - Initialize it using the functions provided by the hashset [ my_hashset->it_start() and my_hashset->it_end() ]
// - Initialize it using the init() function (when the iterator is already allocated)
// - Initialize it using the new() function (allocates on the heap, pointers only)
it = my_hashset->it_start(my_hashset);
it = my_hashset->it_end(my_hashset);
// This is equivalent to it_start()
hs_iter_init(&it, my_hashset);
// For pointers
// Also equivalent to it_start()
hashset_iter *iter = hs_iter_new(my_hashset);
// The actual while loop
while (!hs_iter_end(iter))
{
// Accessing elements
int e = hs_iter_value(iter);
size_t i = hs_iter_index(iter);
// Print index and element
printf("hashset[%2" PRIuMAX "] = %2d\n", i, e);
// Move iterator forwards
hs_iter_next(iter);
}
// Send the iterator to the start of the hashset
hs_iter_to_start(iter);
// Send the iterator to the end of the hashset
hs_iter_to_end(iter);
// Backwards loop
while (!hs_iter_start(iter))
{
// Accessing elements
int e = hs_iter_value(iter);
size_t i = hs_iter_index(iter);
// Print index and element
printf("hashset[%2" PRIuMAX "] = %2d\n", i, e);
// Move iterator backwards
hs_iter_prev(iter);
}
// Certain iterators also allow you to modify the contents it is iterating over
// Exceptions are collections that depend of the current state of the element
// like tree-based collections and heap (collections that have some kind of ordering).
// You also can't change the keys of an associative collection
// In the case of a hashset or any set, this is not possible because the
// values of a set are its keys. Changing the elements could cause the set
// to be in an invalid state.
// Dispose the iterator called by hs_iter_new()
hs_iter_free(iter);
// Dispose the hashset created
hs_free(my_hashset);
return 0;
}
+5 -6
View File
@@ -18,18 +18,17 @@
#include <stdlib.h>
#include "hashset.h"
// change to hashset to have the same effects
HASHSET_GENERATE(set, set, /* static */, int)
void print_set(set *s)
{
size_t index;
int result;
set_iter iter;
set_iter_new(&iter, s);
for (set_iter_tostart(&iter); !set_iter_end(&iter);)
set_iter_init(&iter, s);
for (set_iter_to_start(&iter); !set_iter_end(&iter); set_iter_next(&iter))
{
set_iter_next(&iter, &result, &index);
int result = set_iter_value(&iter);
size_t index = set_iter_index(&iter);
if (index == 0)
printf("[ %2d, ", result);
else if (index == s->count - 1)
+1
View File
@@ -1,3 +1,4 @@
# Heap examples
* heapsort.c - Uses the heap to sort the elements in a given array.
* iterator.c - A complete example of the heap iterator
+181
View File
@@ -0,0 +1,181 @@
/**
* iterator.c
*
* Creation Date: 15/05/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
* Iterator Example
*/
#include "heap.h"
#include <stdio.h>
#include <inttypes.h>
// Int compare function
int intcmp(int a, int b)
{
return a - b;
}
// Creates a heap of integers
HEAP_GENERATE(h, heap, /* FMOD */, int)
int main(int argc, char const *argv[])
{
// Create a new max heap with an initial capacity of 100
heap *my_heap = h_new(100, MaxHeap, intcmp);
// Add elements to the heap
for (int i = 0; i < 20; i++)
{
h_insert(my_heap, i);
}
// Iterate from the start (index 0) to the end (index count - 1) of the heap
for (heap_iter it = my_heap->it_start(my_heap); // Initialize iterator 'it' to the start of the heap
!h_iter_end(&it); // Conditional stop (until it is not at the end)
h_iter_next(&it)) // Iterator goes one position forward
{
// Access the current element
int e = h_iter_value(&it);
// Access the current index (index is relative to all the elements in the iteration)
size_t i = h_iter_index(&it);
// Print heap
// Index is useful in situations like this
// If it is the first element
if (i == 0)
printf("[ %d, ", e);
// If it is the last element
else if (i == h_count(my_heap) - 1)
printf("%d ]\n", e);
// For elements at the middle
else
printf("%d, ", e);
}
// Index can also be used to iterate over a certain portion of a collection
size_t limit = h_count(my_heap) / 2;
for (heap_iter it = my_heap->it_start(my_heap); !h_iter_end(&it); h_iter_next(&it))
{
// Access the current element
int e = h_iter_value(&it);
// Access the current index (index is relative to all the elements in the iteration)
size_t i = h_iter_index(&it);
// Print heap up until limit
// If it is the first element
if (i == 0)
printf("[ %d, ", e);
// If it is the last element
else if (i == limit - 1) // -1 because index is 0 based and we want half of the heap
{
printf("%d ]\n", e);
break;
}
// For elements at the middle
else
printf("%d, ", e);
}
// Going backwards
for (heap_iter it = my_heap->it_end(my_heap); // Initialize iterator 'it' to the end of the heap
!h_iter_start(&it); // Conditional stop (until it is not at the start)
h_iter_prev(&it)) // Iterator goes one position backwards
{
// Access the current element
int e = h_iter_value(&it);
// Access the current index (index is relative to all the elements in the iteration)
size_t i = h_iter_index(&it);
// Print heap
// Note how the conditions for the first and last elements are simply swapped
// Because iterating backwards make the first element be the index count - 1
// and the last one be the index 0
// If it is the first element
if (i == h_count(my_heap) - 1)
printf("[ %d, ", e);
// If it is the last element
else if (i == 0)
printf("%d ]\n", e);
// For elements at the middle
else
printf("%d, ", e);
}
// You can also use iterators in a while loop
// But to do so you must declare the iterator struct outside the loop first
heap_iter it;
// You have three options:
// - Initialize it using the functions provided by the heap [ my_heap->it_start() and my_heap->it_end() ]
// - Initialize it using the init() function (when the iterator is already allocated)
// - Initialize it using the new() function (allocates on the heap, pointers only)
it = my_heap->it_start(my_heap);
it = my_heap->it_end(my_heap);
// This is equivalent to it_start()
h_iter_init(&it, my_heap);
// For pointers
// Also equivalent to it_start()
heap_iter *iter = h_iter_new(my_heap);
// The actual while loop
while (!h_iter_end(iter))
{
// Accessing elements
int e = h_iter_value(iter);
size_t i = h_iter_index(iter);
// Print index and element
printf("heap[%2" PRIuMAX "] = %2d\n", i, e);
// Move iterator forwards
h_iter_next(iter);
}
// Send the iterator to the start of the heap
h_iter_to_start(iter);
// Send the iterator to the end of the heap
h_iter_to_end(iter);
// Backwards loop
while (!h_iter_start(iter))
{
// Accessing elements
int e = h_iter_value(iter);
size_t i = h_iter_index(iter);
// Print index and element
printf("heap[%2" PRIuMAX "] = %2d\n", i, e);
// Move iterator backwards
h_iter_prev(iter);
}
// Certain iterators also allow you to modify the contents it is iterating over
// Exceptions are collections that depend of the current state of the element
// like tree-based collections and heap (collections that have some kind of ordering).
// You also can't change the keys of an associative collection
// In the case of a heap this is not possible because the heap have its
// elements ordered. Changing them could cause the heap to be in an invalid
// state.
// Dispose the iterator called by h_iter_new()
h_iter_free(iter);
// Dispose the heap created
h_free(my_heap);
return 0;
}
+61
View File
@@ -0,0 +1,61 @@
/**
* deque.c
*
* Creation Date: 11/04/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#include "deque.h"
#include <stdio.h>
#include <stdlib.h>
DEQUE_GENERATE(d, deque, static, int)
int main(int argc, char const *argv[])
{
// Initialize deque and add some elements
deque *d = d_new(10);
for (int i = 0; i < 10; i++)
{
i % 2 == 0 ? d_push_back(d, i) : d_push_front(d, i);
}
// Initialize iterator
deque_iter iter;
d_iter_init(&iter, d);
// Make the iterator go back and forward
for (int j = 0; j < 4; j++)
{
while (!d_iter_end(&iter))
{
printf("C[%2d] = %2d\n", d_iter_index(&iter), d_iter_value(&iter));
d_iter_next(&iter);
}
printf("\n");
while (!d_iter_start(&iter))
{
printf("C[%2d] = %2d\n", d_iter_index(&iter), d_iter_value(&iter));
d_iter_prev(&iter);
}
printf("\n\n");
}
for (d_iter_to_start(&iter); !d_iter_end(&iter); d_iter_next(&iter))
{
printf("D[%2d] = %2d\n", d_iter_index(&iter), d_iter_value(&iter));
}
printf("\n");
for (d_iter_to_end(&iter); !d_iter_start(&iter); d_iter_prev(&iter))
{
printf("D[%2d] = %2d\n", d_iter_index(&iter), d_iter_value(&iter));
}
d_free(d);
return 0;
}
+77
View File
@@ -0,0 +1,77 @@
/**
* hashmap.c
*
* Creation Date: 11/04/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#include "hashmap.h"
#include <stdio.h>
#include <stdlib.h>
HASHMAP_GENERATE(hm, hmap, static, int, double)
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 intcmp(int a, int b)
{
return a - b;
}
int main(int argc, char const *argv[])
{
double varr[10] = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9};
// Initialize hashmap and add some element
hmap *hm = hm_new(50, 0.9, intcmp, inthash);
for (int i = 0; i < 10; i++)
hm_insert(hm, i, varr[i]);
// Initialize iterator
hmap_iter iter;
hm_iter_init(&iter, hm);
for (int j = 0; j < 4; j++)
{
while (!hm_iter_end(&iter))
{
printf("C[%2d] = { %2d : %2.2lf }\n", hm_iter_index(&iter), hm_iter_key(&iter), hm_iter_value(&iter));
hm_iter_next(&iter);
}
printf("\n");
while (!hm_iter_start(&iter))
{
printf("C[%2d] = { %2d : %2.2lf }\n", hm_iter_index(&iter), hm_iter_key(&iter), hm_iter_value(&iter));
hm_iter_prev(&iter);
}
printf("\n\n");
}
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("\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));
}
hm_free(hm);
return 0;
}
+76
View File
@@ -0,0 +1,76 @@
/**
* hashset.c
*
* Creation Date: 11/04/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#include "hashset.h"
#include <stdio.h>
#include <stdlib.h>
HASHSET_GENERATE(hs, hset, static, int)
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 intcmp(int a, int b)
{
return a - b;
}
int main(int argc, char const *argv[])
{
// Initialize hash set and add some elements
hset *hs = hs_new(10, 0.9, intcmp, inthash);
for (int i = 0; i < 10; i++)
hs_insert(hs, i);
// Initialize iterator
hset_iter iter;
hs_iter_init(&iter, hs);
// Make the iterator go back and forward
for (int j = 0; j < 4; j++)
{
while (!hs_iter_end(&iter))
{
printf("C[%2d] = %2d\n", hs_iter_index(&iter), hs_iter_value(&iter));
hs_iter_next(&iter);
}
printf("\n");
while (!hs_iter_start(&iter))
{
printf("C[%2d] = %2d\n", hs_iter_index(&iter), hs_iter_value(&iter));
hs_iter_prev(&iter);
}
printf("\n\n");
}
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("\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));
}
hs_free(hs);
return 0;
}
+64
View File
@@ -0,0 +1,64 @@
/**
* heap.c
*
* Creation Date: 11/04/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#include "heap.h"
#include <stdio.h>
#include <stdlib.h>
int intcmp(int a, int b)
{
return a - b;
}
HEAP_GENERATE(h, heap, static, int)
int main(int argc, char const *argv[])
{
// Initialize heap and add some elements
heap *h = h_new(10, MaxHeap, intcmp);
for (int i = 0; i < 10; i++)
h_insert(h, i);
// Initialize iterator
heap_iter iter;
h_iter_init(&iter, h);
// Make the iterator go back and forward
for (int j = 0; j < 4; j++)
{
while (!h_iter_end(&iter))
{
printf("C[%2d] = %2d\n", h_iter_index(&iter), h_iter_value(&iter));
h_iter_next(&iter);
}
printf("\n");
while (!h_iter_start(&iter))
{
printf("C[%2d] = %2d\n", h_iter_index(&iter), h_iter_value(&iter));
h_iter_prev(&iter);
}
printf("\n\n");
}
for (h_iter_to_start(&iter); !h_iter_end(&iter); h_iter_next(&iter))
{
printf("H[%2d] = %2d\n", h_iter_index(&iter), h_iter_value(&iter));
}
printf("\n");
for (h_iter_to_end(&iter); !h_iter_start(&iter); h_iter_prev(&iter))
{
printf("H[%2d] = %2d\n", h_iter_index(&iter), h_iter_value(&iter));
}
h_free(h);
return 0;
}
+59
View File
@@ -0,0 +1,59 @@
/**
* linkedlist.c
*
* Creation Date: 11/04/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#include "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();
for (int i = 0; i < 10; i++)
ll_push_back(l, i);
// Initialize iterator
linkedlist_iter iter;
ll_iter_init(&iter, l);
// Make the iterator go back and forward
for (int j = 0; j < 4; j++)
{
while (!ll_iter_end(&iter))
{
printf("C[%2d] = %2d\n", ll_iter_index(&iter), ll_iter_value(&iter));
ll_iter_next(&iter);
}
printf("\n");
while (!ll_iter_start(&iter))
{
printf("C[%2d] = %2d\n", ll_iter_index(&iter), ll_iter_value(&iter));
ll_iter_prev(&iter);
}
printf("\n\n");
}
for (ll_iter_to_start(&iter); !ll_iter_end(&iter); ll_iter_next(&iter))
{
printf("LL[%2d] = %2d\n", ll_iter_index(&iter), ll_iter_value(&iter));
}
printf("\n");
for (ll_iter_to_end(&iter); !ll_iter_start(&iter); ll_iter_prev(&iter))
{
printf("LL[%2d] = %2d\n", ll_iter_index(&iter), ll_iter_value(&iter));
}
ll_free(l);
return 0;
}
+59
View File
@@ -0,0 +1,59 @@
/**
* list.c
*
* Creation Date: 11/04/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#include "list.h"
#include <stdio.h>
#include <stdlib.h>
LIST_GENERATE(l, list, static, int)
int main(int argc, char const *argv[])
{
// Initialize list and add some elements
list *l = l_new(10);
for (int i = 0; i < 10; i++)
l_push_back(l, i);
// Initialize iterator
list_iter iter;
l_iter_init(&iter, l);
// Make the iterator go back and forward
for (int j = 0; j < 4; j++)
{
while (!l_iter_end(&iter))
{
printf("C[%2d] = %2d\n", l_iter_index(&iter), l_iter_value(&iter));
l_iter_next(&iter);
}
printf("\n");
while (!l_iter_start(&iter))
{
printf("C[%2d] = %2d\n", l_iter_index(&iter), l_iter_value(&iter));
l_iter_prev(&iter);
}
printf("\n\n");
}
for (l_iter_to_start(&iter); !l_iter_end(&iter); l_iter_next(&iter))
{
printf("L[%2d] = %2d\n", l_iter_index(&iter), l_iter_value(&iter));
}
printf("\n");
for (l_iter_to_end(&iter); !l_iter_start(&iter); l_iter_prev(&iter))
{
printf("L[%2d] = %2d\n", l_iter_index(&iter), l_iter_value(&iter));
}
l_free(l);
return 0;
}
@@ -1,10 +1,15 @@
// Checks if the queue iterator can go back and forward in the queue without
// hitting invalid states or a null pointer. Check is done visually.
/**
* queue.c
*
* Creation Date: 11/04/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "../../src/queue.h"
#include "queue.h"
QUEUE_GENERATE(q, queue, static, int)
@@ -20,7 +25,7 @@ int main(int argc, char const *argv[])
// Initialize iterator
queue_iter iter;
q_iter_new(&iter, q);
q_iter_init(&iter, q);
// Make the iterator go back and forward
for (int j = 0; j < 4; j++)
@@ -1,10 +1,15 @@
// Checks if the stack iterator can go back and forward in the stack without
// hitting invalid states or a null pointer. Check is done visually.
/**
* stack.c
*
* Creation Date: 11/04/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "../../src/stack.h"
#include "stack.h"
STACK_GENERATE(s, stack, static, int)
@@ -20,7 +25,7 @@ int main(int argc, char const *argv[])
// Initialize iterator
stack_iter iter;
s_iter_new(&iter, s);
s_iter_init(&iter, s);
// Make the iterator go back and forward
for (int j = 0; j < 4; j++)
@@ -1,10 +1,15 @@
// Checks if the treemap iterator can go back and forward in the treemap without
// hitting invalid states or a null pointer. Check is done visually.
/**
* treemap.c
*
* Creation Date: 11/04/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "../../src/treemap.h"
#include "treemap.h"
int intcmp(int a, int b)
{
@@ -26,7 +31,7 @@ int main(int argc, char const *argv[])
// Initialize iterator
tmap_iter iter;
tm_iter_new(&iter, tm);
tm_iter_init(&iter, tm);
// Make the iterator go back and forward
for (int j = 0; j < 4; j++)
@@ -1,10 +1,15 @@
// Checks if the treeset iterator can go back and forward in the treeset without
// hitting invalid states or a null pointer. Check is done visually.
/**
* treeset.c
*
* Creation Date: 11/04/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "../../src/treeset.h"
#include "treeset.h"
int intcmp(int a, int b)
{
@@ -25,7 +30,7 @@ int main(int argc, char const *argv[])
// Initialize iterator
tset_iter iter;
ts_iter_new(&iter, ts);
ts_iter_init(&iter, ts);
// Make the iterator go back and forward
for (int j = 0; j < 4; j++)
+1 -1
View File
@@ -1,4 +1,4 @@
# Linkedlist examples
* iterator.c - Example of using a linked list iterator.
* iterator.c - A complete example of the linked list iterator
* linked_list_node.c - Example of using functions that add or remove elements relative to a node.
+172 -23
View File
@@ -1,46 +1,195 @@
/**
* iterator.c
*
* Creation Date: 22/03/2019
* Creation Date: 10/05/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
* Iterator Example
*/
#include <stdio.h>
#include "linkedlist.h"
#include <stdio.h>
#include <inttypes.h>
LINKEDLIST_GENERATE(ll, linked, static, int)
// Creates a linkedlist of integers
LINKEDLIST_GENERATE(ll, linkedlist, /* FMOD */, int)
int main(int argc, char const *argv[])
{
size_t i;
int r;
// Create a new linkedlist
linkedlist *my_linkedlist = ll_new();
// Initliazie linked list and add some elements
linked *ll = ll_new();
// Add elements to the linkedlist
for (int i = 0; i < 20; i++)
ll_push_back(ll, i);
{
ll_push_back(my_linkedlist, i);
}
// Initialize iterator
linked_iter iter;
ll_iter_new(&iter, ll);
// Iterate from the start (index 0) to the end (index count - 1) of the linkedlist
for (linkedlist_iter it = my_linkedlist->it_start(my_linkedlist); // Initialize iterator 'it' to the start of the linkedlist
!ll_iter_end(&it); // Conditional stop (until it is not at the end)
ll_iter_next(&it)) // Iterator goes one position forward
{
// Access the current element
int e = ll_iter_value(&it);
// Move cursor to the end of the list
ll_iter_toend(&iter);
// While there is a previous element on the list
while (ll_iter_prev(&iter, &r, &i))
printf("list[%2d] = %2d\n", i, r);
// Access the current index (index is relative to all the elements in the iteration)
size_t i = ll_iter_index(&it);
printf("\n");
// Print linkedlist
// Move cursor to the start of the list
ll_iter_tostart(&iter);
// While there is a next element on the list
while (ll_iter_next(&iter, &r, &i))
printf("list[%2d] = %2d\n", i, r);
// Index is useful in situations like this
// If it is the first element
if (i == 0)
printf("[ %d, ", e);
// If it is the last element
else if (i == ll_count(my_linkedlist) - 1)
printf("%d ]\n", e);
// For elements at the middle
else
printf("%d, ", e);
}
ll_free(ll);
// Index can also be used to iterate over a certain portion of a collection
size_t limit = ll_count(my_linkedlist) / 2;
for (linkedlist_iter it = my_linkedlist->it_start(my_linkedlist); !ll_iter_end(&it); ll_iter_next(&it))
{
// Access the current element
int e = ll_iter_value(&it);
// Access the current index (index is relative to all the elements in the iteration)
size_t i = ll_iter_index(&it);
// Print linkedlist up until limit
// If it is the first element
if (i == 0)
printf("[ %d, ", e);
// If it is the last element
else if (i == limit - 1) // -1 because index is 0 based and we want half of the linkedlist
{
printf("%d ]\n", e);
break;
}
// For elements at the middle
else
printf("%d, ", e);
}
// Going backwards
for (linkedlist_iter it = my_linkedlist->it_end(my_linkedlist); // Initialize iterator 'it' to the end of the linkedlist
!ll_iter_start(&it); // Conditional stop (until it is not at the start)
ll_iter_prev(&it)) // Iterator goes one position backwards
{
// Access the current element
int e = ll_iter_value(&it);
// Access the current index (index is relative to all the elements in the iteration)
size_t i = ll_iter_index(&it);
// Print linkedlist
// Note how the conditions for the first and last elements are simply swapped
// Because iterating backwards make the first element be the index count - 1
// and the last one be the index 0
// If it is the first element
if (i == ll_count(my_linkedlist) - 1)
printf("[ %d, ", e);
// If it is the last element
else if (i == 0)
printf("%d ]\n", e);
// For elements at the middle
else
printf("%d, ", e);
}
// You can also use iterators in a while loop
// But to do so you must declare the iterator struct outside the loop first
linkedlist_iter it;
// You have three options:
// - Initialize it using the functions provided by the linkedlist [ my_linkedlist->it_start() and my_linkedlist->it_end() ]
// - Initialize it using the init() function (when the iterator is already allocated)
// - Initialize it using the new() function (allocates on the heap, pointers only)
it = my_linkedlist->it_start(my_linkedlist);
it = my_linkedlist->it_end(my_linkedlist);
// This is equivalent to it_start()
ll_iter_init(&it, my_linkedlist);
// For pointers
// Also equivalent to it_start()
linkedlist_iter *iter = ll_iter_new(my_linkedlist);
// The actual while loop
while (!ll_iter_end(iter))
{
// Accessing elements
int e = ll_iter_value(iter);
size_t i = ll_iter_index(iter);
// Print index and element
printf("linkedlist[%2" PRIuMAX "] = %2d\n", i, e);
// Move iterator forwards
ll_iter_next(iter);
}
// Send the iterator to the start of the linkedlist
ll_iter_to_start(iter);
// Send the iterator to the end of the linkedlist
ll_iter_to_end(iter);
// Backwards loop
while (!ll_iter_start(iter))
{
// Accessing elements
int e = ll_iter_value(iter);
size_t i = ll_iter_index(iter);
// Print index and element
printf("linkedlist[%2" PRIuMAX "] = %2d\n", i, e);
// Move iterator backwards
ll_iter_prev(iter);
}
// Certain iterators also allow you to modify the contents it is iterating over
// Exceptions are collections that depend of the current state of the element
// like tree-based collections and heap (collections that have some kind of ordering).
// You also can't change the keys of an associative collection
// Change every element that is divisible by 2 to the number 7
for (ll_iter_to_start(&it); !ll_iter_end(&it); ll_iter_next(&it))
{
// Get a reference to the current value
int *r = ll_iter_rvalue(&it);
if (r != NULL && *r % 2 == 0)
*r = 7;
}
// Now print it to see the difference
for (linkedlist_iter it = my_linkedlist->it_start(my_linkedlist); !ll_iter_end(&it); ll_iter_next(&it))
{
int e = ll_iter_value(&it);
size_t i = ll_iter_index(&it);
if (i == 0)
printf("[ %d, ", e);
else if (i == ll_count(my_linkedlist) - 1)
printf("%d ]\n", e);
else
printf("%d, ", e);
}
// Dispose the iterator called by ll_iter_new()
ll_iter_free(iter);
// Dispose the linkedlist created
ll_free(my_linkedlist);
return 0;
}
+22 -6
View File
@@ -7,13 +7,14 @@
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#include "linkedlist.h"
#include <stdio.h>
#include <assert.h>
#include "linkedlist.h"
#include <inttypes.h>
LINKEDLIST_GENERATE(l, list, /* static */, int)
int main(int argc, char const *argv[])
int main(void)
{
list *l = l_new();
@@ -25,14 +26,14 @@ int main(int argc, char const *argv[])
{
if (node->data % 3 == 0)
{
l_insert_prv(node, 33);
l_insert_nxt(node, 99);
l_insert_before(l, node, 33);
l_insert_after(l, node, 99);
node = node->next; // skip 99
}
}
size_t s = 0;
for (list_node *node = l_front_node(l); node != NULL; node = l_next_node(node), s++)
for (list_node *node = l_head(l); node != NULL; node = l_next_node(node), s++)
{
if (node->prev == NULL)
printf("[ %d, ", node->data);
@@ -42,7 +43,22 @@ int main(int argc, char const *argv[])
printf("%d, ", node->data);
}
printf("List Head: %d\nList Tail: %d\nList Count: %d\n", l->head->data, l->tail->data, l->count);
printf("\n\n");
s = 0;
for (list_node *node = l_tail(l); node != NULL; node = l_prev_node(node), s++)
{
if (node->next == NULL)
printf("[ %d, ", node->data);
else if (node->prev == NULL)
printf("%d ]\n", node->data);
else
printf("%d, ", node->data);
}
printf("\n\n");
printf("List Head: %d\nList Tail: %d\nList Count: %" PRIuMAX "\n", l->head->data, l->tail->data, l->count);
assert(s == l->count);
+3 -1
View File
@@ -1,3 +1,5 @@
# List examples
Currently none
* iterator.c - A complete example of the list iterator
* list.c - Example of using a list and its iterator.
* string.c - How to treat a list as a mutable string.
+195
View File
@@ -0,0 +1,195 @@
/**
* iterator.c
*
* Creation Date: 10/05/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
* Iterator Example
*/
#include "list.h"
#include <stdio.h>
#include <inttypes.h>
// Creates a list of integers
LIST_GENERATE(l, list, /* FMOD */, int)
int main(int argc, char const *argv[])
{
// Create a new list with an initial capacity of 100
list *my_list = l_new(100);
// Add elements to the list
for (int i = 0; i < 20; i++)
{
l_push_back(my_list, i);
}
// Iterate from the start (index 0) to the end (index count - 1) of the list
for (list_iter it = my_list->it_start(my_list); // Initialize iterator 'it' to the start of the list
!l_iter_end(&it); // Conditional stop (until it is not at the end)
l_iter_next(&it)) // Iterator goes one position forward
{
// Access the current element
int e = l_iter_value(&it);
// Access the current index (index is relative to all the elements in the iteration)
size_t i = l_iter_index(&it);
// Print list
// Index is useful in situations like this
// If it is the first element
if (i == 0)
printf("[ %d, ", e);
// If it is the last element
else if (i == l_count(my_list) - 1)
printf("%d ]\n", e);
// For elements at the middle
else
printf("%d, ", e);
}
// Index can also be used to iterate over a certain portion of a collection
size_t limit = l_count(my_list) / 2;
for (list_iter it = my_list->it_start(my_list); !l_iter_end(&it); l_iter_next(&it))
{
// Access the current element
int e = l_iter_value(&it);
// Access the current index (index is relative to all the elements in the iteration)
size_t i = l_iter_index(&it);
// Print list up until limit
// If it is the first element
if (i == 0)
printf("[ %d, ", e);
// If it is the last element
else if (i == limit - 1) // -1 because index is 0 based and we want half of the list
{
printf("%d ]\n", e);
break;
}
// For elements at the middle
else
printf("%d, ", e);
}
// Going backwards
for (list_iter it = my_list->it_end(my_list); // Initialize iterator 'it' to the end of the list
!l_iter_start(&it); // Conditional stop (until it is not at the start)
l_iter_prev(&it)) // Iterator goes one position backwards
{
// Access the current element
int e = l_iter_value(&it);
// Access the current index (index is relative to all the elements in the iteration)
size_t i = l_iter_index(&it);
// Print list
// Note how the conditions for the first and last elements are simply swapped
// Because iterating backwards make the first element be the index count - 1
// and the last one be the index 0
// If it is the first element
if (i == l_count(my_list) - 1)
printf("[ %d, ", e);
// If it is the last element
else if (i == 0)
printf("%d ]\n", e);
// For elements at the middle
else
printf("%d, ", e);
}
// You can also use iterators in a while loop
// But to do so you must declare the iterator struct outside the loop first
list_iter it;
// You have three options:
// - Initialize it using the functions provided by the list [ my_list->it_start() and my_list->it_end() ]
// - Initialize it using the init() function (when the iterator is already allocated)
// - Initialize it using the new() function (allocates on the heap, pointers only)
it = my_list->it_start(my_list);
it = my_list->it_end(my_list);
// This is equivalent to it_start()
l_iter_init(&it, my_list);
// For pointers
// Also equivalent to it_start()
list_iter *iter = l_iter_new(my_list);
// The actual while loop
while (!l_iter_end(iter))
{
// Accessing elements
int e = l_iter_value(iter);
size_t i = l_iter_index(iter);
// Print index and element
printf("list[%2" PRIuMAX "] = %2d\n", i, e);
// Move iterator forwards
l_iter_next(iter);
}
// Send the iterator to the start of the list
l_iter_to_start(iter);
// Send the iterator to the end of the list
l_iter_to_end(iter);
// Backwards loop
while (!l_iter_start(iter))
{
// Accessing elements
int e = l_iter_value(iter);
size_t i = l_iter_index(iter);
// Print index and element
printf("list[%2" PRIuMAX "] = %2d\n", i, e);
// Move iterator backwards
l_iter_prev(iter);
}
// Certain iterators also allow you to modify the contents it is iterating over
// Exceptions are collections that depend of the current state of the element
// like tree-based collections and heap (collections that have some kind of ordering).
// You also can't change the keys of an associative collection
// Change every element that is divisible by 2 to the number 7
for (l_iter_to_start(&it); !l_iter_end(&it); l_iter_next(&it))
{
// Get a reference to the current value
int *r = l_iter_rvalue(&it);
if (r != NULL && *r % 2 == 0)
*r = 7;
}
// Now print it to see the difference
for (list_iter it = my_list->it_start(my_list); !l_iter_end(&it); l_iter_next(&it))
{
int e = l_iter_value(&it);
size_t i = l_iter_index(&it);
if (i == 0)
printf("[ %d, ", e);
else if (i == l_count(my_list) - 1)
printf("%d ]\n", e);
else
printf("%d, ", e);
}
// Dispose the iterator called by l_iter_new()
l_iter_free(iter);
// Dispose the list created
l_free(my_list);
return 0;
}
+75
View File
@@ -0,0 +1,75 @@
/**
* list.c
*
* Creation Date: 08/04/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#include "list.h"
#include <stdio.h>
LIST_GENERATE(l, list, /* FMOD */, int)
int main(int argc, char const *argv[])
{
// Create a list with internal capacity of 100
list *my_list = l_new(100);
// - push_front (index: 0) [Complexity: O(N)]
// - push (index: give) [Complexity: O(N)*]
// - push_back (index: count) [Complexity: O(1)]
//
// - pop_front (index: 0) [Complexity: O(N)]
// - pop (index: given) [Complexity: O(N)*]
// - push_back (index: count - 1) [Complexity: O(1)]
//
// *average
//
// Average list Input/Output: O(N)
for (int i = 0; i < 200; i++)
{
// Add elements to the list
l_push_back(my_list, i);
}
// Erase all values from the list
l_clear(my_list);
// Now that list is empty, add only even numbers
for (int i = 0; i < 200; i++)
{
// Add even numbers to a given index. In this case they are being added
// to the end of the list (count index == push_back). With a condition
// of being even (i % 2 == 0)
bool added = l_push_if(my_list, i, l_count(my_list), i % 2 == 0);
// If added is true, the element was added to the list
}
// Iterator
list_iter iter;
int result, sum = 0;
size_t index;
// Iterate over each element starting from the start (iter_new positions
// the iterator to the start of the list) until the end of the list.
for (l_iter_init(&iter, my_list); !l_iter_end(&iter); l_iter_next(&iter))
{
// Here index corresponds to the position of the result relative to all
// other elements in the iteration. It is only a coincidence that the
// index here is the same as the result's position in the list.
index = l_iter_index(&iter);
result = l_iter_value(&iter);
// Do whatever you want with result and index, e.g.
sum += result * index;
}
// Release resources
l_free(my_list);
return 0;
}
+163
View File
@@ -0,0 +1,163 @@
/**
* string.c
*
* Creation Date: 08/04/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#include "list.h"
#include <stdio.h>
#include <string.h>
LIST_GENERATE(str, string, /* FMOD */, char)
// Comparison function
int chrcmp(char a, char b)
{
return (a > b) - (a < b);
}
void print_str(string *str)
{
// If the buffer is not completely filled, there will be at least one null
// byte in the end of the list's contents. This printf is possible but very
// dangerous as you might end up printing something else from memory until
// a null byte.
printf("%s\n", str->buffer);
printf("Size: %llu\n", str_count(str));
}
int main(int argc, char const *argv[])
{
// How to treat a list as a mutable string without \0 at the end
char *example1 = "Lorem ipsum";
char *example2 = "dolor sit amet";
char *example3 = "consectetur";
string *my_str = str_new_from(example2, strlen(example2));
// Add a single character to the front of the list
str_push_front(my_str, ' ');
// Add a sequence of characters to the front of the list
str_prepend(my_str, example1, strlen(example1));
// Add a charater to the back of the list
str_push_back(my_str, ' ');
// Add a sequence of characters to the back of the list
str_append(my_str, example3, strlen(example3));
// Iterate through each letter and print it
string_iter iter;
str_iter_init(&iter, my_str);
size_t index;
char result;
// Printing each character
for (str_iter_to_start(&iter); !str_iter_end(&iter); str_iter_next(&iter))
{
putchar(str_iter_value(&iter));
}
printf("\n\n");
// You can also print it reversed
for (str_iter_to_end(&iter); !str_iter_start(&iter); str_iter_prev(&iter))
{
putchar(str_iter_value(&iter));
}
printf("\n\n");
// Now remove the first letter supposing we don't know where it starts
index = str_indexof(my_str, ' ', chrcmp, true);
if (index == str_count(my_str))
{
// char not found...
// Treat error
}
// Now that we know where the first word is, remove it, including the
// extra space. [from, to] are inclusive.
str_remove(my_str, 0, index);
// Print it once again
for (str_iter_to_start(&iter); !str_iter_end(&iter); str_iter_next(&iter))
{
putchar(str_iter_value(&iter));
}
printf("\nString length: %lu\n\n", str_count(my_str));
print_str(my_str);
// Removing last word.
// Finding last white space:
index = str_indexof(my_str, ' ', chrcmp, false);
// Extract last word including white space
string *str_out = str_extract(my_str, index, str_count(my_str) - 1);
if (!str_out)
printf("Could not extract string\n");
else
{
// Pop white space
str_pop_front(str_out);
for (str_iter_init(&iter, my_str); !str_iter_end(&iter); str_iter_next(&iter))
{
putchar(str_iter_value(&iter));
}
printf("\nString length: %lu\n\n", str_count(my_str));
for (str_iter_init(&iter, str_out); !str_iter_end(&iter); str_iter_next(&iter))
{
putchar(str_iter_value(&iter));
}
printf("\nString length: %lu\n", str_count(str_out));
}
// Free strings
str_free(my_str);
str_free(str_out);
printf("\n----------------------------------------\n\n");
// Another example follows
// Using prepend, insert, append, remove and extract functions
string *str = str_new(100);
str_prepend(str, "Hello World!", 12);
print_str(str);
str_insert(str, "Awesome ", 8, 6);
print_str(str);
str_append(str, " Indigo.", 8);
print_str(str);
str_remove(str, 14, 20);
print_str(str);
string *str_res = str_extract(str, 5, 12);
print_str(str);
print_str(str_res);
str_free(str);
str_free(str_res);
return 0;
}
+1
View File
@@ -1,3 +1,4 @@
# Queue examples
* ice_cream.c - Example of what happens when you get late to the queue and the ice creams are sold out!
* iterator.c - A complete example of the queue iterator
+1 -1
View File
@@ -7,10 +7,10 @@
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#include "queue.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "queue.h"
QUEUE_GENERATE(q, queue, /* static */, const char *)
+195
View File
@@ -0,0 +1,195 @@
/**
* iterator.c
*
* Creation Date: 15/05/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
* Iterator Example
*/
#include "queue.h"
#include <stdio.h>
#include <inttypes.h>
// Creates a queue of integers
QUEUE_GENERATE(q, queue, /* FMOD */, int)
int main(int argc, char const *argv[])
{
// Create a new queue with an initial capacity of 100
queue *my_queue = q_new(100);
// Add elements to the queue
for (int i = 0; i < 20; i++)
{
q_enqueue(my_queue, i);
}
// Iterate from the start (front) to the end (rear) of the queue
for (queue_iter it = my_queue->it_start(my_queue); // Initialize iterator 'it' to the start of the queue
!q_iter_end(&it); // Conditional stop (until it is not at the end)
q_iter_next(&it)) // Iterator goes one position forward
{
// Access the current element
int e = q_iter_value(&it);
// Access the current index (index is relative to all the elements in the iteration)
size_t i = q_iter_index(&it);
// Print queue
// Index is useful in situations like this
// If it is the first element
if (i == 0)
printf("[ %d, ", e);
// If it is the last element
else if (i == q_count(my_queue) - 1)
printf("%d ]\n", e);
// For elements at the middle
else
printf("%d, ", e);
}
// Index can also be used to iterate over a certain portion of a collection
size_t limit = q_count(my_queue) / 2;
for (queue_iter it = my_queue->it_start(my_queue); !q_iter_end(&it); q_iter_next(&it))
{
// Access the current element
int e = q_iter_value(&it);
// Access the current index (index is relative to all the elements in the iteration)
size_t i = q_iter_index(&it);
// Print queue up until limit
// If it is the first element
if (i == 0)
printf("[ %d, ", e);
// If it is the last element
else if (i == limit - 1) // -1 because index is 0 based and we want half of the queue
{
printf("%d ]\n", e);
break;
}
// For elements at the middle
else
printf("%d, ", e);
}
// Going backwards
for (queue_iter it = my_queue->it_end(my_queue); // Initialize iterator 'it' to the end of the queue
!q_iter_start(&it); // Conditional stop (until it is not at the start)
q_iter_prev(&it)) // Iterator goes one position backwards
{
// Access the current element
int e = q_iter_value(&it);
// Access the current index (index is relative to all the elements in the iteration)
size_t i = q_iter_index(&it);
// Print queue
// Note how the conditions for the first and last elements are simply swapped
// Because iterating backwards make the first element be the index count - 1
// and the last one be the index 0
// If it is the first element
if (i == q_count(my_queue) - 1)
printf("[ %d, ", e);
// If it is the last element
else if (i == 0)
printf("%d ]\n", e);
// For elements at the middle
else
printf("%d, ", e);
}
// You can also use iterators in a while loop
// But to do so you must declare the iterator struct outside the loop first
queue_iter it;
// You have three options:
// - Initialize it using the functions provided by the queue [ my_queue->it_start() and my_queue->it_end() ]
// - Initialize it using the init() function (when the iterator is already allocated)
// - Initialize it using the new() function (allocates on the heap, pointers only)
it = my_queue->it_start(my_queue);
it = my_queue->it_end(my_queue);
// This is equivalent to it_start()
q_iter_init(&it, my_queue);
// For pointers
// Also equivalent to it_start()
queue_iter *iter = q_iter_new(my_queue);
// The actual while loop
while (!q_iter_end(iter))
{
// Accessing elements
int e = q_iter_value(iter);
size_t i = q_iter_index(iter);
// Print index and element
printf("queue[%2" PRIuMAX "] = %2d\n", i, e);
// Move iterator forwards
q_iter_next(iter);
}
// Send the iterator to the start of the queue
q_iter_to_start(iter);
// Send the iterator to the end of the queue
q_iter_to_end(iter);
// Backwards loop
while (!q_iter_start(iter))
{
// Accessing elements
int e = q_iter_value(iter);
size_t i = q_iter_index(iter);
// Print index and element
printf("queue[%2" PRIuMAX "] = %2d\n", i, e);
// Move iterator backwards
q_iter_prev(iter);
}
// Certain iterators also allow you to modify the contents it is iterating over
// Exceptions are collections that depend of the current state of the element
// like tree-based collections and heap (collections that have some kind of ordering).
// You also can't change the keys of an associative collection
// Change every element that is divisible by 3 to the number 7
for (q_iter_to_start(&it); !q_iter_end(&it); q_iter_next(&it))
{
// Get a reference to the current value
int *r = q_iter_rvalue(&it);
if (r != NULL && *r % 3 == 0)
*r = 7;
}
// Now print it to see the difference
for (queue_iter it = my_queue->it_start(my_queue); !q_iter_end(&it); q_iter_next(&it))
{
int e = q_iter_value(&it);
size_t i = q_iter_index(&it);
if (i == 0)
printf("[ %d, ", e);
else if (i == q_count(my_queue) - 1)
printf("%d ]\n", e);
else
printf("%d, ", e);
}
// Dispose the iterator called by q_iter_new()
q_iter_free(iter);
// Dispose the queue created
q_free(my_queue);
return 0;
}
+1
View File
@@ -1,3 +1,4 @@
# Stack examples
* hanoi.c - Animated example of solving the hanoi tower.
* iterator.c - A complete example of the stack iterator
-2
View File
@@ -13,8 +13,6 @@
STACK_GENERATE(s, stack, /* static */, int)
#define MAX(a, b) a > b ? a : b
void print_hanoi(stack *t1, stack *t2, stack *t3);
const char *draw(int value);
void move_disc(stack *from, stack *to);
+195
View File
@@ -0,0 +1,195 @@
/**
* iterator.c
*
* Creation Date: 15/05/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
* Iterator Example
*/
#include "stack.h"
#include <stdio.h>
#include <inttypes.h>
// Creates a stack of integers
STACK_GENERATE(s, stack, /* FMOD */, int)
int main(int argc, char const *argv[])
{
// Create a new stack with an initial capacity of 100
stack *my_stack = s_new(100);
// Add elements to the stack
for (int i = 0; i < 20; i++)
{
s_push(my_stack, i);
}
// Iterate from the start (top) to the end (bottom) of the stack
for (stack_iter it = my_stack->it_start(my_stack); // Initialize iterator 'it' to the start of the stack
!s_iter_end(&it); // Conditional stop (until it is not at the end)
s_iter_next(&it)) // Iterator goes one position forward
{
// Access the current element
int e = s_iter_value(&it);
// Access the current index (index is relative to all the elements in the iteration)
size_t i = s_iter_index(&it);
// Print stack
// Index is useful in situations like this
// If it is the first element
if (i == 0)
printf("[ %d, ", e);
// If it is the last element
else if (i == s_count(my_stack) - 1)
printf("%d ]\n", e);
// For elements at the middle
else
printf("%d, ", e);
}
// Index can also be used to iterate over a certain portion of a collection
size_t limit = s_count(my_stack) / 2;
for (stack_iter it = my_stack->it_start(my_stack); !s_iter_end(&it); s_iter_next(&it))
{
// Access the current element
int e = s_iter_value(&it);
// Access the current index (index is relative to all the elements in the iteration)
size_t i = s_iter_index(&it);
// Print stack up until limit
// If it is the first element
if (i == 0)
printf("[ %d, ", e);
// If it is the last element
else if (i == limit - 1) // -1 because index is 0 based and we want half of the stack
{
printf("%d ]\n", e);
break;
}
// For elements at the middle
else
printf("%d, ", e);
}
// Going backwards
for (stack_iter it = my_stack->it_end(my_stack); // Initialize iterator 'it' to the end of the stack
!s_iter_start(&it); // Conditional stop (until it is not at the start)
s_iter_prev(&it)) // Iterator goes one position backwards
{
// Access the current element
int e = s_iter_value(&it);
// Access the current index (index is relative to all the elements in the iteration)
size_t i = s_iter_index(&it);
// Print stack
// Note how the conditions for the first and last elements are simply swapped
// Because iterating backwards make the first element be the index count - 1
// and the last one be the index 0
// If it is the first element
if (i == s_count(my_stack) - 1)
printf("[ %d, ", e);
// If it is the last element
else if (i == 0)
printf("%d ]\n", e);
// For elements at the middle
else
printf("%d, ", e);
}
// You can also use iterators in a while loop
// But to do so you must declare the iterator struct outside the loop first
stack_iter it;
// You have three options:
// - Initialize it using the functions provided by the stack [ my_stack->it_start() and my_stack->it_end() ]
// - Initialize it using the init() function (when the iterator is already allocated)
// - Initialize it using the new() function (allocates on the heap, pointers only)
it = my_stack->it_start(my_stack);
it = my_stack->it_end(my_stack);
// This is equivalent to it_start()
s_iter_init(&it, my_stack);
// For pointers
// Also equivalent to it_start()
stack_iter *iter = s_iter_new(my_stack);
// The actual while loop
while (!s_iter_end(iter))
{
// Accessing elements
int e = s_iter_value(iter);
size_t i = s_iter_index(iter);
// Print index and element
printf("stack[%2" PRIuMAX "] = %2d\n", i, e);
// Move iterator forwards
s_iter_next(iter);
}
// Send the iterator to the start of the stack
s_iter_to_start(iter);
// Send the iterator to the end of the stack
s_iter_to_end(iter);
// Backwards loop
while (!s_iter_start(iter))
{
// Accessing elements
int e = s_iter_value(iter);
size_t i = s_iter_index(iter);
// Print index and element
printf("stack[%2" PRIuMAX "] = %2d\n", i, e);
// Move iterator backwards
s_iter_prev(iter);
}
// Certain iterators also allow you to modify the contents it is iterating over
// Exceptions are collections that depend of the current state of the element
// like tree-based collections and heap (collections that have some kind of ordering).
// You also can't change the keys of an associative collection
// Change every element that is divisible by 3 to the number 7
for (s_iter_to_start(&it); !s_iter_end(&it); s_iter_next(&it))
{
// Get a reference to the current value
int *r = s_iter_rvalue(&it);
if (r != NULL && *r % 3 == 0)
*r = 7;
}
// Now print it to see the difference
for (stack_iter it = my_stack->it_start(my_stack); !s_iter_end(&it); s_iter_next(&it))
{
int e = s_iter_value(&it);
size_t i = s_iter_index(&it);
if (i == 0)
printf("[ %d, ", e);
else if (i == s_count(my_stack) - 1)
printf("%d ]\n", e);
else
printf("%d, ", e);
}
// Dispose the iterator called by s_iter_new()
s_iter_free(iter);
// Dispose the stack created
s_free(my_stack);
return 0;
}
+2 -1
View File
@@ -1,3 +1,4 @@
# Treemap examples
Currently none
* pseudo_multiset.c - An example of how to make a multiset using a map.
* iterator.c - A complete example of the treemap iterator
+217
View File
@@ -0,0 +1,217 @@
/**
* iterator.c
*
* Creation Date: 16/05/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
* Iterator Example
*/
#include "treemap.h"
#include <stdio.h>
#include <inttypes.h>
// Int compare function
int intcmp(int a, int b)
{
return a - b;
}
// Creates a treemap of integers
TREEMAP_GENERATE(tm, treemap, /* FMOD */, int, double)
int main(int argc, char const *argv[])
{
// Create a new treemap
treemap *my_map = tm_new(intcmp);
// Add pairs to the treemap
for (int i = 0; i < 20; i++)
{
// Map integers to doubles
tm_insert(my_map, i, (double)i / 10.0);
}
// Iterate from the start (left-most node) to the end (right-most node) of the treemap
for (treemap_iter it = my_map->it_start(my_map); // Initialize iterator 'it' to the start of the treemap
!tm_iter_end(&it); // Conditional stop (until it is not at the end)
tm_iter_next(&it)) // Iterator goes one position forward
{
// Access the current key
int k = tm_iter_key(&it);
// Access the current value
double v = tm_iter_value(&it);
// Access the current index (index is relative to all the pairs in the iteration)
size_t i = tm_iter_index(&it);
// Print treemap
// Index is useful in situations like this
// If it is the first pair
if (i == 0)
printf("[ {%d:%.2lf}, ", k, v);
// If it is the last pair
else if (i == tm_count(my_map) - 1)
printf("{%d:%.2lf} ]\n", k, v);
// For pairs at the middle
else
printf("{%d:%.2lf}, ", k, v);
}
// Index can also be used to iterate over a certain portion of a collection
size_t limit = tm_count(my_map) / 2;
for (treemap_iter it = my_map->it_start(my_map); !tm_iter_end(&it); tm_iter_next(&it))
{
// Access the current key
int k = tm_iter_key(&it);
// Access the current value
double v = tm_iter_value(&it);
// Access the current index (index is relative to all the pairs in the iteration)
size_t i = tm_iter_index(&it);
// Print treemap up until limit
// If it is the first pair
if (i == 0)
printf("[ {%d:%.2lf}, ", k, v);
// If it is the last pair
else if (i == limit - 1) // -1 because index is 0 based and we want half of the treemap
{
printf("{%d:%.2lf} ]\n", k, v);
break;
}
// For pairs at the middle
else
printf("{%d:%.2lf}, ", k, v);
}
// Going backwards
for (treemap_iter it = my_map->it_end(my_map); // Initialize iterator 'it' to the end of the treemap
!tm_iter_start(&it); // Conditional stop (until it is not at the start)
tm_iter_prev(&it)) // Iterator goes one position backwards
{
// Access the current key
int k = tm_iter_key(&it);
// Access the current value
double v = tm_iter_value(&it);
// Access the current index (index is relative to all the pairs in the iteration)
size_t i = tm_iter_index(&it);
// Print treemap
// Note how the conditions for the first and last pairs are simply swapped
// Because iterating backwards make the first pair be the index count - 1
// and the last one be the index 0
// If it is the first pair
if (i == tm_count(my_map) - 1)
printf("[ {%d:%.2lf}, ", k, v);
// If it is the last pair
else if (i == 0)
printf("{%d:%.2lf} ]\n", k, v);
// For pairs at the middle
else
printf("{%d:%.2lf}, ", k, v);
}
// You can also use iterators in a while loop
// But to do so you must declare the iterator struct outside the loop first
treemap_iter it;
// You have three options:
// - Initialize it using the functions provided by the treemap [ my_map->it_start() and my_map->it_end() ]
// - Initialize it using the init() function (when the iterator is already allocated)
// - Initialize it using the new() function (allocates on the heap, pointers only)
it = my_map->it_start(my_map);
it = my_map->it_end(my_map);
// This is equivalent to it_start()
tm_iter_init(&it, my_map);
// For pointers
// Also equivalent to it_start()
treemap_iter *iter = tm_iter_new(my_map);
// The actual while loop
while (!tm_iter_end(iter))
{
// Accessing pairs
int k = tm_iter_key(iter);
double v = tm_iter_value(iter);
size_t i = tm_iter_index(iter);
// Print index and key value pair
printf("treemap[%2" PRIuMAX "] = { %2d : %.2lf }\n", i, k, v);
// Move iterator forwards
tm_iter_next(iter);
}
// Send the iterator to the start of the treemap
tm_iter_to_start(iter);
// Send the iterator to the end of the treemap
tm_iter_to_end(iter);
// Backwards loop
while (!tm_iter_start(iter))
{
// Accessing pairs
int k = tm_iter_key(iter);
double v = tm_iter_value(iter);
size_t i = tm_iter_index(iter);
// Print index and the key value pair
printf("treemap[%2" PRIuMAX "] = { %2d : %.2lf }\n", i, k, v);
// Move iterator backwards
tm_iter_prev(iter);
}
// Certain iterators also allow you to modify the contents it is iterating over
// Exceptions are collections that depend of the current state of the pair
// like tree-based collections and heap (collections that have some kind of ordering).
// You also can't change the keys of an associative collection
// Change every value where its key is divisible by 3 to the number 7
for (tm_iter_to_start(&it); !tm_iter_end(&it); tm_iter_next(&it))
{
// Get current key
int k = tm_iter_key(&it);
// Get a reference to the current value
double *v = tm_iter_rvalue(&it);
if (k % 3 == 0)
*v = 7;
}
// Now print it to see the difference
for (treemap_iter it = my_map->it_start(my_map); !tm_iter_end(&it); tm_iter_next(&it))
{
int k = tm_iter_key(&it);
double v = tm_iter_value(&it);
size_t i = tm_iter_index(&it);
if (i == 0)
printf("[ {%d:%.2lf}, ", k, v);
else if (i == tm_count(my_map) - 1)
printf("{%d:%.2lf} ]\n", k, v);
else
printf("{%d:%.2lf}, ", k, v);
}
// Dispose the iterator called by tm_iter_new()
tm_iter_free(iter);
// Dispose the treemap created
tm_free(my_map);
return 0;
}
+86
View File
@@ -0,0 +1,86 @@
/**
* pseudo_multiset.c
*
* Creation Date: 26/04/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
// How to make a multiset using a map
#include "treemap.h"
#include <stdio.h>
#include <inttypes.h>
// Mapping an integer by size_t which will represent the key's multiplicity
// (key could be anything and multiplicity could be an integer, preferably
// unsigned)
TREEMAP_GENERATE(tm, tmap, , int, size_t)
// Compare function used by the treemap
int intcmp(int a, int b)
{
return (a > b) - (a < b);
}
// Little helper to print the tree
void print_tree(tmap_node *root, int height)
{
if (!root)
return;
print_tree(root->right, height + 1);
for (int i = 0; i < height; i++)
printf("|------- ");
// Key:Multiplicity
printf("%d:%" PRIuMAX "\n", root->key, root->value);
print_tree(root->left, height + 1);
}
int main(int argc, char const *argv[])
{
tmap *map = tm_new(intcmp);
// Start adding elements
for (int i = 0; i < 100; i++)
{
// Modulo of 8 so we get some repetition
int key = i % 8;
// Get the reference to a value in the map with the key
size_t *rvalue = tm_get_ref(map, key);
// If the key exists, rvalue is not null
if (rvalue != NULL)
{
// Incrementing it means we have added another key to the set
// The value represents the multiplicity, that is, how many times
// we have added the key in the set
(*rvalue)++;
}
else
// Create a new entry with key with an initial multiplicity of 1
tm_insert(map, key, 1);
}
print_tree(map->root, 0);
// Summary
printf("\n---------- SUMMARY ----------\n\n");
// Print using iterator
for (tmap_iter it = map->it_start(map); !tm_iter_end(&it); tm_iter_next(&it))
{
// Map[key] = multiplicity
printf("Map[%2d] = %" PRIuMAX "\n", tm_iter_key(&it), tm_iter_value(&it));
}
tm_free(map);
return 0;
}
+1
View File
@@ -1,4 +1,5 @@
# Treeset examples
* iterator.c - A complete example of the treeset iterator
* set_ops.c - Demonstrates common set operations like *union*, *intersection*, *difference* and *symmetric difference*.
* tree_print.c - How to print a binary tree.
+194
View File
@@ -0,0 +1,194 @@
/**
* iterator.c
*
* Creation Date: 16/05/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
* Iterator Example
*/
#include "treeset.h"
#include <stdio.h>
#include <inttypes.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;
}
// Creates a treeset of integers
TREESET_GENERATE(ts, treeset, /* FMOD */, int)
int main(int argc, char const *argv[])
{
// Create a new treeset with an initial capacity of 100 and load factor of 0.6
treeset *my_treeset = ts_new(intcmp);
// Add elements to the treeset
for (int i = 0; i < 20; i++)
{
ts_insert(my_treeset, i);
}
// Iterate from the start (index 0) to the end (index count - 1) of the treeset
for (treeset_iter it = my_treeset->it_start(my_treeset); // Initialize iterator 'it' to the start of the treeset
!ts_iter_end(&it); // Conditional stop (until it is not at the end)
ts_iter_next(&it)) // Iterator goes one position forward
{
// Access the current element
int e = ts_iter_value(&it);
// Access the current index (index is relative to all the elements in the iteration)
size_t i = ts_iter_index(&it);
// Print treeset
// Index is useful in situations like this
// If it is the first element
if (i == 0)
printf("[ %d, ", e);
// If it is the last element
else if (i == ts_count(my_treeset) - 1)
printf("%d ]\n", e);
// For elements at the middle
else
printf("%d, ", e);
}
// Index can also be used to iterate over a certain portion of a collection
size_t limit = ts_count(my_treeset) / 2;
for (treeset_iter it = my_treeset->it_start(my_treeset); !ts_iter_end(&it); ts_iter_next(&it))
{
// Access the current element
int e = ts_iter_value(&it);
// Access the current index (index is relative to all the elements in the iteration)
size_t i = ts_iter_index(&it);
// Print treeset up until limit
// If it is the first element
if (i == 0)
printf("[ %d, ", e);
// If it is the last element
else if (i == limit - 1) // -1 because index is 0 based and we want half of the treeset
{
printf("%d ]\n", e);
break;
}
// For elements at the middle
else
printf("%d, ", e);
}
// Going backwards
for (treeset_iter it = my_treeset->it_end(my_treeset); // Initialize iterator 'it' to the end of the treeset
!ts_iter_start(&it); // Conditional stop (until it is not at the start)
ts_iter_prev(&it)) // Iterator goes one position backwards
{
// Access the current element
int e = ts_iter_value(&it);
// Access the current index (index is relative to all the elements in the iteration)
size_t i = ts_iter_index(&it);
// Print treeset
// Note how the conditions for the first and last elements are simply swapped
// Because iterating backwards make the first element be the index count - 1
// and the last one be the index 0
// If it is the first element
if (i == ts_count(my_treeset) - 1)
printf("[ %d, ", e);
// If it is the last element
else if (i == 0)
printf("%d ]\n", e);
// For elements at the middle
else
printf("%d, ", e);
}
// You can also use iterators in a while loop
// But to do so you must declare the iterator struct outside the loop first
treeset_iter it;
// You have three options:
// - Initialize it using the functions provided by the treeset [ my_treeset->it_start() and my_treeset->it_end() ]
// - Initialize it using the init() function (when the iterator is already allocated)
// - Initialize it using the new() function (allocates on the heap, pointers only)
it = my_treeset->it_start(my_treeset);
it = my_treeset->it_end(my_treeset);
// This is equivalent to it_start()
ts_iter_init(&it, my_treeset);
// For pointers
// Also equivalent to it_start()
treeset_iter *iter = ts_iter_new(my_treeset);
// The actual while loop
while (!ts_iter_end(iter))
{
// Accessing elements
int e = ts_iter_value(iter);
size_t i = ts_iter_index(iter);
// Print index and element
printf("treeset[%2" PRIuMAX "] = %2d\n", i, e);
// Move iterator forwards
ts_iter_next(iter);
}
// Send the iterator to the start of the treeset
ts_iter_to_start(iter);
// Send the iterator to the end of the treeset
ts_iter_to_end(iter);
// Backwards loop
while (!ts_iter_start(iter))
{
// Accessing elements
int e = ts_iter_value(iter);
size_t i = ts_iter_index(iter);
// Print index and element
printf("treeset[%2" PRIuMAX "] = %2d\n", i, e);
// Move iterator backwards
ts_iter_prev(iter);
}
// Certain iterators also allow you to modify the contents it is iterating over
// Exceptions are collections that depend of the current state of the element
// like tree-based collections and heap (collections that have some kind of ordering).
// You also can't change the keys of an associative collection
// In the case of a treeset or any set, this is not possible because the
// values of a set are its keys. Changing the elements could cause the set
// to be in an invalid state.
// Dispose the iterator called by ts_iter_new()
ts_iter_free(iter);
// Dispose the treeset created
ts_free(my_treeset);
return 0;
}
+5 -5
View File
@@ -22,13 +22,13 @@ TREESET_GENERATE(set, set, /* static */, int)
void print_set(set *s)
{
size_t index;
int result;
set_iter iter;
set_iter_new(&iter, s);
for (set_iter_tostart(&iter); !set_iter_end(&iter);)
set_iter_init(&iter, s);
for (set_iter_to_start(&iter); !set_iter_end(&iter); set_iter_next(&iter))
{
set_iter_next(&iter, &result, &index);
int result = set_iter_value(&iter);
size_t index = set_iter_index(&iter);
if (index == 0)
printf("[ %2d, ", result);
else if (index == s->count - 1)
+1 -1
View File
@@ -24,7 +24,7 @@ void print_tree(set_node *root, int height)
for (int i = 0; i < height; i++)
printf("|------- ");
printf("%d\n", root->key);
printf("%d\n", root->value);
print_tree(root->left, height + 1);
}
+443 -331
View File
@@ -37,339 +37,451 @@
#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) \
\
struct SNAME##_s \
{ \
V *buffer; \
size_t capacity; \
size_t count; \
size_t front; \
size_t rear; \
}; \
\
struct SNAME##_iter_s \
{ \
struct SNAME##_s *target; \
size_t cursor; \
size_t index; \
bool start; \
bool end; \
}; \
\
#define DEQUE_GENERATE_STRUCT(PFX, SNAME, FMOD, V)
/* HEADER ********************************************************************/
#define DEQUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
\
typedef struct SNAME##_s SNAME; \
typedef struct SNAME##_iter_s SNAME##_iter; \
\
FMOD SNAME *PFX##_new(size_t size); \
FMOD void PFX##_clear(SNAME *_deque_); \
FMOD void PFX##_free(SNAME *_deque_); \
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_); \
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); \
FMOD V PFX##_front(SNAME *_deque_); \
FMOD V PFX##_back(SNAME *_deque_); \
FMOD bool PFX##_empty(SNAME *_deque_); \
FMOD bool PFX##_full(SNAME *_deque_); \
FMOD size_t PFX##_count(SNAME *_deque_); \
FMOD size_t PFX##_capacity(SNAME *_deque_); \
\
FMOD void PFX##_iter_new(SNAME##_iter *iter, SNAME *target); \
FMOD bool PFX##_iter_start(SNAME##_iter *iter); \
FMOD bool PFX##_iter_end(SNAME##_iter *iter); \
FMOD void PFX##_iter_tostart(SNAME##_iter *iter); \
FMOD void PFX##_iter_toend(SNAME##_iter *iter); \
FMOD bool PFX##_iter_next(SNAME##_iter *iter, V *result, size_t *index); \
FMOD bool PFX##_iter_prev(SNAME##_iter *iter, V *result, size_t *index); \
\
#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 size); \
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); \
\
/* SOURCE ********************************************************************/
#define DEQUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \
\
FMOD bool PFX##_grow(SNAME *_deque_); \
\
FMOD SNAME *PFX##_new(size_t size) \
{ \
if (size < 1) \
return NULL; \
\
SNAME *_deque_ = malloc(sizeof(SNAME)); \
\
if (!_deque_) \
return NULL; \
\
_deque_->buffer = malloc(sizeof(V) * size); \
\
if (!_deque_->buffer) \
{ \
free(_deque_); \
return NULL; \
} \
\
memset(_deque_->buffer, 0, sizeof(V) * size); \
\
_deque_->capacity = size; \
_deque_->count = 0; \
_deque_->front = 0; \
_deque_->rear = 0; \
\
return _deque_; \
} \
\
FMOD void PFX##_clear(SNAME *_deque_) \
{ \
memset(_deque_->buffer, 0, sizeof(V) * _deque_->capacity); \
\
_deque_->count = 0; \
_deque_->front = 0; \
_deque_->rear = 0; \
} \
\
FMOD void PFX##_free(SNAME *_deque_) \
{ \
free(_deque_->buffer); \
free(_deque_); \
} \
\
FMOD bool PFX##_push_front(SNAME *_deque_, V element) \
{ \
if (PFX##_full(_deque_)) \
{ \
if (!PFX##_grow(_deque_)) \
return false; \
} \
\
_deque_->front = (_deque_->front == 0) ? _deque_->capacity - 1 : _deque_->front - 1; \
\
_deque_->buffer[_deque_->front] = element; \
\
_deque_->count++; \
\
return true; \
} \
\
FMOD bool PFX##_push_back(SNAME *_deque_, V element) \
{ \
if (PFX##_full(_deque_)) \
{ \
if (!PFX##_grow(_deque_)) \
return false; \
} \
\
_deque_->buffer[_deque_->rear] = element; \
\
_deque_->rear = (_deque_->rear == _deque_->capacity - 1) ? 0 : _deque_->rear + 1; \
\
_deque_->count++; \
\
return true; \
} \
\
FMOD bool PFX##_pop_front(SNAME *_deque_) \
{ \
if (PFX##_empty(_deque_)) \
return false; \
\
_deque_->buffer[_deque_->front] = 0; \
\
_deque_->front = (_deque_->front == _deque_->capacity - 1) ? 0 : _deque_->front + 1; \
\
_deque_->count--; \
\
return true; \
} \
\
FMOD bool PFX##_pop_back(SNAME *_deque_) \
{ \
if (PFX##_empty(_deque_)) \
return false; \
\
_deque_->rear = (_deque_->rear == 0) ? _deque_->capacity - 1 : _deque_->rear - 1; \
\
_deque_->buffer[_deque_->rear] = 0; \
\
_deque_->count--; \
\
return true; \
} \
\
FMOD bool PFX##_push_front_if(SNAME *_deque_, 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 (PFX##_empty(_deque_)) \
return 0; \
\
return _deque_->buffer[_deque_->front]; \
} \
\
FMOD V PFX##_back(SNAME *_deque_) \
{ \
if (PFX##_empty(_deque_)) \
return 0; \
\
return _deque_->buffer[(_deque_->rear == 0) ? _deque_->capacity - 1 : _deque_->rear - 1]; \
} \
\
FMOD bool PFX##_empty(SNAME *_deque_) \
{ \
return _deque_->count == 0; \
} \
\
FMOD bool PFX##_full(SNAME *_deque_) \
{ \
return _deque_->count >= _deque_->capacity; \
} \
\
FMOD size_t PFX##_count(SNAME *_deque_) \
{ \
return _deque_->count; \
} \
\
FMOD size_t PFX##_capacity(SNAME *_deque_) \
{ \
return _deque_->capacity; \
} \
\
FMOD bool PFX##_grow(SNAME *_deque_) \
{ \
\
size_t new_capacity = _deque_->capacity * 2; \
\
V *new_buffer = malloc(sizeof(V) * new_capacity); \
\
if (!new_buffer) \
return false; \
\
for (size_t i = _deque_->front, j = 0; j < _deque_->count; i = (i + 1) % _deque_->capacity, j++) \
{ \
new_buffer[j] = _deque_->buffer[i]; \
} \
\
free(_deque_->buffer); \
\
_deque_->buffer = new_buffer; \
_deque_->capacity = new_capacity; \
_deque_->front = 0; \
_deque_->rear = _deque_->count; \
\
return true; \
} \
\
FMOD void PFX##_iter_new(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 iter->cursor == iter->target->front && iter->start; \
} \
\
FMOD bool PFX##_iter_end(SNAME##_iter *iter) \
{ \
size_t real_rear = iter->target->rear == 0 ? iter->target->capacity - 1 : iter->target->rear - 1; \
return iter->cursor == real_rear && iter->end; \
} \
\
FMOD void PFX##_iter_tostart(SNAME##_iter *iter) \
{ \
iter->cursor = iter->target->front; \
iter->index = 0; \
iter->start = true; \
iter->end = PFX##_empty(iter->target); \
} \
\
FMOD void PFX##_iter_toend(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
iter->cursor = 0; \
else \
iter->cursor = (iter->target->rear == 0) ? iter->target->count - 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, V *result, size_t *index) \
{ \
if (iter->end) \
return false; \
\
*index = iter->index; \
*result = iter->target->buffer[iter->cursor]; \
iter->start = false; \
\
if (iter->index == iter->target->count - 1) \
iter->end = true; \
else \
{ \
iter->cursor = (iter->cursor + 1) % (iter->target->capacity); \
iter->index++; \
} \
\
return true; \
} \
\
FMOD bool PFX##_iter_prev(SNAME##_iter *iter, V *result, size_t *index) \
{ \
if (iter->start) \
return false; \
\
*index = iter->index; \
*result = iter->target->buffer[iter->cursor]; \
iter->end = false; \
\
if (iter->index == 0) \
iter->start = true; \
else \
{ \
iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; \
iter->index--; \
} \
\
return true; \
#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_); \
\
FMOD SNAME *PFX##_new(size_t size) \
{ \
if (size < 1) \
return NULL; \
\
SNAME *_deque_ = malloc(sizeof(SNAME)); \
\
if (!_deque_) \
return NULL; \
\
_deque_->buffer = malloc(sizeof(V) * size); \
\
if (!_deque_->buffer) \
{ \
free(_deque_); \
return NULL; \
} \
\
memset(_deque_->buffer, 0, sizeof(V) * size); \
\
_deque_->capacity = size; \
_deque_->count = 0; \
_deque_->front = 0; \
_deque_->back = 0; \
\
_deque_->it_start = PFX##_impl_it_start; \
_deque_->it_end = PFX##_impl_it_end; \
\
return _deque_; \
} \
\
FMOD void PFX##_clear(SNAME *_deque_) \
{ \
memset(_deque_->buffer, 0, sizeof(V) * _deque_->capacity); \
\
_deque_->count = 0; \
_deque_->front = 0; \
_deque_->back = 0; \
} \
\
FMOD void PFX##_free(SNAME *_deque_) \
{ \
free(_deque_->buffer); \
free(_deque_); \
} \
\
FMOD bool PFX##_push_front(SNAME *_deque_, V element) \
{ \
if (PFX##_full(_deque_)) \
{ \
if (!PFX##_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; \
} \
\
FMOD bool PFX##_push_back(SNAME *_deque_, V element) \
{ \
if (PFX##_full(_deque_)) \
{ \
if (!PFX##_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; \
} \
\
FMOD bool PFX##_pop_front(SNAME *_deque_) \
{ \
if (PFX##_empty(_deque_)) \
return false; \
\
_deque_->buffer[_deque_->front] = 0; \
\
_deque_->front = (_deque_->front == _deque_->capacity - 1) ? 0 : _deque_->front + 1; \
\
_deque_->count--; \
\
return true; \
} \
\
FMOD bool PFX##_pop_back(SNAME *_deque_) \
{ \
if (PFX##_empty(_deque_)) \
return false; \
\
_deque_->back = (_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1; \
\
_deque_->buffer[_deque_->back] = 0; \
\
_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 (PFX##_empty(_deque_)) \
return 0; \
\
return _deque_->buffer[_deque_->front]; \
} \
\
FMOD V PFX##_back(SNAME *_deque_) \
{ \
if (PFX##_empty(_deque_)) \
return 0; \
\
return _deque_->buffer[(_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1]; \
} \
\
FMOD bool PFX##_contains(SNAME *_deque_, V element, int (*comparator)(V, V)) \
{ \
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_) \
{ \
return _deque_->count == 0; \
} \
\
FMOD bool PFX##_full(SNAME *_deque_) \
{ \
return _deque_->count >= _deque_->capacity; \
} \
\
FMOD size_t PFX##_count(SNAME *_deque_) \
{ \
return _deque_->count; \
} \
\
FMOD size_t PFX##_capacity(SNAME *_deque_) \
{ \
return _deque_->capacity; \
} \
\
FMOD 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->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->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; \
} \
\
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) % (iter->target->capacity); \
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) ? iter->target->capacity - 1 : iter->cursor - 1; \
iter->index--; \
} \
\
return true; \
} \
\
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return 0; \
\
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; \
} \
\
FMOD bool PFX##_impl_grow(SNAME *_deque_) \
{ \
\
size_t new_capacity = _deque_->capacity * 2; \
\
V *new_buffer = malloc(sizeof(V) * 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; \
} \
\
SNAME##_iter PFX##_impl_it_start(SNAME *_deque_) \
{ \
SNAME##_iter iter; \
\
PFX##_iter_init(&iter, _deque_); \
\
return iter; \
} \
\
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 */
+15 -56
View File
@@ -11,63 +11,22 @@
#ifndef CMC_FOR_EACH
#define CMC_FOR_EACH
#include <stdlib.h>
#include <stdbool.h>
#define FOR_EACH(PFX, SNAME, V, TARGET, BODY) \
do \
{ \
size_t index; \
V value; \
SNAME##_iter iter; \
PFX##_iter_new(&iter, TARGET); \
while (PFX##_iter_next(&iter, &value, &index)) \
{ \
BODY; \
} \
#define FOR_EACH(PFX, SNAME, TARGET, BODY) \
do \
{ \
for (SNAME##_iter iter = TARGET->it_start(TARGET); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
{ \
BODY; \
} \
} while (0);
#define FOR_EACH_REV(PFX, SNAME, V, TARGET, BODY) \
do \
{ \
size_t index; \
V value; \
SNAME##_iter iter; \
PFX##_iter_new(&iter, TARGET); \
PFX##_iter_toend(&iter); \
while (PFX##_iter_prev(&iter, &value, &index)) \
{ \
BODY; \
} \
#define FOR_EACH_REV(PFX, SNAME, TARGET, BODY) \
do \
{ \
for (SNAME##_iter iter = TARGET->it_end(TARGET); !PFX##_iter_start(&iter); PFX##_iter_prev(&iter)) \
{ \
BODY; \
} \
} while (0);
#define FOR_EACH_MAP(PFX, SNAME, K, V, TARGET, BODY) \
do \
{ \
size_t index; \
K key; \
V value; \
SNAME##_iter iter; \
PFX##_iter_new(&iter, TARGET); \
while (PFX##_iter_next(&iter, &key, &value, &index)) \
{ \
BODY; \
} \
} while (0);
#define FOR_EACH_MAP_REV(PFX, SNAME, K, V, TARGET, BODY) \
do \
{ \
size_t index; \
K key; \
V value; \
SNAME##_iter iter; \
PFX##_iter_new(&iter, TARGET); \
PFX##_iter_toend(&iter); \
while (PFX##_iter_prev(&iter, &key, &value, &index)) \
{ \
BODY; \
} \
} while (0);
#endif /* CMC_FOR_EACH */
#endif /* CMC_FOR_EACH */
+329 -162
View File
@@ -29,13 +29,37 @@ typedef enum EntryState_e
ES_FILLED = 1
} EntryState;
static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
6151, 12289, 24593, 49157, 98317,
196613, 393241, 786433, 1572869,
3145739, 6291469, 12582917,
25165843, 50331653, 100663319,
201326611, 402653189, 805306457,
1610612741};
static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
3067, 6143, 12289, 24571, 49157,
98299, 196613, 393209, 786431,
1572869, 3145721, 6291449,
12582917, 25165813, 50331653,
100663291, 201326611, 402653189,
805306357, 1610612741,
3221225473, 6442450939,
12884901893, 25769803799,
51539607551, 103079215111,
206158430209, 412316860441,
824633720831, 1649267441651,
3298534883309, 6597069766657,
13194139533299, 26388279066623,
52776558133303, 105553116266489,
211106232532969, 422212465066001,
844424930131963,
1688849860263953,
3377699720527861,
6755399441055731,
13510798882111483,
27021597764222939,
54043195528445957,
108086391056891903,
216172782113783773,
432345564227567621,
864691128455135207,
1729382256910270481,
3458764513820540933,
6917529027641081903,
13835058055282163729llu};
#endif /* CMC_HASH_TABLE_SETUP */
@@ -57,78 +81,141 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
#define HASHMAP_GENERATE_SOURCE_PUBLIC(PFX, SNAME, FMOD, K, V) \
HASHMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V)
/* STRUCT ********************************************************************/
#define HASHMAP_GENERATE_STRUCT(PFX, SNAME, FMOD, K, V) \
\
struct SNAME##_s \
{ \
struct SNAME##_entry_s *buffer; \
size_t capacity; \
size_t count; \
double load; \
int (*cmp)(K, K); \
size_t (*hash)(K); \
}; \
\
struct SNAME##_entry_s \
{ \
K key; \
V value; \
size_t dist; \
enum EntryState_e state; \
}; \
\
struct SNAME##_iter_s \
{ \
struct SNAME##_s *target; \
size_t cursor; \
size_t index; \
size_t first; \
size_t last; \
bool start; \
bool end; \
}; \
\
#define HASHMAP_GENERATE_STRUCT(PFX, SNAME, FMOD, K, V)
/* HEADER ********************************************************************/
#define HASHMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \
\
typedef struct SNAME##_s SNAME; \
typedef struct SNAME##_entry_s SNAME##_entry; \
typedef struct SNAME##_iter_s SNAME##_iter; \
/* Hashmap Structure */ \
typedef struct SNAME##_s \
{ \
/* Array of Entries */ \
struct SNAME##_entry_s *buffer; \
\
/* Current array capacity */ \
size_t capacity; \
\
/* Current amount of keys */ \
size_t count; \
\
/* Load factor in range (0.0, 1.0) */ \
double load; \
\
/* Key comparison function */ \
int (*cmp)(K, K); \
\
/* Key hash function */ \
size_t (*hash)(K); \
\
/* Function that returns an iterator to the start of the hashmap */ \
struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
\
/* Function that returns an iterator to the end of the hashmap */ \
struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
\
} SNAME, *SNAME##_ptr; \
\
/* Hashmap Entry */ \
typedef struct SNAME##_entry_s \
{ \
/* Entry Key */ \
K key; \
\
/* Entry Value */ \
V value; \
\
/* The distance of this node to its original position, used by robin-hood hashing */ \
size_t dist; \
\
/* The sate of this node (DELETED, EMPTY, FILLED) */ \
enum EntryState_e state; \
\
} SNAME##_entry, *SNAME##_entry_ptr; \
\
/* Hashmap Iterator */ \
typedef struct SNAME##_iter_s \
{ \
/* Target hashmap */ \
struct SNAME##_s *target; \
\
/* Cursor's position (index) */ \
size_t cursor; \
\
/* Keeps track of relative index to the iteration of elements */ \
size_t index; \
\
/* The index of the first element */ \
size_t first; \
\
/* The index of the last element */ \
size_t last; \
\
/* 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, double load, int (*compare)(K, K), size_t (*hash)(K)); \
FMOD void PFX##_clear(SNAME *_map_); \
FMOD void PFX##_free(SNAME *_map_); \
/* Collection Input and Output */ \
FMOD bool PFX##_insert(SNAME *_map_, K key, V value); \
FMOD bool PFX##_remove(SNAME *_map_, K key, V *value); \
/* Conditional Input and Output */ \
FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition); \
FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition); \
/* Element Access */ \
FMOD bool PFX##_max(SNAME *_map_, K *key, V *value); \
FMOD bool PFX##_min(SNAME *_map_, K *key, V *value); \
FMOD V PFX##_get(SNAME *_map_, K key); \
FMOD V *PFX##_get_ref(SNAME *_map_, K key); \
/* Collection State */ \
FMOD bool PFX##_contains(SNAME *_map_, K key); \
FMOD bool PFX##_empty(SNAME *_map_); \
FMOD size_t PFX##_count(SNAME *_map_); \
FMOD size_t PFX##_capacity(SNAME *_map_); \
\
FMOD void PFX##_iter_new(SNAME##_iter *iter, SNAME *target); \
/* 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_tostart(SNAME##_iter *iter); \
FMOD void PFX##_iter_toend(SNAME##_iter *iter); \
FMOD bool PFX##_iter_next(SNAME##_iter *iter, K *key, V *value, size_t *index); \
FMOD bool PFX##_iter_prev(SNAME##_iter *iter, K *key, V *value, size_t *index); \
FMOD bool PFX##_iter_next(SNAME##_iter *iter); \
FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \
/* Iterator Access */ \
FMOD K PFX##_iter_key(SNAME##_iter *iter); \
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); \
\
/* SOURCE ********************************************************************/
#define HASHMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) \
\
FMOD bool PFX##_grow(SNAME *_map_); \
FMOD SNAME##_entry *PFX##_get_entry(SNAME *_map_, K key); \
FMOD size_t PFX##_calculate_size(size_t required); \
/* Implementation Detail Functions */ \
FMOD bool PFX##_impl_grow(SNAME *_map_); \
FMOD SNAME##_entry *PFX##_impl_get_entry(SNAME *_map_, K key); \
FMOD size_t PFX##_impl_calculate_size(size_t required); \
SNAME##_iter PFX##_impl_it_start(SNAME *_map_); \
SNAME##_iter PFX##_impl_it_end(SNAME *_map_); \
\
FMOD SNAME *PFX##_new(size_t size, double load, int (*compare)(K, K), size_t (*hash)(K)) \
{ \
if (size == 0 || load <= 0 || load >= 1) \
return NULL; \
\
size_t real_size = PFX##_calculate_size(size); \
size_t real_size = PFX##_impl_calculate_size(size); \
\
SNAME *_map_ = malloc(sizeof(SNAME)); \
\
@@ -151,6 +238,9 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
_map_->cmp = compare; \
_map_->hash = hash; \
\
_map_->it_start = PFX##_impl_it_start; \
_map_->it_end = PFX##_impl_it_end; \
\
return _map_; \
} \
\
@@ -171,7 +261,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
{ \
if ((double)_map_->capacity * _map_->load <= (double)_map_->count) \
{ \
if (!PFX##_grow(_map_)) \
if (!PFX##_impl_grow(_map_)) \
return false; \
} \
\
@@ -181,7 +271,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
\
SNAME##_entry *target = &(_map_->buffer[pos]); \
\
if (PFX##_get_entry(_map_, key) != NULL) \
if (PFX##_impl_get_entry(_map_, key) != NULL) \
return false; \
\
if (target->state == ES_EMPTY || target->state == ES_DELETED) \
@@ -204,6 +294,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
target->value = value; \
target->dist = pos - original_pos; \
target->state = ES_FILLED; \
\
break; \
} \
else if (target->dist < original_pos - pos) \
@@ -230,7 +321,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
\
FMOD bool PFX##_remove(SNAME *_map_, K key, V *value) \
{ \
SNAME##_entry *result = PFX##_get_entry(_map_, key); \
SNAME##_entry *result = PFX##_impl_get_entry(_map_, key); \
\
if (result == NULL) \
return false; \
@@ -268,23 +359,20 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
return false; \
\
SNAME##_iter iter; \
K result_key, max_key; \
V result_value; \
size_t index; \
\
for (PFX##_iter_new(&iter, _map_); !PFX##_iter_end(&iter);) \
for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
{ \
PFX##_iter_next(&iter, &result_key, &result_value, &index); \
K result_key = PFX##_iter_key(&iter); \
V result_value = PFX##_iter_value(&iter); \
size_t index = PFX##_iter_index(&iter); \
\
if (index == 0) \
{ \
max_key = result_key; \
*key = result_key; \
*value = result_value; \
} \
else if (_map_->cmp(result_key, max_key) > 0) \
else if (_map_->cmp(result_key, *key) > 0) \
{ \
max_key = result_key; \
*key = result_key; \
*value = result_value; \
} \
@@ -299,24 +387,21 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
return false; \
\
SNAME##_iter iter; \
K result_key, min_key; \
V result_value; \
size_t index; \
\
for (PFX##_iter_new(&iter, _map_); !PFX##_iter_end(&iter);) \
for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
{ \
PFX##_iter_next(&iter, &result_key, &result_value, &index); \
K result_key = PFX##_iter_key(&iter); \
V result_value = PFX##_iter_value(&iter); \
size_t index = PFX##_iter_index(&iter); \
\
if (index == 0) \
{ \
min_key = result_key; \
*key = result_key; \
*value = result_value; \
} \
else if (_map_->cmp(result_key, min_key) < 0) \
else if (_map_->cmp(result_key, *key) < 0) \
{ \
min_key = result_key; \
*key = min_key; \
*key = result_key; \
*value = result_value; \
} \
} \
@@ -326,7 +411,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
\
FMOD V PFX##_get(SNAME *_map_, K key) \
{ \
SNAME##_entry *entry = PFX##_get_entry(_map_, key); \
SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \
\
if (!entry) \
return 0; \
@@ -334,6 +419,21 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
return entry->value; \
} \
\
FMOD V *PFX##_get_ref(SNAME *_map_, K key) \
{ \
SNAME##_entry *entry = PFX##_impl_get_entry(_map_, key); \
\
if (!entry) \
return NULL; \
\
return &(entry->value); \
} \
\
FMOD bool PFX##_contains(SNAME *_map_, K key) \
{ \
return PFX##_impl_get_entry(_map_, key) != NULL; \
} \
\
FMOD bool PFX##_empty(SNAME *_map_) \
{ \
return _map_->count == 0; \
@@ -344,77 +444,29 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
return _map_->count; \
} \
\
FMOD bool PFX##_grow(SNAME *_map_) \
FMOD size_t PFX##_capacity(SNAME *_map_) \
{ \
size_t new_size = PFX##_calculate_size((size_t)((double)_map_->capacity * 1.5)); \
\
SNAME *_new_map_ = PFX##_new(new_size, _map_->load, _map_->cmp, _map_->hash); \
\
if (!_new_map_) \
return false; \
\
SNAME##_iter iter; \
K key; \
V value; \
size_t index; \
\
for (PFX##_iter_new(&iter, _map_); !PFX##_iter_end(&iter);) \
{ \
PFX##_iter_next(&iter, &key, &value, &index); \
PFX##_insert(_new_map_, key, value); \
} \
\
if (_map_->count != _new_map_->count) \
{ \
PFX##_free(_new_map_); \
return false; \
} \
\
SNAME##_entry *tmp = _map_->buffer; \
_map_->buffer = _new_map_->buffer; \
_new_map_->buffer = tmp; \
\
_map_->capacity = _new_map_->capacity; \
\
PFX##_free(_new_map_); \
\
return true; \
return _map_->capacity; \
} \
\
FMOD SNAME##_entry *PFX##_get_entry(SNAME *_map_, K key) \
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \
{ \
size_t hash = _map_->hash(key); \
size_t pos = hash % _map_->capacity; \
SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \
\
SNAME##_entry *target = &(_map_->buffer[pos % _map_->capacity]); \
if (!iter) \
return NULL; \
\
while (target->state == ES_FILLED || target->state == ES_DELETED) \
{ \
if (_map_->cmp(target->key, key) == 0) \
return target; \
PFX##_iter_init(iter, target); \
\
pos++; \
target = &(_map_->buffer[pos % _map_->capacity]); \
} \
\
return NULL; \
return iter; \
} \
\
FMOD size_t PFX##_calculate_size(size_t required) \
FMOD void PFX##_iter_free(SNAME##_iter *iter) \
{ \
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]; \
free(iter); \
} \
\
FMOD void PFX##_iter_new(SNAME##_iter *iter, SNAME *target) \
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \
{ \
iter->target = target; \
iter->cursor = 0; \
@@ -448,15 +500,15 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
\
FMOD bool PFX##_iter_start(SNAME##_iter *iter) \
{ \
return iter->start && iter->cursor == iter->first; \
return PFX##_empty(iter->target) || iter->start; \
} \
\
FMOD bool PFX##_iter_end(SNAME##_iter *iter) \
{ \
return iter->end && iter->cursor == iter->last; \
return PFX##_empty(iter->target) || iter->end; \
} \
\
FMOD void PFX##_iter_tostart(SNAME##_iter *iter) \
FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \
{ \
iter->cursor = iter->first; \
iter->index = 0; \
@@ -464,7 +516,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
iter->end = PFX##_empty(iter->target); \
} \
\
FMOD void PFX##_iter_toend(SNAME##_iter *iter) \
FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \
{ \
iter->cursor = iter->last; \
iter->index = iter->target->count - 1; \
@@ -472,30 +524,29 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
iter->end = true; \
} \
\
FMOD bool PFX##_iter_next(SNAME##_iter *iter, K *key, V *value, size_t *index) \
FMOD bool PFX##_iter_next(SNAME##_iter *iter) \
{ \
if (iter->end) \
return false; \
\
SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \
\
*key = scan->key; \
*value = scan->value; \
*index = iter->index; \
\
if (iter->cursor == iter->last) \
iter->end = true; \
else \
{ \
iter->index++; \
while (1) \
{ \
iter->cursor++; \
scan = &(iter->target->buffer[iter->cursor]); \
iter->end = true; \
\
if (scan->state == ES_FILLED) \
break; \
} \
return false; \
} \
\
iter->index++; \
\
while (1) \
{ \
iter->cursor++; \
scan = &(iter->target->buffer[iter->cursor]); \
\
if (scan->state == ES_FILLED) \
break; \
} \
\
iter->start = PFX##_empty(iter->target); \
@@ -503,35 +554,151 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
return true; \
} \
\
FMOD bool PFX##_iter_prev(SNAME##_iter *iter, K *key, V *value, size_t *index) \
FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \
{ \
if (iter->start) \
return false; \
\
SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \
\
*key = scan->key; \
*value = scan->value; \
*index = iter->index; \
\
if (iter->cursor == iter->first) \
iter->start = true; \
else \
{ \
iter->index--; \
while (1) \
{ \
iter->cursor--; \
scan = &(iter->target->buffer[iter->cursor]); \
iter->start = true; \
\
if (scan->state == ES_FILLED) \
break; \
} \
return false; \
} \
\
iter->index--; \
\
while (1) \
{ \
iter->cursor--; \
scan = &(iter->target->buffer[iter->cursor]); \
\
if (scan->state == ES_FILLED) \
break; \
} \
\
iter->end = PFX##_empty(iter->target); \
\
return true; \
} \
\
FMOD K PFX##_iter_key(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return 0; \
\
return iter->target->buffer[iter->cursor].key; \
} \
\
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return 0; \
\
return iter->target->buffer[iter->cursor].value; \
} \
\
FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return NULL; \
\
return &(iter->target->buffer[iter->cursor].value); \
} \
\
FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \
{ \
return iter->index; \
} \
\
FMOD bool PFX##_impl_grow(SNAME *_map_) \
{ \
size_t new_size = PFX##_impl_calculate_size(_map_->capacity + _map_->capacity / 2); \
\
SNAME *_new_map_ = PFX##_new(new_size, _map_->load, _map_->cmp, _map_->hash); \
\
if (!_new_map_) \
return false; \
\
SNAME##_iter iter; \
\
for (PFX##_iter_init(&iter, _map_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
{ \
K key = PFX##_iter_key(&iter); \
V value = PFX##_iter_value(&iter); \
\
PFX##_insert(_new_map_, key, value); \
} \
\
if (_map_->count != _new_map_->count) \
{ \
PFX##_free(_new_map_); \
return false; \
} \
\
SNAME##_entry *tmp = _map_->buffer; \
_map_->buffer = _new_map_->buffer; \
_new_map_->buffer = tmp; \
\
_map_->capacity = _new_map_->capacity; \
\
PFX##_free(_new_map_); \
\
return true; \
} \
\
FMOD SNAME##_entry *PFX##_impl_get_entry(SNAME *_map_, K key) \
{ \
size_t hash = _map_->hash(key); \
size_t pos = hash % _map_->capacity; \
\
SNAME##_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; \
} \
\
FMOD size_t PFX##_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]; \
} \
\
SNAME##_iter PFX##_impl_it_start(SNAME *_map_) \
{ \
SNAME##_iter iter; \
\
PFX##_iter_init(&iter, _map_); \
\
return iter; \
} \
\
SNAME##_iter PFX##_impl_it_end(SNAME *_map_) \
{ \
SNAME##_iter iter; \
\
PFX##_iter_init(&iter, _map_); \
PFX##_iter_to_end(&iter); \
\
return iter; \
}
#endif /* CMC_HASHMAP_H */
+310 -182
View File
@@ -29,13 +29,37 @@ typedef enum EntryState_e
ES_FILLED = 1
} EntryState;
static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
6151, 12289, 24593, 49157, 98317,
196613, 393241, 786433, 1572869,
3145739, 6291469, 12582917,
25165843, 50331653, 100663319,
201326611, 402653189, 805306457,
1610612741};
static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
3067, 6143, 12289, 24571, 49157,
98299, 196613, 393209, 786431,
1572869, 3145721, 6291449,
12582917, 25165813, 50331653,
100663291, 201326611, 402653189,
805306357, 1610612741,
3221225473, 6442450939,
12884901893, 25769803799,
51539607551, 103079215111,
206158430209, 412316860441,
824633720831, 1649267441651,
3298534883309, 6597069766657,
13194139533299, 26388279066623,
52776558133303, 105553116266489,
211106232532969, 422212465066001,
844424930131963,
1688849860263953,
3377699720527861,
6755399441055731,
13510798882111483,
27021597764222939,
54043195528445957,
108086391056891903,
216172782113783773,
432345564227567621,
864691128455135207,
1729382256910270481,
3458764513820540933,
6917529027641081903,
13835058055282163729llu};
#endif /* CMC_HASH_TABLE_SETUP */
@@ -57,74 +81,132 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
#define HASHSET_GENERATE_SOURCE_PUBLIC(PFX, SNAME, FMOD, K, V) \
HASHSET_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* STRUCT ********************************************************************/
#define HASHSET_GENERATE_STRUCT(PFX, SNAME, FMOD, V) \
\
struct SNAME##_s \
{ \
struct SNAME##_entry_s *buffer; \
size_t capacity; \
size_t count; \
double load; \
int (*cmp)(V, V); \
size_t (*hash)(V); \
}; \
\
struct SNAME##_entry_s \
{ \
V value; \
size_t dist; \
enum EntryState_e state; \
}; \
\
struct SNAME##_iter_s \
{ \
struct SNAME##_s *target; \
size_t cursor; \
size_t index; \
size_t first; \
size_t last; \
bool start; \
bool end; \
}; \
\
#define HASHSET_GENERATE_STRUCT(PFX, SNAME, FMOD, V)
/* HEADER ********************************************************************/
#define HASHSET_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
\
typedef struct SNAME##_s SNAME; \
typedef struct SNAME##_entry_s SNAME##_entry; \
typedef struct SNAME##_iter_s SNAME##_iter; \
/* Hashset Structure */ \
typedef struct SNAME##_s \
{ \
/* Array of Entries */ \
struct SNAME##_entry_s *buffer; \
\
/* Current Array Capcity */ \
size_t capacity; \
\
/* Current amount of elements */ \
size_t count; \
\
/* Load factor in range (0.0, 1.0) */ \
double load; \
\
/* Element comparison function */ \
int (*cmp)(V, V); \
\
/* Element hash function */ \
size_t (*hash)(V); \
\
/* Function that returns an iterator to the start of the hashset */ \
struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
\
/* Function that returns an iterator to the end of the hashset */ \
struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
\
} SNAME, *SNAME##_ptr; \
\
typedef struct SNAME##_entry_s \
{ \
/* Entry element */ \
V value; \
\
/* The distance of this node to its original position, used by robin-hood hashing */ \
size_t dist; \
\
/* The sate of this node (DELETED, EMPTY, FILLED) */ \
enum EntryState_e state; \
\
} SNAME##_entry, *SNAME##_entry_ptr; \
\
/* Hashset Iterator */ \
typedef struct SNAME##_iter_s \
{ \
/* Target Hashset */ \
struct SNAME##_s *target; \
\
/* Cursor's position (index) */ \
size_t cursor; \
\
/* Keeps track of relative index to the iteration of elements */ \
size_t index; \
\
/* The index of the first element */ \
size_t first; \
\
/* The index of the last element */ \
size_t last; \
\
/* 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, double load, int (*compare)(V, V), size_t (*hash)(V)); \
FMOD void PFX##_clear(SNAME *_set_); \
FMOD void PFX##_free(SNAME *_set_); \
/* Collection Input and Output */ \
FMOD bool PFX##_insert(SNAME *_set_, V element); \
FMOD bool PFX##_remove(SNAME *_set_, V element); \
/* Conditional Input and Output */ \
FMOD bool PFX##_insert_if(SNAME *_set_, V element, bool condition); \
FMOD bool PFX##_remove_if(SNAME *_set_, V element, bool condition); \
FMOD V PFX##_max(SNAME *_set_); \
FMOD V PFX##_min(SNAME *_set_); \
/* Element Access */ \
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_); \
FMOD size_t PFX##_count(SNAME *_set_); \
FMOD size_t PFX##_capacity(SNAME *_set_); \
\
/* Set Operations */ \
FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_); \
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 void PFX##_iter_new(SNAME##_iter *iter, SNAME *target); \
/* 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); \
FMOD void PFX##_iter_tostart(SNAME##_iter *iter); \
FMOD void PFX##_iter_toend(SNAME##_iter *iter); \
FMOD bool PFX##_iter_next(SNAME##_iter *iter, V *value, size_t *index); \
FMOD bool PFX##_iter_prev(SNAME##_iter *iter, V *value, size_t *index); \
/* 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); \
\
/* SOURCE ********************************************************************/
#define HASHSET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \
\
/* Implementation Detail Functions */ \
FMOD bool PFX##_grow(SNAME *_set_); \
FMOD SNAME##_entry *PFX##_get_entry(SNAME *_set_, V element); \
FMOD size_t PFX##_calculate_size(size_t required); \
SNAME##_iter PFX##_impl_it_start(SNAME *_set_); \
SNAME##_iter PFX##_impl_it_end(SNAME *_set_); \
\
FMOD SNAME *PFX##_new(size_t size, double load, int (*compare)(V, V), size_t (*hash)(V)) \
{ \
@@ -154,6 +236,9 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
_set_->cmp = compare; \
_set_->hash = hash; \
\
_set_->it_start = PFX##_impl_it_start; \
_set_->it_end = PFX##_impl_it_end; \
\
return _set_; \
} \
\
@@ -190,7 +275,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
if (target->state == ES_EMPTY || target->state == ES_DELETED) \
{ \
target->value = element; \
target->dist = original_pos - pos; \
target->dist = pos - original_pos; \
target->state = ES_FILLED; \
} \
else \
@@ -205,9 +290,10 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
target->value = element; \
target->dist = pos - original_pos; \
target->state = ES_FILLED; \
\
break; \
} \
else if (target->dist < original_pos - pos) \
else if (target->dist < pos - original_pos) \
{ \
V tmp = target->value; \
size_t tmp_dist = target->dist; \
@@ -258,48 +344,51 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
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##_iter iter; \
V result, max; \
size_t index; \
\
for (PFX##_iter_new(&iter, _set_); !PFX##_iter_end(&iter);) \
for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
{ \
PFX##_iter_next(&iter, &result, &index); \
V result = PFX##_iter_value(&iter); \
size_t index = PFX##_iter_index(&iter); \
\
if (index == 0) \
max = result; \
else if (_set_->cmp(result, max) > 0) \
max = result; \
*value = result; \
else if (_set_->cmp(result, *value) > 0) \
*value = result; \
} \
\
return max; \
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##_iter iter; \
V result, min; \
size_t index; \
\
for (PFX##_iter_new(&iter, _set_); !PFX##_iter_end(&iter);) \
for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
{ \
PFX##_iter_next(&iter, &result, &index); \
V result = PFX##_iter_value(&iter); \
size_t index = PFX##_iter_index(&iter); \
\
if (index == 0) \
min = result; \
else if (_set_->cmp(result, min) < 0) \
min = result; \
*value = result; \
else if (_set_->cmp(result, *value) < 0) \
*value = result; \
} \
\
return min; \
return true; \
} \
\
FMOD bool PFX##_contains(SNAME *_set_, V element) \
{ \
return PFX##_get_entry(_set_, element) != NULL; \
} \
\
FMOD bool PFX##_empty(SNAME *_set_) \
@@ -312,99 +401,30 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
return _set_->count; \
} \
\
FMOD bool PFX##_grow(SNAME *_set_) \
FMOD size_t PFX##_capacity(SNAME *_set_) \
{ \
size_t new_size = PFX##_calculate_size((size_t)((double)_set_->capacity * 1.5)); \
\
SNAME *_new_set_ = PFX##_new(new_size, _set_->load, _set_->cmp, _set_->hash); \
\
if (!_new_set_) \
return false; \
\
SNAME##_iter iter; \
V value; \
size_t index; \
\
for (PFX##_iter_new(&iter, _set_); !PFX##_iter_end(&iter);) \
{ \
PFX##_iter_next(&iter, &value, &index); \
PFX##_insert(_new_set_, value); \
} \
\
if (_set_->count != _new_set_->count) \
{ \
PFX##_free(_new_set_); \
return false; \
} \
\
SNAME##_entry *tmp = _set_->buffer; \
_set_->buffer = _new_set_->buffer; \
_new_set_->buffer = tmp; \
\
_set_->capacity = _new_set_->capacity; \
\
PFX##_free(_new_set_); \
\
return true; \
} \
\
FMOD SNAME##_entry *PFX##_get_entry(SNAME *_set_, V element) \
{ \
size_t hash = _set_->hash(element); \
size_t pos = hash % _set_->capacity; \
\
SNAME##_entry *target = &(_set_->buffer[pos % _set_->capacity]); \
\
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; \
} \
\
FMOD size_t PFX##_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]; \
return _set_->capacity; \
} \
\
FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_) \
{ \
SNAME##_iter iter1, iter2; \
size_t index; \
V value; \
\
SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \
\
if (!_set_r_) \
return false; \
\
PFX##_iter_new(&iter1, _set1_); \
PFX##_iter_new(&iter2, _set2_); \
SNAME##_iter iter1, iter2; \
PFX##_iter_init(&iter1, _set1_); \
PFX##_iter_init(&iter2, _set2_); \
\
for (PFX##_iter_tostart(&iter1); !PFX##_iter_end(&iter1);) \
for (PFX##_iter_to_start(&iter1); !PFX##_iter_end(&iter1); PFX##_iter_next(&iter1)) \
{ \
PFX##_iter_next(&iter1, &value, &index); \
PFX##_insert(_set_r_, value); \
PFX##_insert(_set_r_, PFX##_iter_value(&iter1)); \
} \
\
for (PFX##_iter_tostart(&iter2); !PFX##_iter_end(&iter2);) \
for (PFX##_iter_to_start(&iter2); !PFX##_iter_end(&iter2); PFX##_iter_next(&iter2)) \
{ \
PFX##_iter_next(&iter2, &value, &index); \
PFX##_insert(_set_r_, value); \
PFX##_insert(_set_r_, PFX##_iter_value(&iter2)); \
} \
\
return _set_r_; \
@@ -412,10 +432,6 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
\
FMOD SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_) \
{ \
SNAME##_iter iter; \
size_t index; \
V value; \
\
SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \
\
if (!_set_r_) \
@@ -424,11 +440,13 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
SNAME *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; \
SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \
\
PFX##_iter_new(&iter, _set_A_); \
SNAME##_iter iter; \
PFX##_iter_init(&iter, _set_A_); \
\
for (PFX##_iter_tostart(&iter); !PFX##_iter_end(&iter);) \
for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
{ \
PFX##_iter_next(&iter, &value, &index); \
V value = PFX##_iter_value(&iter); \
\
if (PFX##_get_entry(_set_B_, value) != NULL) \
PFX##_insert(_set_r_, value); \
} \
@@ -438,20 +456,18 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
\
FMOD SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_) \
{ \
SNAME##_iter iter; \
size_t index; \
V value; \
\
SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \
\
if (!_set_r_) \
return false; \
\
PFX##_iter_new(&iter, _set1_); \
SNAME##_iter iter; \
PFX##_iter_init(&iter, _set1_); \
\
for (PFX##_iter_tostart(&iter); !PFX##_iter_end(&iter);) \
for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
{ \
PFX##_iter_next(&iter, &value, &index); \
V value = PFX##_iter_value(&iter); \
\
if (PFX##_get_entry(_set2_, value) == NULL) \
PFX##_insert(_set_r_, value); \
} \
@@ -462,27 +478,27 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_) \
{ \
SNAME##_iter iter1, iter2; \
size_t index; \
V value; \
\
SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \
\
if (!_set_r_) \
return false; \
\
PFX##_iter_new(&iter1, _set1_); \
PFX##_iter_new(&iter2, _set2_); \
PFX##_iter_init(&iter1, _set1_); \
PFX##_iter_init(&iter2, _set2_); \
\
for (PFX##_iter_tostart(&iter1); !PFX##_iter_end(&iter1);) \
for (PFX##_iter_to_start(&iter1); !PFX##_iter_end(&iter1); PFX##_iter_next(&iter1)) \
{ \
PFX##_iter_next(&iter1, &value, &index); \
V value = PFX##_iter_value(&iter1); \
\
if (PFX##_get_entry(_set2_, value) == NULL) \
PFX##_insert(_set_r_, value); \
} \
\
for (PFX##_iter_tostart(&iter2); !PFX##_iter_end(&iter2);) \
for (PFX##_iter_to_start(&iter2); !PFX##_iter_end(&iter2); PFX##_iter_next(&iter2)) \
{ \
PFX##_iter_next(&iter2, &value, &index); \
V value = PFX##_iter_value(&iter2); \
\
if (PFX##_get_entry(_set1_, value) == NULL) \
PFX##_insert(_set_r_, value); \
} \
@@ -490,7 +506,24 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
return _set_r_; \
} \
\
FMOD void PFX##_iter_new(SNAME##_iter *iter, SNAME *target) \
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 = 0; \
@@ -524,15 +557,15 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
\
FMOD bool PFX##_iter_start(SNAME##_iter *iter) \
{ \
return iter->start && iter->cursor == iter->first; \
return PFX##_empty(iter->target) || iter->start; \
} \
\
FMOD bool PFX##_iter_end(SNAME##_iter *iter) \
{ \
return iter->end && iter->cursor == iter->last; \
return PFX##_empty(iter->target) || iter->end; \
} \
\
FMOD void PFX##_iter_tostart(SNAME##_iter *iter) \
FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \
{ \
iter->cursor = iter->first; \
iter->index = 0; \
@@ -540,7 +573,7 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
iter->end = PFX##_empty(iter->target); \
} \
\
FMOD void PFX##_iter_toend(SNAME##_iter *iter) \
FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \
{ \
iter->cursor = iter->last; \
iter->index = iter->target->count - 1; \
@@ -548,21 +581,19 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
iter->end = true; \
} \
\
FMOD bool PFX##_iter_next(SNAME##_iter *iter, V *value, size_t *index) \
FMOD bool PFX##_iter_next(SNAME##_iter *iter) \
{ \
if (iter->end) \
return false; \
\
SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \
\
*value = scan->value; \
*index = iter->index; \
\
if (iter->cursor == iter->last) \
iter->end = true; \
else \
{ \
iter->index++; \
\
while (1) \
{ \
iter->cursor++; \
@@ -578,21 +609,19 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
return true; \
} \
\
FMOD bool PFX##_iter_prev(SNAME##_iter *iter, V *value, size_t *index) \
FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \
{ \
if (iter->start) \
return false; \
\
SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \
\
*value = scan->value; \
*index = iter->index; \
\
if (iter->cursor == iter->first) \
iter->start = true; \
else \
{ \
iter->index--; \
\
while (1) \
{ \
iter->cursor--; \
@@ -606,6 +635,105 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079,
iter->end = PFX##_empty(iter->target); \
\
return true; \
} \
\
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return 0; \
\
return iter->target->buffer[iter->cursor].value; \
} \
\
FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \
{ \
return iter->index; \
} \
\
FMOD bool PFX##_grow(SNAME *_set_) \
{ \
size_t new_size = PFX##_calculate_size(_set_->capacity + _set_->capacity / 2); \
\
SNAME *_new_set_ = PFX##_new(new_size, _set_->load, _set_->cmp, _set_->hash); \
\
if (!_new_set_) \
return false; \
\
SNAME##_iter iter; \
\
for (PFX##_iter_init(&iter, _set_); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
{ \
PFX##_insert(_new_set_, PFX##_iter_value(&iter)); \
} \
\
if (_set_->count != _new_set_->count) \
{ \
PFX##_free(_new_set_); \
\
return false; \
} \
\
SNAME##_entry *tmp = _set_->buffer; \
_set_->buffer = _new_set_->buffer; \
_new_set_->buffer = tmp; \
\
_set_->capacity = _new_set_->capacity; \
\
PFX##_free(_new_set_); \
\
return true; \
} \
\
FMOD SNAME##_entry *PFX##_get_entry(SNAME *_set_, V element) \
{ \
size_t hash = _set_->hash(element); \
size_t pos = hash % _set_->capacity; \
\
SNAME##_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; \
} \
\
FMOD size_t PFX##_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]; \
} \
\
SNAME##_iter PFX##_impl_it_start(SNAME *_set_) \
{ \
SNAME##_iter iter; \
\
PFX##_iter_init(&iter, _set_); \
\
return iter; \
} \
\
SNAME##_iter PFX##_impl_it_end(SNAME *_set_) \
{ \
SNAME##_iter iter; \
\
PFX##_iter_init(&iter, _set_); \
PFX##_iter_to_end(&iter); \
\
return iter; \
}
#endif /* CMC_HASHSET_H */
+237 -125
View File
@@ -43,61 +43,105 @@ typedef enum HeapOrder
#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) \
\
struct SNAME##_s \
{ \
V *buffer; \
size_t capacity; \
size_t count; \
enum HeapOrder HO; \
int (*cmp)(V, V); \
}; \
\
struct SNAME##_iter_s \
{ \
struct SNAME##_s *target; \
size_t cursor; \
bool start; \
bool end; \
}; \
\
#define HEAP_GENERATE_STRUCT(PFX, SNAME, FMOD, V)
/* HEADER ********************************************************************/
#define HEAP_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
\
typedef struct SNAME##_s SNAME; \
typedef struct SNAME##_iter_s SNAME##_iter; \
\
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_); \
FMOD bool PFX##_insert(SNAME *_heap_, V element); \
FMOD bool PFX##_remove(SNAME *_heap_, V *result); \
FMOD bool PFX##_insert_if(SNAME *_heap_, V element, bool condition); \
FMOD bool PFX##_remove_if(SNAME *_heap_, V *result, bool condition); \
FMOD V PFX##_peek(SNAME *_heap_); \
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_); \
\
FMOD void PFX##_iter_new(SNAME##_iter *iter, SNAME *target); \
FMOD bool PFX##_iter_start(SNAME##_iter *iter); \
FMOD bool PFX##_iter_end(SNAME##_iter *iter); \
FMOD void PFX##_iter_tostart(SNAME##_iter *iter); \
FMOD void PFX##_iter_toend(SNAME##_iter *iter); \
FMOD bool PFX##_iter_next(SNAME##_iter *iter, V *result, size_t *index); \
FMOD bool PFX##_iter_prev(SNAME##_iter *iter, V *result, size_t *index); \
\
#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); \
\
/* SOURCE ********************************************************************/
#define HEAP_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \
\
FMOD bool PFX##_grow(SNAME *_heap_); \
FMOD size_t PFX##_p(size_t index); \
FMOD size_t PFX##_l(size_t index); \
FMOD size_t PFX##_r(size_t index); \
FMOD bool PFX##_float_up(SNAME *_heap_, size_t index); \
FMOD bool PFX##_float_down(SNAME *_heap_, size_t index); \
/* 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_); \
\
FMOD SNAME *PFX##_new(size_t size, HeapOrder HO, int (*compare)(V, V)) \
{ \
@@ -127,6 +171,9 @@ typedef enum HeapOrder
_heap_->HO = HO; \
_heap_->cmp = compare; \
\
_heap_->it_start = PFX##_impl_it_start; \
_heap_->it_end = PFX##_impl_it_end; \
\
return _heap_; \
} \
\
@@ -147,7 +194,7 @@ typedef enum HeapOrder
{ \
if (PFX##_full(_heap_)) \
{ \
if (!PFX##_grow(_heap_)) \
if (!PFX##_impl_grow(_heap_)) \
return false; \
} \
\
@@ -159,7 +206,7 @@ typedef enum HeapOrder
\
_heap_->buffer[_heap_->count++] = element; \
\
if (!PFX##_float_up(_heap_, _heap_->count - 1)) \
if (!PFX##_impl_float_up(_heap_, _heap_->count - 1)) \
return false; \
\
return true; \
@@ -176,7 +223,7 @@ typedef enum HeapOrder
\
_heap_->count--; \
\
if (!PFX##_float_down(_heap_, 0)) \
if (!PFX##_impl_float_down(_heap_, 0)) \
return false; \
\
return true; \
@@ -206,6 +253,25 @@ typedef enum HeapOrder
return _heap_->buffer[0]; \
} \
\
FMOD V *PFX##_peek_ref(SNAME *_heap_) \
{ \
if (PFX##_empty(_heap_)) \
return NULL; \
\
return &(_heap_->buffer[0]); \
} \
\
FMOD bool PFX##_contains(SNAME *_heap_, V element) \
{ \
for (size_t i = 0; i < _heap_->count; i++) \
{ \
if (_heap_->cmp(_heap_->buffer[i], element) == 0) \
return true; \
} \
\
return false; \
} \
\
FMOD bool PFX##_empty(SNAME *_heap_) \
{ \
return _heap_->count == 0; \
@@ -226,7 +292,99 @@ typedef enum HeapOrder
return _heap_->capacity; \
} \
\
FMOD bool PFX##_grow(SNAME *_heap_) \
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 = 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 = 0; \
iter->start = true; \
iter->end = PFX##_empty(iter->target); \
} \
\
FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \
{ \
iter->cursor = 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 = false; \
\
if (iter->cursor == iter->target->count - 1) \
iter->end = true; \
else \
iter->cursor++; \
\
return true; \
} \
\
FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \
{ \
if (iter->start) \
return false; \
\
iter->end = false; \
\
if (iter->cursor == 0) \
iter->start = true; \
else \
iter->cursor--; \
\
return true; \
} \
\
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return 0; \
\
return iter->target->buffer[iter->cursor]; \
} \
\
FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \
{ \
return iter->cursor; \
} \
\
FMOD bool PFX##_impl_grow(SNAME *_heap_) \
{ \
size_t new_capacity = _heap_->capacity * 2; \
\
@@ -241,7 +399,7 @@ typedef enum HeapOrder
return true; \
} \
\
FMOD size_t PFX##_p(size_t index) \
FMOD size_t PFX##_impl_p(size_t index) \
{ \
if (index == 0) \
return 0; \
@@ -249,47 +407,47 @@ typedef enum HeapOrder
return (index - 1) / 2; \
} \
\
FMOD size_t PFX##_l(size_t index) \
FMOD size_t PFX##_impl_l(size_t index) \
{ \
return 2 * index + 1; \
} \
\
FMOD size_t PFX##_r(size_t index) \
FMOD size_t PFX##_impl_r(size_t index) \
{ \
return 2 * index + 2; \
} \
\
FMOD bool PFX##_float_up(SNAME *_heap_, size_t index) \
FMOD bool PFX##_impl_float_up(SNAME *_heap_, size_t index) \
{ \
size_t C = index; \
V child = _heap_->buffer[C]; \
V parent = _heap_->buffer[PFX##_p(C)]; \
V parent = _heap_->buffer[PFX##_impl_p(C)]; \
\
int mod = _heap_->HO; \
\
while (C > 0 && _heap_->cmp(child, parent) * mod > 0) \
{ \
V tmp = _heap_->buffer[C]; \
_heap_->buffer[C] = _heap_->buffer[PFX##_p(C)]; \
_heap_->buffer[PFX##_p(C)] = tmp; \
_heap_->buffer[C] = _heap_->buffer[PFX##_impl_p(C)]; \
_heap_->buffer[PFX##_impl_p(C)] = tmp; \
\
C = PFX##_p(C); \
C = PFX##_impl_p(C); \
\
child = _heap_->buffer[C]; \
parent = _heap_->buffer[PFX##_p(C)]; \
parent = _heap_->buffer[PFX##_impl_p(C)]; \
} \
\
return true; \
} \
\
FMOD bool PFX##_float_down(SNAME *_heap_, size_t index) \
FMOD bool PFX##_impl_float_down(SNAME *_heap_, size_t index) \
{ \
int mod = _heap_->HO; \
\
while (index < _heap_->count) \
{ \
size_t L = PFX##_l(index); \
size_t R = PFX##_r(index); \
size_t L = PFX##_impl_l(index); \
size_t R = PFX##_impl_r(index); \
size_t C = index; \
\
if (L < _heap_->count && _heap_->cmp(_heap_->buffer[L], _heap_->buffer[C]) * mod > 0) \
@@ -317,70 +475,24 @@ typedef enum HeapOrder
return true; \
} \
\
FMOD void PFX##_iter_new(SNAME##_iter *iter, SNAME *target) \
SNAME##_iter PFX##_impl_it_start(SNAME *_heap_) \
{ \
iter->target = target; \
iter->cursor = 0; \
iter->start = true; \
iter->end = PFX##_empty(target); \
SNAME##_iter iter; \
\
PFX##_iter_init(&iter, _heap_); \
PFX##_iter_to_start(&iter); \
\
return iter; \
} \
\
FMOD bool PFX##_iter_start(SNAME##_iter *iter) \
SNAME##_iter PFX##_impl_it_end(SNAME *_heap_) \
{ \
return iter->cursor == 0 && iter->start; \
} \
SNAME##_iter iter; \
\
FMOD bool PFX##_iter_end(SNAME##_iter *iter) \
{ \
return iter->cursor == iter->target->count - 1 && iter->end; \
} \
PFX##_iter_init(&iter, _heap_); \
PFX##_iter_to_end(&iter); \
\
FMOD void PFX##_iter_tostart(SNAME##_iter *iter) \
{ \
iter->cursor = 0; \
iter->start = true; \
iter->end = PFX##_empty(iter->target); \
} \
\
FMOD void PFX##_iter_toend(SNAME##_iter *iter) \
{ \
iter->cursor = iter->target->count - 1; \
iter->start = PFX##_empty(iter->target); \
iter->end = true; \
} \
\
FMOD bool PFX##_iter_next(SNAME##_iter *iter, V *result, size_t *index) \
{ \
if (iter->end) \
return false; \
\
*index = iter->cursor; \
*result = iter->target->buffer[iter->cursor]; \
iter->start = false; \
\
if (iter->cursor == iter->target->count - 1) \
iter->end = true; \
else \
iter->cursor++; \
\
return true; \
} \
\
FMOD bool PFX##_iter_prev(SNAME##_iter *iter, V *result, size_t *index) \
{ \
if (iter->start) \
return false; \
\
*index = iter->cursor; \
*result = iter->target->buffer[iter->cursor]; \
iter->end = false; \
\
if (iter->cursor == 0) \
iter->start = true; \
else \
iter->cursor--; \
\
return true; \
return iter; \
}
#endif /* CMC_HEAP_H */
+315 -158
View File
@@ -36,79 +36,135 @@
#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) \
\
struct SNAME##_s \
{ \
struct SNAME##_node_s *head; \
struct SNAME##_node_s *tail; \
size_t count; \
}; \
\
struct SNAME##_node_s \
{ \
V data; \
struct SNAME##_s *owner; \
struct SNAME##_node_s *next; \
struct SNAME##_node_s *prev; \
}; \
\
struct SNAME##_iter_s \
{ \
struct SNAME##_s *target; \
struct SNAME##_node_s *cursor; \
size_t index; \
bool start; \
bool end; \
}; \
\
#define LINKEDLIST_GENERATE_STRUCT(PFX, SNAME, FMOD, V)
/* HEADER ********************************************************************/
#define LINKEDLIST_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
\
typedef struct SNAME##_s SNAME; \
typedef struct SNAME##_node_s SNAME##_node; \
typedef struct SNAME##_iter_s SNAME##_iter; \
/* Linked List 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 *); \
\
/* Function that returns an iterator to the end of the list */ \
struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
\
} SNAME, *SNAME_ptr; \
\
/* Doubly-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; \
\
/* Pointer to the previous node on the linked list */ \
struct SNAME##_node_s *prev; \
\
} SNAME##_node, *SNAME##_node_ptr; \
\
/* Linked List Iterator */ \
typedef struct SNAME##_iter_s \
{ \
/* Target Linked List */ \
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 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 *_list_); \
FMOD void PFX##_free(SNAME *_list_); \
/* Collection Input and Output */ \
FMOD bool PFX##_push_front(SNAME *_list_, V element); \
FMOD bool PFX##_push(SNAME *_list_, V element, size_t index); \
FMOD bool PFX##_push_back(SNAME *_list_, V element); \
FMOD bool PFX##_pop_front(SNAME *_list_); \
FMOD bool PFX##_pop(SNAME *_list_, size_t index); \
FMOD bool PFX##_pop_back(SNAME *_list_); \
/* Conditional Input and Output */ \
FMOD bool PFX##_push_if(SNAME *_list_, V element, size_t index, bool condition); \
FMOD bool PFX##_pop_if(SNAME *_list_, size_t index, bool condition); \
/* Element Access */ \
FMOD V PFX##_front(SNAME *_list_); \
FMOD V PFX##_get(SNAME *_list_, size_t index); \
FMOD V *PFX##_get_ref(SNAME *_list_, size_t index); \
FMOD V PFX##_back(SNAME *_list_); \
/* Collection State */ \
FMOD bool PFX##_contains(SNAME *_list_, V element, int (*comparator)(V, V)); \
FMOD bool PFX##_empty(SNAME *_list_); \
FMOD size_t PFX##_count(SNAME *_list_); \
\
FMOD SNAME##_node *PFX##_new_node(SNAME *_owner_, V element); \
FMOD SNAME##_node *PFX##_front_node(SNAME *_list_); \
/* Node Related Functions */ \
/* Node Allocation and Deallocation */ \
FMOD SNAME##_node *PFX##_new_node(V element); \
FMOD void PFX##_free_node(SNAME##_node *_node_); \
/* Node Access Relative to a Linked List */ \
FMOD SNAME##_node *PFX##_head(SNAME *_list_); \
FMOD SNAME##_node *PFX##_get_node(SNAME *_list_, size_t index); \
FMOD SNAME##_node *PFX##_back_node(SNAME *_list_); \
FMOD bool PFX##_insert_nxt(SNAME##_node *node, V element); \
FMOD bool PFX##_insert_prv(SNAME##_node *node, V element); \
FMOD bool PFX##_remove_nxt(SNAME##_node *node); \
FMOD bool PFX##_remove_cur(SNAME##_node *node); \
FMOD bool PFX##_remove_prv(SNAME##_node *node); \
FMOD SNAME##_node *PFX##_next_node(SNAME##_node *node); \
FMOD SNAME##_node *PFX##_prev_node(SNAME##_node *node); \
FMOD SNAME##_node *PFX##_tail(SNAME *_list_); \
/* Input and Output Relative to a Node */ \
FMOD bool PFX##_insert_after(SNAME *_owner_, SNAME##_node *_node_, V element); \
FMOD bool PFX##_insert_before(SNAME *_owner_, SNAME##_node *_node_, V element); \
FMOD bool PFX##_remove_after(SNAME *_owner_, SNAME##_node *_node_); \
FMOD bool PFX##_remove_current(SNAME *_owner_, SNAME##_node *_node_); \
FMOD bool PFX##_remove_before(SNAME *_owner_, SNAME##_node *_node_); \
/* Node Access Relative to a Linked List Node */ \
FMOD SNAME##_node *PFX##_next_node(SNAME##_node *_node_); \
FMOD SNAME##_node *PFX##_prev_node(SNAME##_node *_node_); \
\
FMOD void PFX##_iter_new(SNAME##_iter *iter, SNAME *target); \
/* 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); \
FMOD void PFX##_iter_tostart(SNAME##_iter *iter); \
FMOD void PFX##_iter_toend(SNAME##_iter *iter); \
FMOD bool PFX##_iter_next(SNAME##_iter *iter, V *result, size_t *index); \
FMOD bool PFX##_iter_prev(SNAME##_iter *iter, V *result, size_t *index); \
/* 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); \
FMOD SNAME##_node *PFX##_iter_node(SNAME##_iter *iter); \
\
/* 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_); \
\
FMOD SNAME *PFX##_new(void) \
{ \
SNAME *_list_ = malloc(sizeof(SNAME)); \
@@ -120,6 +176,9 @@
_list_->head = NULL; \
_list_->tail = NULL; \
\
_list_->it_start = PFX##_impl_it_start; \
_list_->it_end = PFX##_impl_it_end; \
\
return _list_; \
} \
\
@@ -148,21 +207,21 @@
\
FMOD bool PFX##_push_front(SNAME *_list_, V element) \
{ \
SNAME##_node *node = PFX##_new_node(_list_, element); \
SNAME##_node *_node_ = PFX##_new_node(element); \
\
if (!node) \
if (!_node_) \
return false; \
\
if (PFX##_empty(_list_)) \
{ \
_list_->head = node; \
_list_->tail = node; \
_list_->head = _node_; \
_list_->tail = _node_; \
} \
else \
{ \
node->next = _list_->head; \
_list_->head->prev = node; \
_list_->head = node; \
_node_->next = _list_->head; \
_list_->head->prev = _node_; \
_list_->head = _node_; \
} \
\
_list_->count++; \
@@ -184,17 +243,17 @@
return PFX##_push_back(_list_, element); \
} \
\
SNAME##_node *node = PFX##_new_node(_list_, element); \
SNAME##_node *_node_ = PFX##_new_node(element); \
\
if (!node) \
if (!_node_) \
return false; \
\
SNAME##_node *scan = PFX##_get_node(_list_, index - 1); \
\
node->next = scan->next; \
node->prev = scan; \
node->next->prev = node; \
node->prev->next = node; \
_node_->next = scan->next; \
_node_->prev = scan; \
_node_->next->prev = _node_; \
_node_->prev->next = _node_; \
\
_list_->count++; \
\
@@ -203,21 +262,21 @@
\
FMOD bool PFX##_push_back(SNAME *_list_, V element) \
{ \
SNAME##_node *node = PFX##_new_node(_list_, element); \
SNAME##_node *_node_ = PFX##_new_node(element); \
\
if (!node) \
if (!_node_) \
return false; \
\
if (PFX##_empty(_list_)) \
{ \
_list_->head = node; \
_list_->tail = node; \
_list_->head = _node_; \
_list_->tail = _node_; \
} \
else \
{ \
node->prev = _list_->tail; \
_list_->tail->next = node; \
_list_->tail = node; \
_node_->prev = _list_->tail; \
_list_->tail->next = _node_; \
_list_->tail = _node_; \
} \
\
_list_->count++; \
@@ -230,10 +289,10 @@
if (PFX##_empty(_list_)) \
return false; \
\
SNAME##_node *node = _list_->head; \
SNAME##_node *_node_ = _list_->head; \
_list_->head = _list_->head->next; \
\
free(node); \
free(_node_); \
\
if (_list_->head == NULL) \
_list_->tail = NULL; \
@@ -262,15 +321,15 @@
return PFX##_pop_back(_list_); \
} \
\
SNAME##_node *node = PFX##_get_node(_list_, index); \
SNAME##_node *_node_ = PFX##_get_node(_list_, index); \
\
if (!node) \
if (!_node_) \
return false; \
\
node->next->prev = node->prev; \
node->prev->next = node->next; \
_node_->next->prev = _node_->prev; \
_node_->prev->next = _node_->next; \
\
free(node); \
free(_node_); \
\
_list_->count--; \
\
@@ -282,10 +341,10 @@
if (PFX##_empty(_list_)) \
return false; \
\
SNAME##_node *node = _list_->tail; \
SNAME##_node *_node_ = _list_->tail; \
_list_->tail = _list_->tail->prev; \
\
free(node); \
free(_node_); \
\
if (_list_->tail == NULL) \
_list_->head = NULL; \
@@ -337,6 +396,22 @@
return scan->data; \
} \
\
FMOD V *PFX##_get_ref(SNAME *_list_, size_t index) \
{ \
if (index >= _list_->count) \
return NULL; \
\
if (PFX##_empty(_list_)) \
return NULL; \
\
SNAME##_node *scan = PFX##_get_node(_list_, index); \
\
if (scan == NULL) \
return NULL; \
\
return &(scan->data); \
} \
\
FMOD V PFX##_back(SNAME *_list_) \
{ \
if (PFX##_empty(_list_)) \
@@ -345,6 +420,21 @@
return _list_->tail->data; \
} \
\
FMOD bool PFX##_contains(SNAME *_list_, V element, int (*comparator)(V, V)) \
{ \
SNAME##_node *scan = _list_->head; \
\
while (scan != NULL) \
{ \
if (comparator(scan->data, element) == 0) \
return true; \
\
scan = scan->next; \
} \
\
return false; \
} \
\
FMOD bool PFX##_empty(SNAME *_list_) \
{ \
return _list_->count == 0; \
@@ -355,22 +445,26 @@
return _list_->count; \
} \
\
FMOD SNAME##_node *PFX##_new_node(SNAME *_owner_, V element) \
FMOD SNAME##_node *PFX##_new_node(V element) \
{ \
SNAME##_node *node = malloc(sizeof(SNAME##_node)); \
SNAME##_node *_node_ = malloc(sizeof(SNAME##_node)); \
\
if (!node) \
if (!_node_) \
return NULL; \
\
node->owner = _owner_; \
node->data = element; \
node->next = NULL; \
node->prev = NULL; \
_node_->data = element; \
_node_->next = NULL; \
_node_->prev = NULL; \
\
return node; \
return _node_; \
} \
\
FMOD SNAME##_node *PFX##_front_node(SNAME *_list_) \
FMOD void PFX##_free_node(SNAME##_node *_node_) \
{ \
free(_node_); \
} \
\
FMOD SNAME##_node *PFX##_head(SNAME *_list_) \
{ \
return _list_->head; \
} \
@@ -383,147 +477,168 @@
if (PFX##_empty(_list_)) \
return NULL; \
\
SNAME##_node *scan = NULL; \
SNAME##_node *_node_ = NULL; \
\
if (index <= _list_->count / 2) \
{ \
scan = _list_->head; \
_node_ = _list_->head; \
for (size_t i = 0; i < index; i++) \
{ \
scan = scan->next; \
_node_ = _node_->next; \
} \
} \
else \
{ \
scan = _list_->tail; \
_node_ = _list_->tail; \
for (size_t i = _list_->count - 1; i > index; i--) \
{ \
scan = scan->prev; \
_node_ = _node_->prev; \
} \
} \
\
return scan; \
return _node_; \
} \
\
FMOD SNAME##_node *PFX##_back_node(SNAME *_list_) \
FMOD SNAME##_node *PFX##_tail(SNAME *_list_) \
{ \
return _list_->tail; \
} \
\
FMOD bool PFX##_insert_nxt(SNAME##_node *node, V element) \
FMOD bool PFX##_insert_after(SNAME *_owner_, SNAME##_node *_node_, V element) \
{ \
SNAME##_node *new_node = PFX##_new_node(node->owner, element); \
SNAME##_node *new_node = PFX##_new_node(element); \
\
if (!new_node) \
return false; \
\
new_node->next = node->next; \
if (node->next != NULL) \
node->next->prev = new_node; \
new_node->next = _node_->next; \
\
if (_node_->next != NULL) \
_node_->next->prev = new_node; \
else \
node->owner->tail = new_node; \
_owner_->tail = new_node; \
\
new_node->prev = node; \
node->next = new_node; \
new_node->prev = _node_; \
_node_->next = new_node; \
\
node->owner->count++; \
_owner_->count++; \
\
return true; \
} \
\
FMOD bool PFX##_insert_prv(SNAME##_node *node, V element) \
FMOD bool PFX##_insert_before(SNAME *_owner_, SNAME##_node *_node_, V element) \
{ \
SNAME##_node *new_node = PFX##_new_node(node->owner, element); \
SNAME##_node *new_node = PFX##_new_node(element); \
\
if (!new_node) \
return false; \
\
new_node->prev = node->prev; \
if (node->prev != NULL) \
node->prev->next = new_node; \
new_node->prev = _node_->prev; \
\
if (_node_->prev != NULL) \
_node_->prev->next = new_node; \
else \
node->owner->head = new_node; \
_owner_->head = new_node; \
\
new_node->next = node; \
node->prev = new_node; \
new_node->next = _node_; \
_node_->prev = new_node; \
\
node->owner->count++; \
_owner_->count++; \
\
return true; \
} \
\
FMOD bool PFX##_remove_nxt(SNAME##_node *node) \
FMOD bool PFX##_remove_after(SNAME *_owner_, SNAME##_node *_node_) \
{ \
if (node->next == NULL) \
if (_node_->next == NULL) \
return false; \
\
SNAME##_node *tmp = node->next; \
SNAME##_node *tmp = _node_->next; \
\
if (node->next != NULL) \
if (tmp->next != NULL) \
{ \
node->next = node->next->next; \
node->next->prev = node; \
_node_->next = _node_->next->next; \
_node_->next->prev = _node_; \
} \
else \
node->owner->tail = node; \
\
node->owner->count--; \
_owner_->tail = _node_; \
\
free(tmp); \
\
return true; \
} \
\
FMOD bool PFX##_remove_cur(SNAME##_node *node) \
{ \
if (node->prev != NULL) \
node->prev->next = node->next; \
else \
node->owner->head = node->next; \
\
if (node->next != NULL) \
node->next->prev = node->prev; \
else \
node->owner->tail = node->prev; \
\
node->owner->count--; \
\
free(node); \
_owner_->count--; \
\
return true; \
} \
\
FMOD bool PFX##_remove_prv(SNAME##_node *node) \
FMOD bool PFX##_remove_current(SNAME *_owner_, SNAME##_node *_node_) \
{ \
if (node->prev == NULL) \
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; \
} \
\
FMOD bool PFX##_remove_before(SNAME *_owner_, SNAME##_node *_node_) \
{ \
if (_node_->prev == NULL) \
return false; \
\
SNAME##_node *tmp = node->prev; \
SNAME##_node *tmp = _node_->prev; \
\
if (node->prev != NULL) \
if (tmp->prev != NULL) \
{ \
node->prev = node->prev->prev; \
node->prev->next = node; \
_node_->prev = _node_->prev->prev; \
_node_->prev->next = _node_; \
} \
else \
node->owner->head = node; \
_owner_->head = _node_; \
\
free(tmp); \
\
_owner_->count--; \
\
return true; \
} \
\
FMOD SNAME##_node *PFX##_next_node(SNAME##_node *node) \
FMOD SNAME##_node *PFX##_next_node(SNAME##_node *_node_) \
{ \
return node->next; \
return _node_->next; \
} \
\
FMOD SNAME##_node *PFX##_prev_node(SNAME##_node *node) \
FMOD SNAME##_node *PFX##_prev_node(SNAME##_node *_node_) \
{ \
return node->prev; \
return _node_->prev; \
} \
\
FMOD void PFX##_iter_new(SNAME##_iter *iter, SNAME *target) \
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; \
@@ -534,15 +649,15 @@
\
FMOD bool PFX##_iter_start(SNAME##_iter *iter) \
{ \
return iter->cursor->prev == NULL && iter->start; \
return PFX##_empty(iter->target) || iter->start; \
} \
\
FMOD bool PFX##_iter_end(SNAME##_iter *iter) \
{ \
return iter->cursor->next == NULL && iter->end; \
return PFX##_empty(iter->target) || iter->end; \
} \
\
FMOD void PFX##_iter_tostart(SNAME##_iter *iter) \
FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \
{ \
iter->cursor = iter->target->head; \
iter->index = 0; \
@@ -550,7 +665,7 @@
iter->end = PFX##_empty(iter->target); \
} \
\
FMOD void PFX##_iter_toend(SNAME##_iter *iter) \
FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \
{ \
iter->cursor = iter->target->tail; \
iter->index = iter->target->count - 1; \
@@ -558,14 +673,12 @@
iter->end = true; \
} \
\
FMOD bool PFX##_iter_next(SNAME##_iter *iter, V *result, size_t *index) \
FMOD bool PFX##_iter_next(SNAME##_iter *iter) \
{ \
if (iter->end) \
return false; \
\
*index = iter->index; \
*result = iter->cursor->data; \
iter->start = false; \
iter->start = PFX##_empty(iter->target); \
\
if (iter->cursor->next == NULL) \
iter->end = true; \
@@ -578,14 +691,12 @@
return true; \
} \
\
FMOD bool PFX##_iter_prev(SNAME##_iter *iter, V *result, size_t *index) \
FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \
{ \
if (iter->start) \
return false; \
\
*index = iter->index; \
*result = iter->cursor->data; \
iter->end = false; \
iter->end = PFX##_empty(iter->target); \
\
if (iter->cursor->prev == NULL) \
iter->start = true; \
@@ -596,6 +707,52 @@
} \
\
return true; \
} \
\
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return 0; \
\
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##_iter_node(SNAME##_iter *iter) \
{ \
return iter->cursor; \
} \
\
SNAME##_iter PFX##_impl_it_start(SNAME *_list_) \
{ \
SNAME##_iter iter; \
\
PFX##_iter_init(&iter, _list_); \
PFX##_iter_to_start(&iter); \
\
return iter; \
} \
\
SNAME##_iter PFX##_impl_it_end(SNAME *_list_) \
{ \
SNAME##_iter iter; \
\
PFX##_iter_init(&iter, _list_); \
PFX##_iter_to_end(&iter); \
\
return iter; \
}
#endif /* CMC_LINKEDLIST_H */
+620 -359
View File
@@ -37,367 +37,628 @@
#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) \
\
struct SNAME##_s \
{ \
V *buffer; \
size_t capacity; \
size_t count; \
}; \
\
struct SNAME##_iter_s \
{ \
struct SNAME##_s *target; \
size_t cursor; \
bool start; \
bool end; \
}; \
\
#define LIST_GENERATE_STRUCT(PFX, SNAME, FMOD, V)
/* HEADER ********************************************************************/
#define LIST_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
\
typedef struct SNAME##_s SNAME; \
typedef struct SNAME##_iter_s SNAME##_iter; \
\
FMOD SNAME *PFX##_new(size_t size); \
FMOD void PFX##_clear(SNAME *_list_); \
FMOD void PFX##_free(SNAME *_list_); \
FMOD bool PFX##_push_front(SNAME *_list_, V element); \
FMOD bool PFX##_push(SNAME *_list_, V element, size_t index); \
FMOD bool PFX##_push_back(SNAME *_list_, V element); \
FMOD bool PFX##_pop_front(SNAME *_list_); \
FMOD bool PFX##_pop(SNAME *_list_, size_t index); \
FMOD bool PFX##_pop_back(SNAME *_list_); \
FMOD bool PFX##_push_if(SNAME *_list_, V element, size_t index, bool condition); \
FMOD bool PFX##_pop_if(SNAME *_list_, size_t index, bool condition); \
FMOD V PFX##_front(SNAME *_list_); \
FMOD V PFX##_get(SNAME *_list_, size_t index); \
FMOD V PFX##_back(SNAME *_list_); \
FMOD bool PFX##_empty(SNAME *_list_); \
FMOD bool PFX##_full(SNAME *_list_); \
FMOD size_t PFX##_count(SNAME *_list_); \
FMOD size_t PFX##_capacity(SNAME *_list_); \
\
FMOD void PFX##_iter_new(SNAME##_iter *iter, SNAME *target); \
FMOD bool PFX##_iter_start(SNAME##_iter *iter); \
FMOD bool PFX##_iter_end(SNAME##_iter *iter); \
FMOD void PFX##_iter_tostart(SNAME##_iter *iter); \
FMOD void PFX##_iter_toend(SNAME##_iter *iter); \
FMOD bool PFX##_iter_next(SNAME##_iter *iter, V *result, size_t *index); \
FMOD bool PFX##_iter_prev(SNAME##_iter *iter, V *result, size_t *index); \
\
#define LIST_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
\
/* List Structure */ \
typedef struct SNAME##_s \
{ \
/* Dynamic array of elements */ \
V *buffer; \
\
/* Current array capacity */ \
size_t capacity; \
\
/* Current amount of elements */ \
size_t count; \
\
/* Function that returns an iterator to the start of the list */ \
struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
\
/* Function that returns an iterator to the end of the list */ \
struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
\
} SNAME, *SNAME##_ptr; \
\
/* List Iterator */ \
typedef struct SNAME##_iter_s \
{ \
/* Target list */ \
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); \
FMOD SNAME *PFX##_new_from(V *elements, size_t size); \
FMOD void PFX##_clear(SNAME *_list_); \
FMOD void PFX##_free(SNAME *_list_); \
/* Collection Input and Output */ \
FMOD bool PFX##_push_front(SNAME *_list_, V element); \
FMOD bool PFX##_push(SNAME *_list_, V element, size_t index); \
FMOD bool PFX##_push_back(SNAME *_list_, V element); \
FMOD bool PFX##_pop_front(SNAME *_list_); \
FMOD bool PFX##_pop(SNAME *_list_, size_t index); \
FMOD bool PFX##_pop_back(SNAME *_list_); \
/* Conditional Input and Output */ \
FMOD bool PFX##_push_if(SNAME *_list_, V element, size_t index, bool condition); \
FMOD bool PFX##_pop_if(SNAME *_list_, size_t index, bool condition); \
/* Collection Range Input and Output */ \
FMOD bool PFX##_prepend(SNAME *_list_, V *elements, size_t size); \
FMOD bool PFX##_insert(SNAME *_list_, V *elements, size_t size, size_t index); \
FMOD bool PFX##_append(SNAME *_list_, V *elements, size_t size); \
FMOD bool PFX##_remove(SNAME *_list_, size_t from, size_t to); \
FMOD SNAME *PFX##_extract(SNAME *_list_, size_t from, size_t to); \
/* Element Access */ \
FMOD V PFX##_front(SNAME *_list_); \
FMOD V PFX##_get(SNAME *_list_, size_t index); \
FMOD V *PFX##_get_ref(SNAME *_list_, size_t index); \
FMOD V PFX##_back(SNAME *_list_); \
FMOD size_t PFX##_indexof(SNAME *_list_, V element, int (*comparator)(V, V), bool from_start); \
/* Collection State */ \
FMOD bool PFX##_contains(SNAME *_list_, V element, int (*comparator)(V, V)); \
FMOD bool PFX##_empty(SNAME *_list_); \
FMOD bool PFX##_full(SNAME *_list_); \
FMOD size_t PFX##_count(SNAME *_list_); \
FMOD bool PFX##_fits(SNAME *_list_, size_t size); \
FMOD size_t PFX##_capacity(SNAME *_list_); \
\
/* 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); \
\
/* SOURCE ********************************************************************/
#define LIST_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \
\
FMOD bool PFX##_grow(SNAME *_list_); \
\
FMOD SNAME *PFX##_new(size_t size) \
{ \
if (size < 1) \
return NULL; \
\
SNAME *_list_ = malloc(sizeof(SNAME)); \
\
if (!_list_) \
return NULL; \
\
_list_->buffer = malloc(sizeof(V) * size); \
\
if (!_list_->buffer) \
{ \
free(_list_); \
return NULL; \
} \
\
memset(_list_->buffer, 0, sizeof(V) * size); \
\
for (size_t i = 0; i < size; i++) \
{ \
_list_->buffer[i] = 0; \
} \
\
_list_->capacity = size; \
_list_->count = 0; \
\
return _list_; \
} \
\
FMOD void PFX##_clear(SNAME *_list_) \
{ \
memset(_list_->buffer, 0, sizeof(V) * _list_->capacity); \
\
_list_->count = 0; \
} \
\
FMOD void PFX##_free(SNAME *_list_) \
{ \
free(_list_->buffer); \
free(_list_); \
} \
\
FMOD bool PFX##_push_front(SNAME *_list_, V element) \
{ \
if (PFX##_full(_list_)) \
{ \
if (!PFX##_grow(_list_)) \
return false; \
} \
\
if (!PFX##_empty(_list_)) \
{ \
for (size_t i = _list_->count; i > 0; i--) \
{ \
_list_->buffer[i] = _list_->buffer[i - 1]; \
} \
} \
\
_list_->buffer[0] = element; \
\
_list_->count++; \
\
return true; \
} \
\
FMOD bool PFX##_push(SNAME *_list_, V element, size_t index) \
{ \
if (index > _list_->count) \
return false; \
\
if (index == 0) \
{ \
return PFX##_push_front(_list_, element); \
} \
else if (index == _list_->count) \
{ \
return PFX##_push_back(_list_, element); \
} \
\
if (PFX##_full(_list_)) \
{ \
if (!PFX##_grow(_list_)) \
return false; \
} \
\
for (size_t i = _list_->count; i > index; i--) \
{ \
_list_->buffer[i] = _list_->buffer[i - 1]; \
} \
\
_list_->buffer[index] = element; \
\
_list_->count++; \
\
return true; \
} \
\
FMOD bool PFX##_push_back(SNAME *_list_, V element) \
{ \
if (PFX##_full(_list_)) \
{ \
if (!PFX##_grow(_list_)) \
return false; \
} \
\
_list_->buffer[_list_->count++] = element; \
\
return true; \
} \
\
FMOD bool PFX##_pop_front(SNAME *_list_) \
{ \
if (PFX##_empty(_list_)) \
return false; \
\
for (size_t i = 0; i < _list_->count; i++) \
{ \
_list_->buffer[i] = _list_->buffer[i + 1]; \
} \
\
_list_->buffer[--_list_->count] = 0; \
\
return true; \
} \
\
FMOD bool PFX##_pop(SNAME *_list_, size_t index) \
{ \
if (PFX##_empty(_list_)) \
return false; \
\
if (index >= _list_->count) \
return false; \
\
if (index == 0) \
{ \
return PFX##_pop_front(_list_); \
} \
else if (index == _list_->count - 1) \
{ \
return PFX##_pop_back(_list_); \
} \
\
for (size_t i = index; i < _list_->count - 1; i++) \
{ \
_list_->buffer[i] = _list_->buffer[i + 1]; \
} \
\
_list_->buffer[--_list_->count] = 0; \
\
return true; \
} \
\
FMOD bool PFX##_pop_back(SNAME *_list_) \
{ \
if (PFX##_empty(_list_)) \
return false; \
\
_list_->buffer[--_list_->count] = 0; \
\
return true; \
} \
\
FMOD bool PFX##_push_if(SNAME *_list_, V element, size_t index, bool condition) \
{ \
if (condition) \
return PFX##_push(_list_, element, index); \
\
return false; \
} \
\
FMOD bool PFX##_pop_if(SNAME *_list_, size_t index, bool condition) \
{ \
if (condition) \
return PFX##_pop(_list_, index); \
\
return false; \
} \
\
FMOD V PFX##_front(SNAME *_list_) \
{ \
if (PFX##_empty(_list_)) \
return 0; \
\
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; \
\
return _list_->buffer[index]; \
} \
\
FMOD V PFX##_back(SNAME *_list_) \
{ \
if (PFX##_empty(_list_)) \
return 0; \
\
return _list_->buffer[_list_->count - 1]; \
} \
\
FMOD bool PFX##_empty(SNAME *_list_) \
{ \
return _list_->count == 0; \
} \
\
FMOD bool PFX##_full(SNAME *_list_) \
{ \
return _list_->count >= _list_->capacity; \
} \
\
FMOD size_t PFX##_count(SNAME *_list_) \
{ \
return _list_->count; \
} \
\
FMOD size_t PFX##_capacity(SNAME *_list_) \
{ \
return _list_->capacity; \
} \
\
FMOD bool PFX##_grow(SNAME *_list_) \
{ \
size_t new_capacity = _list_->capacity * 2; \
\
V *new_buffer = realloc(_list_->buffer, sizeof(V) * new_capacity); \
\
if (!new_buffer) \
return false; \
\
_list_->buffer = new_buffer; \
_list_->capacity = new_capacity; \
\
return true; \
} \
\
FMOD void PFX##_iter_new(SNAME##_iter *iter, SNAME *target) \
{ \
iter->target = target; \
iter->cursor = 0; \
iter->start = true; \
iter->end = PFX##_empty(target); \
} \
\
FMOD bool PFX##_iter_start(SNAME##_iter *iter) \
{ \
return iter->cursor == 0 && iter->start; \
} \
\
FMOD bool PFX##_iter_end(SNAME##_iter *iter) \
{ \
return iter->cursor == iter->target->count - 1 && iter->end; \
} \
\
FMOD void PFX##_iter_tostart(SNAME##_iter *iter) \
{ \
iter->cursor = 0; \
iter->start = true; \
iter->end = PFX##_empty(iter->target); \
} \
\
FMOD void PFX##_iter_toend(SNAME##_iter *iter) \
{ \
iter->cursor = iter->target->count - 1; \
iter->start = PFX##_empty(iter->target); \
iter->end = true; \
} \
\
FMOD bool PFX##_iter_next(SNAME##_iter *iter, V *result, size_t *index) \
{ \
if (iter->end) \
return false; \
\
*index = iter->cursor; \
*result = iter->target->buffer[iter->cursor]; \
iter->start = false; \
\
if (iter->cursor == iter->target->count - 1) \
iter->end = true; \
else \
iter->cursor++; \
\
return true; \
} \
\
FMOD bool PFX##_iter_prev(SNAME##_iter *iter, V *result, size_t *index) \
{ \
if (iter->start) \
return false; \
\
*index = iter->cursor; \
*result = iter->target->buffer[iter->cursor]; \
iter->end = false; \
\
if (iter->cursor == 0) \
iter->start = true; \
else \
iter->cursor--; \
\
return true; \
#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_); \
\
FMOD SNAME *PFX##_new(size_t capacity) \
{ \
if (capacity < 1) \
return NULL; \
\
SNAME *_list_ = malloc(sizeof(SNAME)); \
\
if (!_list_) \
return NULL; \
\
_list_->buffer = malloc(capacity * sizeof(V)); \
\
if (!_list_->buffer) \
{ \
free(_list_); \
return NULL; \
} \
\
memset(_list_->buffer, 0, capacity * sizeof(V)); \
\
_list_->capacity = capacity; \
_list_->count = 0; \
\
_list_->it_start = PFX##_impl_it_start; \
_list_->it_end = PFX##_impl_it_end; \
\
return _list_; \
} \
\
FMOD SNAME *PFX##_new_from(V *elements, size_t size) \
{ \
if (size == 0) \
return NULL; \
\
SNAME *_list_ = PFX##_new(size + size / 2); \
\
if (!_list_) \
return NULL; \
\
memcpy(_list_->buffer, elements, size * sizeof(V)); \
\
_list_->count = size; \
\
return _list_; \
} \
\
FMOD void PFX##_clear(SNAME *_list_) \
{ \
memset(_list_->buffer, 0, sizeof(V) * _list_->capacity); \
\
_list_->count = 0; \
} \
\
FMOD void PFX##_free(SNAME *_list_) \
{ \
free(_list_->buffer); \
free(_list_); \
} \
\
FMOD bool PFX##_push_front(SNAME *_list_, V element) \
{ \
if (PFX##_full(_list_)) \
{ \
if (!PFX##_impl_grow(_list_, _list_->count + 1)) \
return false; \
} \
\
if (!PFX##_empty(_list_)) \
{ \
memmove(_list_->buffer + 1, _list_->buffer, _list_->count * sizeof(V)); \
} \
\
_list_->buffer[0] = element; \
\
_list_->count++; \
\
return true; \
} \
\
FMOD bool PFX##_push(SNAME *_list_, V element, size_t index) \
{ \
if (index > _list_->count) \
return false; \
\
if (index == 0) \
{ \
return PFX##_push_front(_list_, element); \
} \
else if (index == _list_->count) \
{ \
return PFX##_push_back(_list_, element); \
} \
\
if (PFX##_full(_list_)) \
{ \
if (!PFX##_impl_grow(_list_, _list_->count + 1)) \
return false; \
} \
\
memmove(_list_->buffer + index + 1, _list_->buffer + index, (_list_->count - index) * sizeof(V)); \
\
_list_->buffer[index] = element; \
\
_list_->count++; \
\
return true; \
} \
\
FMOD bool PFX##_push_back(SNAME *_list_, V element) \
{ \
if (PFX##_full(_list_)) \
{ \
if (!PFX##_impl_grow(_list_, _list_->count + 1)) \
return false; \
} \
\
_list_->buffer[_list_->count++] = element; \
\
return true; \
} \
\
FMOD bool PFX##_pop_front(SNAME *_list_) \
{ \
if (PFX##_empty(_list_)) \
return false; \
\
memmove(_list_->buffer, _list_->buffer + 1, _list_->count * sizeof(V)); \
\
_list_->buffer[--_list_->count] = 0; \
\
return true; \
} \
\
FMOD bool PFX##_pop(SNAME *_list_, size_t index) \
{ \
if (PFX##_empty(_list_)) \
return false; \
\
if (index >= _list_->count) \
return false; \
\
if (index == 0) \
{ \
return PFX##_pop_front(_list_); \
} \
else if (index == _list_->count - 1) \
{ \
return PFX##_pop_back(_list_); \
} \
\
memmove(_list_->buffer + index, _list_->buffer + index + 1, (_list_->count - index) * sizeof(V)); \
\
_list_->buffer[--_list_->count] = 0; \
\
return true; \
} \
\
FMOD bool PFX##_pop_back(SNAME *_list_) \
{ \
if (PFX##_empty(_list_)) \
return false; \
\
_list_->buffer[--_list_->count] = 0; \
\
return true; \
} \
\
FMOD bool PFX##_push_if(SNAME *_list_, V element, size_t index, bool condition) \
{ \
if (condition) \
return PFX##_push(_list_, element, index); \
\
return false; \
} \
\
FMOD bool PFX##_pop_if(SNAME *_list_, size_t index, bool condition) \
{ \
if (condition) \
return PFX##_pop(_list_, index); \
\
return false; \
} \
\
FMOD bool PFX##_prepend(SNAME *_list_, V *elements, size_t size) \
{ \
if (size == 0) \
return false; \
\
if (!PFX##_fits(_list_, size)) \
{ \
if (!PFX##_impl_grow(_list_, _list_->count + size)) \
return false; \
} \
\
memmove(_list_->buffer + size, _list_->buffer, _list_->count * sizeof(V)); \
\
memcpy(_list_->buffer, elements, size * sizeof(V)); \
\
_list_->count += size; \
\
return true; \
} \
\
FMOD bool PFX##_insert(SNAME *_list_, V *elements, size_t size, size_t index) \
{ \
if (size == 0 || index > _list_->count) \
return false; \
\
if (index == 0) \
return PFX##_prepend(_list_, elements, size); \
else if (index == _list_->count) \
return PFX##_append(_list_, elements, size); \
else \
{ \
if (!PFX##_fits(_list_, size)) \
{ \
if (!PFX##_impl_grow(_list_, _list_->count + size)) \
return false; \
} \
\
memmove(_list_->buffer + index + size, _list_->buffer + index, (_list_->count - index) * sizeof(V)); \
\
memcpy(_list_->buffer + index, elements, size * sizeof(V)); \
\
_list_->count += size; \
} \
\
return true; \
} \
\
FMOD bool PFX##_append(SNAME *_list_, V *elements, size_t size) \
{ \
if (size == 0) \
return false; \
\
if (!PFX##_fits(_list_, size)) \
{ \
if (!PFX##_impl_grow(_list_, _list_->count + size)) \
return false; \
} \
\
memcpy(_list_->buffer + _list_->count, elements, size * sizeof(V)); \
\
_list_->count += size; \
\
return true; \
} \
\
FMOD bool PFX##_remove(SNAME *_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(V)); \
\
memset(_list_->buffer + _list_->count - length, 0, length * sizeof(V)); \
\
_list_->count -= to - from + 1; \
\
return true; \
} \
\
FMOD SNAME *PFX##_extract(SNAME *_list_, size_t from, size_t to) \
{ \
if (from > to || to >= _list_->count) \
return false; \
\
size_t length = to - from + 1; \
\
SNAME *result = PFX##_new_from(_list_->buffer + from, length); \
\
if (!result) \
return NULL; \
\
memmove(_list_->buffer + from, _list_->buffer + to + 1, (_list_->count - to - 1) * sizeof(V)); \
\
memset(_list_->buffer + _list_->count - length, 0, length * sizeof(V)); \
\
_list_->count -= length; \
\
return result; \
} \
\
FMOD V PFX##_front(SNAME *_list_) \
{ \
if (PFX##_empty(_list_)) \
return 0; \
\
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; \
\
return _list_->buffer[index]; \
} \
\
FMOD V *PFX##_get_ref(SNAME *_list_, size_t index) \
{ \
if (index >= _list_->count) \
return NULL; \
\
if (PFX##_empty(_list_)) \
return NULL; \
\
return &(_list_->buffer[index]); \
} \
\
FMOD V PFX##_back(SNAME *_list_) \
{ \
if (PFX##_empty(_list_)) \
return 0; \
\
return _list_->buffer[_list_->count - 1]; \
} \
\
FMOD size_t PFX##_indexof(SNAME *_list_, V element, int (*comparator)(V, V), 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; \
} \
\
FMOD bool PFX##_contains(SNAME *_list_, V element, int (*comparator)(V, V)) \
{ \
for (size_t i = 0; i < _list_->count; i++) \
{ \
if (comparator(_list_->buffer[i], element) == 0) \
return true; \
} \
\
return false; \
} \
\
FMOD bool PFX##_empty(SNAME *_list_) \
{ \
return _list_->count == 0; \
} \
\
FMOD bool PFX##_full(SNAME *_list_) \
{ \
return _list_->count >= _list_->capacity; \
} \
\
FMOD size_t PFX##_count(SNAME *_list_) \
{ \
return _list_->count; \
} \
\
FMOD bool PFX##_fits(SNAME *_list_, size_t size) \
{ \
return _list_->count + size <= _list_->capacity; \
} \
\
FMOD size_t PFX##_capacity(SNAME *_list_) \
{ \
return _list_->capacity; \
} \
\
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 = 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 = 0; \
iter->start = true; \
iter->end = PFX##_empty(iter->target); \
} \
\
FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \
{ \
iter->start = PFX##_empty(iter->target); \
iter->cursor = PFX##_empty(iter->target) ? 0 : iter->target->count - 1; \
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 == iter->target->count - 1) \
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 == 0) \
iter->start = true; \
else \
iter->cursor--; \
\
return true; \
} \
\
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return 0; \
\
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->cursor; \
} \
\
FMOD bool PFX##_impl_grow(SNAME *_list_, size_t required) \
{ \
size_t new_capacity = _list_->capacity * 2; \
\
if (new_capacity < required) \
new_capacity = required; \
\
V *new_buffer = realloc(_list_->buffer, sizeof(V) * new_capacity); \
\
if (!new_buffer) \
return false; \
\
_list_->buffer = new_buffer; \
_list_->capacity = new_capacity; \
\
return true; \
} \
\
SNAME##_iter PFX##_impl_it_start(SNAME *_list_) \
{ \
SNAME##_iter iter; \
\
PFX##_iter_init(&iter, _list_); \
PFX##_iter_to_start(&iter); \
\
return iter; \
} \
\
SNAME##_iter PFX##_impl_it_end(SNAME *_list_) \
{ \
SNAME##_iter iter; \
\
PFX##_iter_init(&iter, _list_); \
PFX##_iter_to_end(&iter); \
\
return iter; \
}
#endif /* CMC_LIST_H */
+382 -269
View File
@@ -37,277 +37,390 @@
#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) \
\
struct SNAME##_s \
{ \
V *buffer; \
size_t capacity; \
size_t count; \
size_t front; \
size_t rear; \
}; \
\
struct SNAME##_iter_s \
{ \
struct SNAME##_s *target; \
size_t cursor; \
size_t index; \
bool start; \
bool end; \
}; \
\
#define QUEUE_GENERATE_STRUCT(PFX, SNAME, FMOD, V)
/* HEADER ********************************************************************/
#define QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
\
typedef struct SNAME##_s SNAME; \
typedef struct SNAME##_iter_s SNAME##_iter; \
\
FMOD SNAME *PFX##_new(size_t size); \
FMOD void PFX##_clear(SNAME *_queue_); \
FMOD void PFX##_free(SNAME *_queue_); \
FMOD bool PFX##_enqueue(SNAME *_queue_, V element); \
FMOD bool PFX##_dequeue(SNAME *_queue_); \
FMOD bool PFX##_enqueue_if(SNAME *_queue_, V element, bool condition); \
FMOD bool PFX##_dequeue_if(SNAME *_queue_, bool condition); \
FMOD V PFX##_peek(SNAME *_queue_); \
FMOD bool PFX##_empty(SNAME *_queue_); \
FMOD bool PFX##_full(SNAME *_queue_); \
FMOD size_t PFX##_count(SNAME *_queue_); \
FMOD size_t PFX##_capacity(SNAME *_queue_); \
\
FMOD void PFX##_iter_new(SNAME##_iter *iter, SNAME *target); \
FMOD bool PFX##_iter_start(SNAME##_iter *iter); \
FMOD bool PFX##_iter_end(SNAME##_iter *iter); \
FMOD void PFX##_iter_tostart(SNAME##_iter *iter); \
FMOD void PFX##_iter_toend(SNAME##_iter *iter); \
FMOD bool PFX##_iter_next(SNAME##_iter *iter, V *result, size_t *index); \
FMOD bool PFX##_iter_prev(SNAME##_iter *iter, V *result, size_t *index); \
\
#define QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
\
/* Queue 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 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(size_t size); \
FMOD void PFX##_clear(SNAME *_queue_); \
FMOD void PFX##_free(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(SNAME *_queue_); \
\
/* 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); \
\
/* SOURCE ********************************************************************/
#define QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \
\
FMOD bool PFX##_grow(SNAME *_queue_); \
\
FMOD SNAME *PFX##_new(size_t size) \
{ \
if (size < 1) \
return NULL; \
\
SNAME *_queue_ = malloc(sizeof(SNAME)); \
\
if (!_queue_) \
return NULL; \
\
_queue_->buffer = malloc(sizeof(V) * size); \
\
if (!_queue_->buffer) \
{ \
free(_queue_); \
return NULL; \
} \
\
memset(_queue_->buffer, 0, sizeof(V) * size); \
\
_queue_->capacity = size; \
_queue_->count = 0; \
_queue_->front = 0; \
_queue_->rear = 0; \
\
return _queue_; \
} \
\
FMOD void PFX##_clear(SNAME *_queue_) \
{ \
memset(_queue_->buffer, 0, sizeof(V) * _queue_->capacity); \
\
_queue_->count = 0; \
_queue_->front = 0; \
_queue_->rear = 0; \
} \
\
FMOD void PFX##_free(SNAME *_queue_) \
{ \
free(_queue_->buffer); \
free(_queue_); \
} \
\
FMOD bool PFX##_enqueue(SNAME *_queue_, V element) \
{ \
if (PFX##_full(_queue_)) \
{ \
if (!PFX##_grow(_queue_)) \
return false; \
} \
\
_queue_->buffer[_queue_->rear] = element; \
\
_queue_->rear = (_queue_->rear == _queue_->capacity - 1) ? 0 : _queue_->rear + 1; \
_queue_->count++; \
\
return true; \
} \
\
FMOD bool PFX##_dequeue(SNAME *_queue_) \
{ \
if (PFX##_empty(_queue_)) \
return false; \
\
_queue_->buffer[_queue_->front] = 0; \
\
_queue_->front = (_queue_->front == _queue_->capacity - 1) ? 0 : _queue_->front + 1; \
_queue_->count--; \
\
return true; \
} \
\
FMOD 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 0; \
\
return _queue_->buffer[_queue_->front]; \
} \
\
FMOD bool PFX##_empty(SNAME *_queue_) \
{ \
return _queue_->count == 0; \
} \
\
FMOD bool PFX##_full(SNAME *_queue_) \
{ \
return _queue_->count >= _queue_->capacity; \
} \
\
FMOD size_t PFX##_count(SNAME *_queue_) \
{ \
return _queue_->count; \
} \
\
FMOD size_t PFX##_capacity(SNAME *_queue_) \
{ \
return _queue_->capacity; \
} \
\
FMOD bool PFX##_grow(SNAME *_queue_) \
{ \
\
size_t new_capacity = _queue_->capacity * 2; \
\
V *new_buffer = malloc(sizeof(V) * new_capacity); \
\
if (!new_buffer) \
return false; \
\
for (size_t i = _queue_->front, j = 0; j < _queue_->count; i = (i + 1) % _queue_->capacity, j++) \
{ \
new_buffer[j] = _queue_->buffer[i]; \
} \
\
free(_queue_->buffer); \
\
_queue_->buffer = new_buffer; \
_queue_->capacity = new_capacity; \
_queue_->front = 0; \
_queue_->rear = _queue_->count; \
\
return true; \
} \
\
FMOD void PFX##_iter_new(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 iter->cursor == iter->target->front && iter->start; \
} \
\
FMOD bool PFX##_iter_end(SNAME##_iter *iter) \
{ \
size_t real_rear = iter->target->rear == 0 ? iter->target->capacity - 1 : iter->target->rear - 1; \
return iter->cursor == real_rear && iter->end; \
} \
\
FMOD void PFX##_iter_tostart(SNAME##_iter *iter) \
{ \
iter->cursor = iter->target->front; \
iter->index = 0; \
iter->start = true; \
iter->end = PFX##_empty(iter->target); \
} \
\
FMOD void PFX##_iter_toend(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
iter->cursor = 0; \
else \
iter->cursor = (iter->target->rear == 0) ? iter->target->count - 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, V *result, size_t *index) \
{ \
if (iter->end) \
return false; \
\
*index = iter->index; \
*result = iter->target->buffer[iter->cursor]; \
iter->start = false; \
\
if (iter->index == iter->target->count - 1) \
iter->end = true; \
else \
{ \
iter->cursor = (iter->cursor + 1) % (iter->target->capacity); \
iter->index++; \
} \
\
return true; \
} \
\
FMOD bool PFX##_iter_prev(SNAME##_iter *iter, V *result, size_t *index) \
{ \
if (iter->start) \
return false; \
\
*index = iter->index; \
*result = iter->target->buffer[iter->cursor]; \
iter->end = false; \
\
if (iter->index == 0) \
iter->start = true; \
else \
{ \
iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; \
iter->index--; \
} \
\
return true; \
#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_); \
\
FMOD SNAME *PFX##_new(size_t size) \
{ \
if (size < 1) \
return NULL; \
\
SNAME *_queue_ = malloc(sizeof(SNAME)); \
\
if (!_queue_) \
return NULL; \
\
_queue_->buffer = malloc(sizeof(V) * size); \
\
if (!_queue_->buffer) \
{ \
free(_queue_); \
return NULL; \
} \
\
memset(_queue_->buffer, 0, sizeof(V) * size); \
\
_queue_->capacity = size; \
_queue_->count = 0; \
_queue_->front = 0; \
_queue_->rear = 0; \
\
_queue_->it_start = PFX##_impl_it_start; \
_queue_->it_end = PFX##_impl_it_end; \
\
return _queue_; \
} \
\
FMOD void PFX##_clear(SNAME *_queue_) \
{ \
memset(_queue_->buffer, 0, sizeof(V) * _queue_->capacity); \
\
_queue_->count = 0; \
_queue_->front = 0; \
_queue_->rear = 0; \
} \
\
FMOD void PFX##_free(SNAME *_queue_) \
{ \
free(_queue_->buffer); \
free(_queue_); \
} \
\
FMOD bool PFX##_enqueue(SNAME *_queue_, V element) \
{ \
if (PFX##_full(_queue_)) \
{ \
if (!PFX##_grow(_queue_)) \
return false; \
} \
\
_queue_->buffer[_queue_->rear] = element; \
\
_queue_->rear = (_queue_->rear == _queue_->capacity - 1) ? 0 : _queue_->rear + 1; \
_queue_->count++; \
\
return true; \
} \
\
FMOD bool PFX##_dequeue(SNAME *_queue_) \
{ \
if (PFX##_empty(_queue_)) \
return false; \
\
_queue_->buffer[_queue_->front] = 0; \
\
_queue_->front = (_queue_->front == _queue_->capacity - 1) ? 0 : _queue_->front + 1; \
_queue_->count--; \
\
return true; \
} \
\
FMOD 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 0; \
\
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 >= _queue_->capacity; \
} \
\
FMOD size_t PFX##_count(SNAME *_queue_) \
{ \
return _queue_->count; \
} \
\
FMOD size_t PFX##_capacity(SNAME *_queue_) \
{ \
return _queue_->capacity; \
} \
\
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->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) ? iter->target->capacity - 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) % (iter->target->capacity); \
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) ? iter->target->capacity - 1 : iter->cursor - 1; \
iter->index--; \
} \
\
return true; \
} \
\
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return 0; \
\
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; \
} \
\
FMOD bool PFX##_grow(SNAME *_queue_) \
{ \
\
size_t new_capacity = _queue_->capacity * 2; \
\
V *new_buffer = malloc(sizeof(V) * 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; \
} \
\
SNAME##_iter PFX##_impl_it_start(SNAME *_queue_) \
{ \
SNAME##_iter iter; \
\
PFX##_iter_init(&iter, _queue_); \
PFX##_iter_to_start(&iter); \
\
return iter; \
} \
\
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_QUEUE_H */
+340 -232
View File
@@ -37,240 +37,348 @@
#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) \
\
struct SNAME##_s \
{ \
V *buffer; \
size_t capacity; \
size_t count; \
}; \
\
struct SNAME##_iter_s \
{ \
struct SNAME##_s *target; \
size_t cursor; \
bool start; \
bool end; \
}; \
\
#define STACK_GENERATE_STRUCT(PFX, SNAME, FMOD, V)
/* HEADER ********************************************************************/
#define STACK_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
\
typedef struct SNAME##_s SNAME; \
typedef struct SNAME##_iter_s SNAME##_iter; \
\
FMOD SNAME *PFX##_new(size_t size); \
FMOD void PFX##_clear(SNAME *_stack_); \
FMOD void PFX##_free(SNAME *_stack_); \
FMOD bool PFX##_push(SNAME *_stack_, V element); \
FMOD bool PFX##_pop(SNAME *_stack_); \
FMOD bool PFX##_push_if(SNAME *_stack_, V element, bool condition); \
FMOD bool PFX##_pop_if(SNAME *_stack_, bool condition); \
FMOD V PFX##_top(SNAME *_stack_); \
FMOD bool PFX##_empty(SNAME *_stack_); \
FMOD bool PFX##_full(SNAME *_stack_); \
FMOD size_t PFX##_count(SNAME *_stack_); \
FMOD size_t PFX##_capacity(SNAME *_stack_); \
\
FMOD void PFX##_iter_new(SNAME##_iter *iter, SNAME *target); \
FMOD bool PFX##_iter_start(SNAME##_iter *iter); \
FMOD bool PFX##_iter_end(SNAME##_iter *iter); \
FMOD void PFX##_iter_tostart(SNAME##_iter *iter); \
FMOD void PFX##_iter_toend(SNAME##_iter *iter); \
FMOD bool PFX##_iter_next(SNAME##_iter *iter, V *result, size_t *index); \
FMOD bool PFX##_iter_prev(SNAME##_iter *iter, V *result, size_t *index); \
\
#define STACK_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
\
/* Stack Structure */ \
typedef struct SNAME##_s \
{ \
/* Dynamic array of elements */ \
V *buffer; \
\
/* Current array capacity */ \
size_t capacity; \
\
/* 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(size_t size); \
FMOD void PFX##_clear(SNAME *_stack_); \
FMOD void PFX##_free(SNAME *_stack_); \
/* Collection Input and Output */ \
FMOD bool PFX##_push(SNAME *_stack_, V element); \
FMOD bool PFX##_pop(SNAME *_stack_); \
/* Conditional Input and Output */ \
FMOD bool PFX##_push_if(SNAME *_stack_, V element, bool condition); \
FMOD bool PFX##_pop_if(SNAME *_stack_, bool condition); \
/* Element Access */ \
FMOD V PFX##_top(SNAME *_stack_); \
/* Collection State */ \
FMOD bool PFX##_contains(SNAME *_stack_, V element, int (*comparator)(V, V)); \
FMOD bool PFX##_empty(SNAME *_stack_); \
FMOD bool PFX##_full(SNAME *_stack_); \
FMOD size_t PFX##_count(SNAME *_stack_); \
FMOD size_t PFX##_capacity(SNAME *_stack_); \
\
/* 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); \
\
/* SOURCE ********************************************************************/
#define STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \
\
FMOD bool PFX##_grow(SNAME *_stack_); \
\
FMOD SNAME *PFX##_new(size_t size) \
{ \
if (size < 1) \
return NULL; \
\
SNAME *_stack_ = malloc(sizeof(SNAME)); \
\
if (!_stack_) \
return NULL; \
\
_stack_->buffer = malloc(sizeof(V) * size); \
\
if (!_stack_->buffer) \
{ \
free(_stack_); \
return NULL; \
} \
\
memset(_stack_->buffer, 0, sizeof(V) * size); \
\
_stack_->capacity = size; \
_stack_->count = 0; \
\
return _stack_; \
} \
\
FMOD void PFX##_clear(SNAME *_stack_) \
{ \
memset(_stack_->buffer, 0, sizeof(V) * _stack_->capacity); \
\
_stack_->count = 0; \
} \
\
FMOD void PFX##_free(SNAME *_stack_) \
{ \
free(_stack_->buffer); \
free(_stack_); \
} \
\
FMOD bool PFX##_push(SNAME *_stack_, V element) \
{ \
if (PFX##_full(_stack_)) \
{ \
if (!PFX##_grow(_stack_)) \
return false; \
} \
\
_stack_->buffer[_stack_->count++] = element; \
\
return true; \
} \
\
FMOD bool PFX##_pop(SNAME *_stack_) \
{ \
if (PFX##_empty(_stack_)) \
return false; \
\
_stack_->buffer[--_stack_->count] = 0; \
\
return true; \
} \
\
FMOD 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 0; \
\
return _stack_->buffer[_stack_->count - 1]; \
} \
\
FMOD bool PFX##_empty(SNAME *_stack_) \
{ \
return _stack_->count == 0; \
} \
\
FMOD bool PFX##_full(SNAME *_stack_) \
{ \
return _stack_->count >= _stack_->capacity; \
} \
\
FMOD size_t PFX##_count(SNAME *_stack_) \
{ \
return _stack_->count; \
} \
\
FMOD size_t PFX##_capacity(SNAME *_stack_) \
{ \
return _stack_->capacity; \
} \
\
FMOD bool PFX##_grow(SNAME *_stack_) \
{ \
size_t new_capacity = _stack_->capacity * 2; \
\
V *new_buffer = realloc(_stack_->buffer, sizeof(V) * new_capacity); \
\
if (!new_buffer) \
return false; \
\
_stack_->buffer = new_buffer; \
_stack_->capacity = new_capacity; \
\
return true; \
} \
\
FMOD void PFX##_iter_new(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 iter->cursor == iter->target->count - 1 && iter->start; \
} \
\
FMOD bool PFX##_iter_end(SNAME##_iter *iter) \
{ \
return iter->cursor == 0 && iter->end; \
} \
\
FMOD void PFX##_iter_tostart(SNAME##_iter *iter) \
{ \
iter->cursor = iter->target->count - 1; \
iter->start = true; \
iter->end = PFX##_empty(iter->target); \
} \
\
FMOD void PFX##_iter_toend(SNAME##_iter *iter) \
{ \
iter->cursor = 0; \
iter->start = PFX##_empty(iter->target); \
iter->end = true; \
} \
\
FMOD bool PFX##_iter_next(SNAME##_iter *iter, V *result, size_t *index) \
{ \
if (iter->end) \
return false; \
\
*index = iter->target->count - iter->cursor - 1; \
*result = iter->target->buffer[iter->cursor]; \
iter->start = false; \
\
if (iter->cursor == 0) \
iter->end = true; \
else \
iter->cursor--; \
\
return true; \
} \
\
FMOD bool PFX##_iter_prev(SNAME##_iter *iter, V *result, size_t *index) \
{ \
if (iter->start) \
return false; \
\
*index = iter->target->count - iter->cursor - 1; \
*result = iter->target->buffer[iter->cursor]; \
iter->end = false; \
\
if (iter->cursor == iter->target->count - 1) \
iter->start = true; \
else \
iter->cursor++; \
\
return true; \
#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_); \
\
FMOD SNAME *PFX##_new(size_t size) \
{ \
if (size < 1) \
return NULL; \
\
SNAME *_stack_ = malloc(sizeof(SNAME)); \
\
if (!_stack_) \
return NULL; \
\
_stack_->buffer = malloc(sizeof(V) * size); \
\
if (!_stack_->buffer) \
{ \
free(_stack_); \
return NULL; \
} \
\
memset(_stack_->buffer, 0, sizeof(V) * size); \
\
_stack_->capacity = size; \
_stack_->count = 0; \
\
_stack_->it_start = PFX##_impl_it_start; \
_stack_->it_end = PFX##_impl_it_end; \
\
return _stack_; \
} \
\
FMOD void PFX##_clear(SNAME *_stack_) \
{ \
memset(_stack_->buffer, 0, sizeof(V) * _stack_->capacity); \
\
_stack_->count = 0; \
} \
\
FMOD void PFX##_free(SNAME *_stack_) \
{ \
free(_stack_->buffer); \
free(_stack_); \
} \
\
FMOD bool PFX##_push(SNAME *_stack_, V element) \
{ \
if (PFX##_full(_stack_)) \
{ \
if (!PFX##_impl_grow(_stack_)) \
return false; \
} \
\
_stack_->buffer[_stack_->count++] = element; \
\
return true; \
} \
\
FMOD bool PFX##_pop(SNAME *_stack_) \
{ \
if (PFX##_empty(_stack_)) \
return false; \
\
_stack_->buffer[--_stack_->count] = 0; \
\
return true; \
} \
\
FMOD 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 0; \
\
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 >= _stack_->capacity; \
} \
\
FMOD size_t PFX##_count(SNAME *_stack_) \
{ \
return _stack_->count; \
} \
\
FMOD size_t PFX##_capacity(SNAME *_stack_) \
{ \
return _stack_->capacity; \
} \
\
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 = 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 0; \
\
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; \
} \
\
FMOD bool PFX##_impl_grow(SNAME *_stack_) \
{ \
size_t new_capacity = _stack_->capacity * 2; \
\
V *new_buffer = realloc(_stack_->buffer, sizeof(V) * new_capacity); \
\
if (!new_buffer) \
return false; \
\
_stack_->buffer = new_buffer; \
_stack_->capacity = new_capacity; \
\
return true; \
} \
\
SNAME##_iter PFX##_impl_it_start(SNAME *_stack_) \
{ \
SNAME##_iter iter; \
\
PFX##_iter_init(&iter, _stack_); \
PFX##_iter_to_start(&iter); \
\
return iter; \
} \
\
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_STACK_H */
+820 -675
View File
File diff suppressed because it is too large. Load diff
+851 -741
View File
File diff suppressed because it is too large. Load diff
+204
View File
@@ -0,0 +1,204 @@
#include "../src/macro_collections.h"
#include <stdio.h>
#include <assert.h>
#include <stdbool.h>
int intcmp(int a, int b)
{
return (a > b) - (a < b);
}
size_t inthash(int t)
{
size_t a = t;
a += ~(a << 15);
a ^= (a >> 10);
a += (a << 3);
a ^= (a >> 6);
a += ~(a << 11);
a ^= (a >> 16);
return a;
}
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)
int main(void)
{
list *l = l_new(1000);
stack *s = s_new(1000);
queue *q = q_new(1000);
deque *d = d_new(1000);
linked *ll = ll_new();
heap *h = h_new(1000, MaxHeap, intcmp);
tset *ts = ts_new(intcmp);
tmap *tm = tm_new(intcmp);
hset *hs = hs_new(1000, 0.9, intcmp, inthash);
hmap *hm = hm_new(1000, 0.9, intcmp, inthash);
bool a[10] = {false, false, false, false, false, false, false, false, false, false},
b[10] = {false, false, false, false, false, false, false, false, false, false},
c[10] = {true, true, true, true, true, true, true, true, true, true};
b[0] = d_contains(d, 1, intcmp);
b[1] = hm_contains(hm, 1);
b[2] = hs_contains(hs, 1);
b[3] = h_contains(h, 1);
b[4] = ll_contains(ll, 1, intcmp);
b[5] = l_contains(l, 1, intcmp);
b[6] = q_contains(q, 1, intcmp);
b[7] = s_contains(s, 1, intcmp);
b[8] = tm_contains(tm, 1);
b[9] = ts_contains(ts, 1);
for (int i = 1; i < 1001; i++)
{
if (i % 2 == 0)
{
d_push_front(d, i);
l_push_front(l, i);
ll_push_front(ll, i);
}
else
{
d_push_back(d, i);
l_push_back(l, i);
ll_push_back(ll, i);
}
s_push(s, i);
q_enqueue(q, i);
h_insert(h, i);
ts_insert(ts, i);
tm_insert(tm, i, i);
hs_insert(hs, i);
hm_insert(hm, i, i);
}
for (int i = 1; i < 1001; i++)
{
c[0] = c[0] && d_contains(d, i, intcmp);
c[1] = c[1] && hm_contains(hm, i);
c[2] = c[2] && hs_contains(hs, i);
c[3] = c[3] && h_contains(h, i);
c[4] = c[4] && ll_contains(ll, i, intcmp);
c[5] = c[5] && l_contains(l, i, intcmp);
c[6] = c[6] && q_contains(q, i, intcmp);
c[7] = c[7] && s_contains(s, i, intcmp);
c[8] = c[8] && tm_contains(tm, i);
c[9] = c[9] && ts_contains(ts, i);
}
for (int i = -500; i < 1; i++)
{
a[0] = a[0] || d_contains(d, i, intcmp);
a[1] = a[1] || hm_contains(hm, i);
a[2] = a[2] || hs_contains(hs, i);
a[3] = a[3] || h_contains(h, i);
a[4] = a[4] || ll_contains(ll, i, intcmp);
a[5] = a[5] || l_contains(l, i, intcmp);
a[6] = a[6] || q_contains(q, i, intcmp);
a[7] = a[7] || s_contains(s, i, intcmp);
a[8] = a[8] || tm_contains(tm, i);
a[9] = a[9] || ts_contains(ts, i);
}
for (int i = 1001; i < 1500; i++)
{
a[0] = a[0] || d_contains(d, i, intcmp);
a[1] = a[1] || hm_contains(hm, i);
a[2] = a[2] || hs_contains(hs, i);
a[3] = a[3] || h_contains(h, i);
a[4] = a[4] || ll_contains(ll, i, intcmp);
a[5] = a[5] || l_contains(l, i, intcmp);
a[6] = a[6] || q_contains(q, i, intcmp);
a[7] = a[7] || s_contains(s, i, intcmp);
a[8] = a[8] || tm_contains(tm, i);
a[9] = a[9] || ts_contains(ts, i);
}
d_clear(d);
hm_clear(hm);
hs_clear(hs);
h_clear(h);
ll_clear(ll);
l_clear(l);
q_clear(q);
s_clear(s);
tm_clear(tm);
ts_clear(ts);
b[0] = b[0] || d_contains(d, 1, intcmp);
b[1] = b[1] || hm_contains(hm, 1);
b[2] = b[2] || hs_contains(hs, 1);
b[3] = b[3] || h_contains(h, 1);
b[4] = b[4] || ll_contains(ll, 1, intcmp);
b[5] = b[5] || l_contains(l, 1, intcmp);
b[6] = b[6] || q_contains(q, 1, intcmp);
b[7] = b[7] || s_contains(s, 1, intcmp);
b[8] = b[8] || tm_contains(tm, 1);
b[9] = b[9] || ts_contains(ts, 1);
printf("-------------------- CONTAINS --------------------\n");
if (c[0] && !a[0] && !b[0])
printf("%10s PASSED\n", "DEQUE");
else
printf("%10s FAILED\n", "DEQUE");
if (c[1] && !a[1] && !b[1])
printf("%10s PASSED\n", "HASHMAP");
else
printf("%10s FAILED\n", "HASHMAP");
if (c[2] && !a[2] && !b[2])
printf("%10s PASSED\n", "HASHSET");
else
printf("%10s FAILED\n", "HASHSET");
if (c[3] && !a[3] && !b[3])
printf("%10s PASSED\n", "HEAP");
else
printf("%10s FAILED\n", "HEAP");
if (c[4] && !a[4] && !b[4])
printf("%10s PASSED\n", "LINKEDLIST");
else
printf("%10s FAILED\n", "LINKEDLIST");
if (c[5] && !a[5] && !b[5])
printf("%10s PASSED\n", "LIST");
else
printf("%10s FAILED\n", "LIST");
if (c[6] && !a[6] && !b[6])
printf("%10s PASSED\n", "QUEUE");
else
printf("%10s FAILED\n", "QUEUE");
if (c[7] && !a[7] && !b[7])
printf("%10s PASSED\n", "STACK");
else
printf("%10s FAILED\n", "STACK");
if (c[8] && !a[8] && !b[8])
printf("%10s PASSED\n", "TREEMAP");
else
printf("%10s FAILED\n", "TREEMAP");
if (c[9] && !a[9] && !b[9])
printf("%10s PASSED\n", "TREESET");
else
printf("%10s FAILED\n", "TREESET");
l_free(l);
ll_free(ll);
s_free(s);
q_free(q);
d_free(d);
h_free(h);
ts_free(ts);
tm_free(tm);
hs_free(hs);
hm_free(hm);
return 0;
}
+127 -85
View File
@@ -1,6 +1,6 @@
#include "../src/macro_collections.h"
#include <stdio.h>
#include <assert.h>
#include "../src/macro_collections.h"
int intcmp(int a, int b)
{
@@ -19,18 +19,18 @@ 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(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(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)
int main(int argc, char const *argv[])
int main(void)
{
list *l = l_new(1000);
stack *s = s_new(1000);
@@ -70,136 +70,178 @@ int main(int argc, char const *argv[])
int sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0, sum5 = 0, sum6 = 0,
sum7 = 0, sum8 = 0, sum9 = 0, sum10 = 0, sum11 = 0;
FOR_EACH(l, list, int, l, {
sum0 += value;
FOR_EACH(d, deque, d, {
sum3 += d_iter_value(&iter);
})
FOR_EACH(s, stack, int, s, {
sum1 += value;
FOR_EACH(hm, hmap, hm, {
sum10 += hm_iter_key(&iter);
sum11 += hm_iter_value(&iter);
})
FOR_EACH(q, queue, int, q, {
sum2 += value;
FOR_EACH(hs, hset, hs, {
sum9 += hs_iter_value(&iter);
})
FOR_EACH(d, deque, int, d, {
sum3 += value;
FOR_EACH(h, heap, h, {
sum5 += h_iter_value(&iter);
})
FOR_EACH(ll, linked, int, ll, {
sum4 += value;
FOR_EACH(ll, linked, ll, {
sum4 += ll_iter_value(&iter);
})
FOR_EACH(h, heap, int, h, {
sum5 += value;
FOR_EACH(l, list, l, {
sum0 += l_iter_value(&iter);
})
FOR_EACH(ts, tset, int, ts, {
sum6 += value;
FOR_EACH(q, queue, q, {
sum2 += q_iter_value(&iter);
})
FOR_EACH_MAP(tm, tmap, int, int, tm, {
sum7 += key;
sum8 += value;
FOR_EACH(s, stack, s, {
sum1 += s_iter_value(&iter);
})
FOR_EACH(hs, hset, int, hs, {
sum9 += value;
FOR_EACH(tm, tmap, tm, {
sum7 += tm_iter_key(&iter);
sum8 += tm_iter_value(&iter);
})
FOR_EACH_MAP(hm, hmap, int, int, hm, {
sum10 += key;
sum11 += value;
FOR_EACH(ts, tset, ts, {
sum6 += ts_iter_value(&iter);
})
if (sum0 == 50005000)
printf("%10s PASSED\n", "LIST");
if (sum1 == 50005000)
printf("%10s PASSED\n", "STACK");
if (sum2 == 50005000)
printf("%10s PASSED\n", "QUEUE");
printf("\n-------------------- FOR_EACH --------------------\n");
if (sum3 == 50005000)
printf("%10s PASSED\n", "DEQUE");
if (sum4 == 50005000)
printf("%10s PASSED\n", "LINKEDLIST");
if (sum5 == 50005000)
printf("%10s PASSED\n", "HEAP");
if (sum6 == 50005000)
printf("%10s PASSED\n", "TREESET");
if (sum7 == 50005000 && sum8 == 50005000)
printf("%10s PASSED\n", "TREEMAP");
else
printf("%10s FAILED\n", "DEQUE");
if (sum9 == 50005000)
printf("%10s PASSED\n", "HASHSET");
else
printf("%10s FAILED\n", "HASHSET");
if (sum10 == 50005000 && sum11 == 50005000)
printf("%10s PASSED\n", "HASHMAP");
else
printf("%10s FAILED\n", "HASHMAP");
if (sum5 == 50005000)
printf("%10s PASSED\n", "HEAP");
else
printf("%10s FAILED\n", "HEAP");
if (sum4 == 50005000)
printf("%10s PASSED\n", "LINKEDLIST");
else
printf("%10s FAILED\n", "LINKEDLIST");
if (sum0 == 50005000)
printf("%10s PASSED\n", "LIST");
else
printf("%10s FAILED\n", "LIST");
if (sum2 == 50005000)
printf("%10s PASSED\n", "QUEUE");
else
printf("%10s FAILED\n", "QUEUE");
if (sum1 == 50005000)
printf("%10s PASSED\n", "STACK");
else
printf("%10s FAILED\n", "STACK");
if (sum7 == 50005000 && sum8 == 50005000)
printf("%10s PASSED\n", "TREEMAP");
else
printf("%10s FAILED\n", "TREEMAP");
if (sum6 == 50005000)
printf("%10s PASSED\n", "TREESET");
else
printf("%10s FAILED\n", "TREESET");
printf("\n\n");
sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0, sum5 = 0, sum6 = 0,
sum7 = 0, sum8 = 0, sum9 = 0, sum10 = 0, sum11 = 0;
FOR_EACH_REV(l, list, int, l, {
sum0 += value;
FOR_EACH_REV(d, deque, d, {
sum3 += d_iter_value(&iter);
})
FOR_EACH_REV(s, stack, int, s, {
sum1 += value;
FOR_EACH_REV(hm, hmap, hm, {
sum10 += hm_iter_key(&iter);
sum11 += hm_iter_value(&iter);
})
FOR_EACH_REV(q, queue, int, q, {
sum2 += value;
FOR_EACH_REV(hs, hset, hs, {
sum9 += hs_iter_value(&iter);
})
FOR_EACH_REV(d, deque, int, d, {
sum3 += value;
FOR_EACH_REV(h, heap, h, {
sum5 += h_iter_value(&iter);
})
FOR_EACH_REV(ll, linked, int, ll, {
sum4 += value;
FOR_EACH_REV(ll, linked, ll, {
sum4 += ll_iter_value(&iter);
})
FOR_EACH_REV(h, heap, int, h, {
sum5 += value;
FOR_EACH_REV(l, list, l, {
sum0 += l_iter_value(&iter);
})
FOR_EACH_REV(ts, tset, int, ts, {
sum6 += value;
FOR_EACH_REV(q, queue, q, {
sum2 += q_iter_value(&iter);
})
FOR_EACH_MAP_REV(tm, tmap, int, int, tm, {
sum7 += key;
sum8 += value;
FOR_EACH_REV(s, stack, s, {
sum1 += s_iter_value(&iter);
})
FOR_EACH_REV(hs, hset, int, hs, {
sum9 += value;
FOR_EACH_REV(tm, tmap, tm, {
sum7 += tm_iter_key(&iter);
sum8 += tm_iter_value(&iter);
})
FOR_EACH_MAP_REV(tm, tmap, int, int, tm, {
sum10 += key;
sum11 += value;
FOR_EACH_REV(ts, tset, ts, {
sum6 += ts_iter_value(&iter);
})
if (sum0 == 50005000)
printf("%10s PASSED\n", "LIST");
if (sum1 == 50005000)
printf("%10s PASSED\n", "STACK");
if (sum2 == 50005000)
printf("%10s PASSED\n", "QUEUE");
printf("-------------------- FOR_EACH_REV --------------------\n");
if (sum3 == 50005000)
printf("%10s PASSED\n", "DEQUE");
if (sum4 == 50005000)
printf("%10s PASSED\n", "LINKEDLIST");
if (sum5 == 50005000)
printf("%10s PASSED\n", "HEAP");
if (sum6 == 50005000)
printf("%10s PASSED\n", "TREESET");
if (sum7 == 50005000 && sum8 == 50005000)
printf("%10s PASSED\n", "TREEMAP");
if (sum9 == 50005000)
printf("%10s PASSED\n", "HASHSET");
else
printf("%10s FAILED\n", "DEQUE");
if (sum10 == 50005000 && sum11 == 50005000)
printf("%10s PASSED\n", "HASHMAP");
else
printf("%10s FAILED\n", "HASHMAP");
if (sum9 == 50005000)
printf("%10s PASSED\n", "HASHSET");
else
printf("%10s FAILED\n", "HASHSET");
if (sum5 == 50005000)
printf("%10s PASSED\n", "HEAP");
else
printf("%10s FAILED\n", "HEAP");
if (sum4 == 50005000)
printf("%10s PASSED\n", "LINKEDLIST");
else
printf("%10s FAILED\n", "LINKEDLIST");
if (sum0 == 50005000)
printf("%10s PASSED\n", "LIST");
else
printf("%10s FAILED\n", "LIST");
if (sum2 == 50005000)
printf("%10s PASSED\n", "QUEUE");
else
printf("%10s FAILED\n", "QUEUE");
if (sum1 == 50005000)
printf("%10s PASSED\n", "STACK");
else
printf("%10s FAILED\n", "STACK");
if (sum7 == 50005000 && sum8 == 50005000)
printf("%10s PASSED\n", "TREEMAP");
else
printf("%10s FAILED\n", "TREEMAP");
if (sum6 == 50005000)
printf("%10s PASSED\n", "TREESET");
else
printf("%10s FAILED\n", "TREESET");
l_free(l);
ll_free(ll);
+106
View File
@@ -0,0 +1,106 @@
#include "../src/macro_collections.h"
#include <stdio.h>
#include <assert.h>
int intcmp(int a, int b)
{
return a - b;
}
size_t inthash(int t)
{
size_t a = t;
a += ~(a << 15);
a ^= (a >> 10);
a += (a << 3);
a ^= (a >> 6);
a += ~(a << 11);
a ^= (a >> 16);
return a;
}
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)
#define ITERATOR_TEST(NAME, PFX, sname, initfunc, insertbody, sumbody, validation1, validation2) \
void NAME##_iterator_test(void) \
{ \
int sum1 = 0; \
double sum2 = 0.0; \
\
sname *coll = initfunc; \
for (int i = 0; i < 10; i++) \
{ \
insertbody; \
} \
\
sname##_iter iter; \
PFX##_iter_init(&iter, coll); \
\
for (int j = 0; j < 4; j++) \
{ \
while (!PFX##_iter_end(&iter)) \
{ \
sumbody; \
PFX##_iter_next(&iter); \
} \
while (!PFX##_iter_start(&iter)) \
{ \
sumbody; \
PFX##_iter_prev(&iter); \
} \
} \
\
for (PFX##_iter_to_start(&iter); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
{ \
sumbody; \
} \
\
for (PFX##_iter_to_end(&iter); !PFX##_iter_start(&iter); PFX##_iter_prev(&iter)) \
{ \
sumbody; \
} \
\
PFX##_free(coll); \
\
if (validation1 && validation2) \
printf("%10s PASSED\n", #NAME); \
else \
printf("%10s FAILED\n", #NAME); \
}
ITERATOR_TEST(DEQUE, d, deque, d_new(20), d_push_front(coll, i), sum1 += d_iter_value(&iter), sum1 == 450, 1)
ITERATOR_TEST(HASHMAP, hm, hmap, hm_new(50, 0.6, intcmp, inthash), hm_insert(coll, i, (double)i / 10.0), sum1 += hm_iter_key(&iter); sum2 += hm_iter_value(&iter), sum1 == 450, sum2 == 45.0)
ITERATOR_TEST(HASHSET, hs, hset, hs_new(50, 0.6, intcmp, inthash), hs_insert(coll, i), sum1 += hs_iter_value(&iter), sum1 == 450, 1)
ITERATOR_TEST(HEAP, h, heap, h_new(20, MaxHeap, intcmp), h_insert(coll, i), sum1 += h_iter_value(&iter), sum1 == 450, 1)
ITERATOR_TEST(LINKEDLIST, ll, linked, ll_new(), ll_push_back(coll, i), sum1 += ll_iter_value(&iter), sum1 == 450, 1)
ITERATOR_TEST(LIST, l, list, l_new(20), l_push_back(coll, i), sum1 += l_iter_value(&iter), sum1 == 450, 1)
ITERATOR_TEST(QUEUE, q, queue, q_new(20), q_enqueue(coll, i), sum1 += q_iter_value(&iter), sum1 == 450, 1)
ITERATOR_TEST(STACK, s, stack, s_new(20), s_push(coll, i), sum1 += s_iter_value(&iter), sum1 == 450, 1)
ITERATOR_TEST(TREEMAP, tm, tmap, tm_new(intcmp), tm_insert(coll, i, (double)i / 10.0), sum1 += tm_iter_key(&iter); sum2 += tm_iter_value(&iter), sum1 == 450, sum2 == 45.0)
ITERATOR_TEST(TREESET, ts, tset, ts_new(intcmp), ts_insert(coll, i), sum1 += ts_iter_value(&iter), sum1 == 450, 1)
int main(void)
{
printf("\n-------------------- ITERATORS --------------------\n");
DEQUE_iterator_test();
HASHMAP_iterator_test();
HASHSET_iterator_test();
HEAP_iterator_test();
LINKEDLIST_iterator_test();
LIST_iterator_test();
QUEUE_iterator_test();
STACK_iterator_test();
TREEMAP_iterator_test();
TREESET_iterator_test();
return 0;
}
-55
View File
@@ -1,55 +0,0 @@
// Checks if the deque iterator can go back and forward in the deque without
// hitting invalid states or a null pointer. Check is done visually.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "../../src/deque.h"
DEQUE_GENERATE(d, deque, static, int)
int main(int argc, char const *argv[])
{
size_t i;
int r;
// Initialize deque and add some elements
deque *d = d_new(10);
for (int i = 0; i < 10; i++)
{
i % 2 == 0 ? d_push_back(d, i) : d_push_front(d, i);
}
// Initialize iterator
deque_iter iter;
d_iter_new(&iter, d);
// Make the iterator go back and forward
for (int j = 0; j < 4; j++)
{
while (d_iter_next(&iter, &r, &i))
printf("C[%2d] = %2d\n", i, r);
printf("\n");
while (d_iter_prev(&iter, &r, &i))
printf("C[%2d] = %2d\n", i, r);
printf("\n\n");
}
for (d_iter_tostart(&iter); !d_iter_end(&iter); /**/)
{
d_iter_next(&iter, &r, &i);
printf("D[%2d] = %2d\n", i, r);
}
printf("\n");
for (d_iter_toend(&iter); !d_iter_start(&iter); /**/)
{
d_iter_prev(&iter, &r, &i);
printf("D[%2d] = %2d\n", i, r);
}
d_free(d);
return 0;
}
-71
View File
@@ -1,71 +0,0 @@
// Checks if the hashmap iterator can go back and forward in the hashmap without
// hitting invalid states or a null pointer. Check is done visually.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "../../src/hashmap.h"
HASHMAP_GENERATE(hm, hmap, static, int, double)
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 intcmp(int a, int b)
{
return a - b;
}
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};
// Initialize hashmap and add some element
hmap *hm = hm_new(50, 0.9, intcmp, inthash);
for (int i = 0; i < 10; i++)
hm_insert(hm, i, varr[i]);
// Initialize iterator
hmap_iter iter;
hm_iter_new(&iter, hm);
// Make the iterator go back and forward
for (int j = 0; j < 4; j++)
{
while (hm_iter_next(&iter, &k, &v, &i))
printf("S[%2d] = { %2d : %2.2lf }\n", i, k, v);
printf("\n");
while (hm_iter_prev(&iter, &k, &v, &i))
printf("S[%2d] = { %2d : %2.2lf }\n", i, k, v);
printf("\n\n");
}
for (hm_iter_tostart(&iter); !hm_iter_end(&iter); /**/)
{
hm_iter_next(&iter, &k, &v, &i);
printf("M[%2d] = { %2d : %2.2lf }\n", i, k, v);
}
printf("\n");
for (hm_iter_toend(&iter); !hm_iter_start(&iter); /**/)
{
hm_iter_prev(&iter, &k, &v, &i);
printf("M[%2d] = { %2d : %2.2lf }\n", i, k, v);
}
hm_free(hm);
return 0;
}
-70
View File
@@ -1,70 +0,0 @@
// Checks if the hash set iterator can go back and forward in the hash set without
// hitting invalid states or a null pointer. Check is done visually.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "../../src/hashset.h"
HASHSET_GENERATE(hs, hash_set, static, int)
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 intcmp(int a, int b)
{
return a - b;
}
int main(int argc, char const *argv[])
{
size_t i;
int r;
// Initialize hash set and add some elements
hash_set *hs = hs_new(10, 0.9, intcmp, inthash);
for (int i = 0; i < 10; i++)
hs_insert(hs, i);
// Initialize iterator
hash_set_iter iter;
hs_iter_new(&iter, hs);
// Make the iterator go back and forward
for (int j = 0; j < 4; j++)
{
while (hs_iter_next(&iter, &r, &i))
printf("C[%2d] = %2d\n", i, r);
printf("\n");
while (hs_iter_prev(&iter, &r, &i))
printf("C[%2d] = %2d\n", i, r);
printf("\n\n");
}
for (hs_iter_tostart(&iter); !hs_iter_end(&iter); /**/)
{
hs_iter_next(&iter, &r, &i);
printf("S[%2d] = %2d\n", i, r);
}
printf("\n");
for (hs_iter_toend(&iter); !hs_iter_start(&iter); /**/)
{
hs_iter_prev(&iter, &r, &i);
printf("S[%2d] = %2d\n", i, r);
}
hs_free(hs);
return 0;
}
-58
View File
@@ -1,58 +0,0 @@
// Checks if the heap iterator can go back and forward in the heap without
// hitting invalid states or a null pointer. Check is done visually.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "../../src/heap.h"
int intcmp(int a, int b)
{
return a - b;
}
HEAP_GENERATE(h, heap, static, int)
int main(int argc, char const *argv[])
{
size_t i;
int r;
// Initialize heap and add some elements
heap *h = h_new(10, MinHeap, intcmp);
for (int i = 9; i >= 0; i--)
h_insert(h, i);
// Initialize iterator
heap_iter iter;
h_iter_new(&iter, h);
// Make the iterator go back and forward
for (int j = 0; j < 4; j++)
{
while (h_iter_next(&iter, &r, &i))
printf("C[%2d] = %2d\n", i, r);
printf("\n");
while (h_iter_prev(&iter, &r, &i))
printf("C[%2d] = %2d\n", i, r);
printf("\n\n");
}
for (h_iter_tostart(&iter); !h_iter_end(&iter); /**/)
{
h_iter_next(&iter, &r, &i);
printf("L[%2d] = %2d\n", i, r);
}
printf("\n");
for (h_iter_toend(&iter); !h_iter_start(&iter); /**/)
{
h_iter_prev(&iter, &r, &i);
printf("L[%2d] = %2d\n", i, r);
}
h_free(h);
return 0;
}
-53
View File
@@ -1,53 +0,0 @@
// Checks if the linked list iterator can go back and forward in the list
// without hitting invalid states or a null pointer. Check is done visually.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "../../src/linkedlist.h"
LINKEDLIST_GENERATE(ll, linked, static, int)
int main(int argc, char const *argv[])
{
size_t i;
int r;
// Initialize linked list and add some elements
linked *ll = ll_new();
for (int i = 0; i < 10; i++)
ll_push_back(ll, i);
// Initialize iterator
linked_iter iter;
ll_iter_new(&iter, ll);
// Make the iterator go back and forward
for (int j = 0; j < 4; j++)
{
while (ll_iter_next(&iter, &r, &i))
printf("C[%2d] = %2d\n", i, r);
printf("\n");
while (ll_iter_prev(&iter, &r, &i))
printf("C[%2d] = %2d\n", i, r);
printf("\n\n");
}
for (ll_iter_tostart(&iter); !ll_iter_end(&iter); /**/)
{
ll_iter_next(&iter, &r, &i);
printf("LL[%2d] = %2d\n", i, r);
}
printf("\n");
for (ll_iter_toend(&iter); !ll_iter_start(&iter); /**/)
{
ll_iter_prev(&iter, &r, &i);
printf("LL[%2d] = %2d\n", i, r);
}
ll_free(ll);
return 0;
}
-53
View File
@@ -1,53 +0,0 @@
// Checks if the list iterator can go back and forward in the list without
// hitting invalid states or a null pointer. Check is done visually.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "../../src/list.h"
LIST_GENERATE(l, list, static, int)
int main(int argc, char const *argv[])
{
size_t i;
int r;
// Initialize list and add some elements
list *l = l_new(10);
for (int i = 0; i < 10; i++)
l_push_back(l, i);
// Initialize iterator
list_iter iter;
l_iter_new(&iter, l);
// Make the iterator go back and forward
for (int j = 0; j < 4; j++)
{
while (l_iter_next(&iter, &r, &i))
printf("C[%2d] = %2d\n", i, r);
printf("\n");
while (l_iter_prev(&iter, &r, &i))
printf("C[%2d] = %2d\n", i, r);
printf("\n\n");
}
for (l_iter_tostart(&iter); !l_iter_end(&iter); /**/)
{
l_iter_next(&iter, &r, &i);
printf("L[%2d] = %2d\n", i, r);
}
printf("\n");
for (l_iter_toend(&iter); !l_iter_start(&iter); /**/)
{
l_iter_prev(&iter, &r, &i);
printf("L[%2d] = %2d\n", i, r);
}
l_free(l);
return 0;
}
+29
View File
@@ -0,0 +1,29 @@
// Tests all containers if they accept a pinter type
// Compile with -Wall -Wextra
#include "../src/macro_collections.h"
#include <stdio.h>
typedef struct my_struct_s
{
int a, b;
} my_struct;
COLLECTION_GENERATE(LIST, PUBLIC, l, list, /* FMOD */, /* K */, my_struct *)
COLLECTION_GENERATE(STACK, PUBLIC, s, stack, /* FMOD */, /* K */, my_struct *)
COLLECTION_GENERATE(QUEUE, PUBLIC, q, queue, /* FMOD */, /* K */, my_struct *)
COLLECTION_GENERATE(DEQUE, PUBLIC, d, deque, /* FMOD */, /* K */, my_struct *)
COLLECTION_GENERATE(LINKEDLIST, PUBLIC, ll, linked, /* FMOD */, /* K */, my_struct *)
COLLECTION_GENERATE(HEAP, PUBLIC, h, heap, /* FMOD */, /* K */, my_struct *)
COLLECTION_GENERATE(TREESET, PUBLIC, ts, tset, /* FMOD */, /* K */, my_struct *)
COLLECTION_GENERATE(TREEMAP, PUBLIC, tm, tmap, /* FMOD */, my_struct *, my_struct *)
COLLECTION_GENERATE(HASHSET, PUBLIC, hs, hset, /* FMOD */, /* K */, my_struct *)
COLLECTION_GENERATE(HASHMAP, PUBLIC, hm, hmap, /* FMOD */, my_struct *, my_struct *)
int main(void)
{
printf("+--------------------------------------------------+\n");
printf("| Pointer Data Type is Working |\n");
printf("+--------------------------------------------------+\n");
return 0;
}