Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b51efa5c45 | ||
|
|
835caa8333 | ||
|
|
645b02708d | ||
|
|
fa2e3d1fcd | ||
|
|
4d4f1256ee | ||
|
|
fe056c1b06 | ||
|
|
ce470f50b5 | ||
|
|
a23dfb0ab0 | ||
|
|
c93f4bac6b | ||
|
|
e1bb3542ee | ||
|
|
a1e0a4edbb | ||
|
|
feaac16804 | ||
|
|
66b6677afa | ||
|
|
f80b17ff82 | ||
|
|
c16ecd886c | ||
|
|
922d8b01b8 | ||
|
|
203516d8cf | ||
|
|
767fc0d7fd | ||
|
|
10e0b4b397 | ||
|
|
22ab6fdb64 | ||
|
|
e08a8f89f3 | ||
|
|
4bebb90cb6 | ||
|
|
f8607e8cdc | ||
|
|
2b8f778c59 | ||
|
|
aec7efd4c3 | ||
|
|
1987152b03 | ||
|
|
649f02665f | ||
|
|
59a1e2a682 | ||
|
|
e85bc72203 | ||
|
|
aa033b0316 | ||
|
|
770ec1c4c7 | ||
|
|
90a6b4ef0d | ||
|
|
63eb525406 | ||
|
|
97f46b3a81 | ||
|
|
424ba074ff | ||
|
|
9209e0d5ec | ||
|
|
546ac80030 | ||
|
|
69eed72838 | ||
|
|
ce4fadff01 | ||
|
|
624d1613f0 | ||
|
|
b85f3d1f81 | ||
|
|
89254ab5db | ||
|
|
e39d60ade9 | ||
|
|
77a7178857 | ||
|
|
85bef64551 | ||
|
|
720e55bfcc | ||
|
|
8e0183a7d7 | ||
|
|
7fa0eafd2c | ||
|
|
e9ee0a88b7 | ||
|
|
ab776dd7f3 | ||
|
|
a9661c3485 | ||
|
|
9680f6a923 | ||
|
|
aa53485d62 | ||
|
|
8112ea6f42 | ||
|
|
7340866da1 | ||
|
|
e4a7b01d3a | ||
|
|
7c82fff41d |
No files matched your search
+2
-2
@@ -1,13 +1,13 @@
|
||||
# clang-format 9.0.0
|
||||
Language: Cpp
|
||||
BasedOnStyle: LLVM
|
||||
AlignEscapedNewlines: Left
|
||||
AlignEscapedNewlines: DontAlign
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
BreakBeforeBraces: Allman
|
||||
BreakStringLiterals: false
|
||||
ColumnLimit: 80
|
||||
ColumnLimit: 120
|
||||
Cpp11BracedListStyle: false
|
||||
ForEachMacros: ["CMC_FOREACH", "CMC_FOREACH_REV"]
|
||||
IndentCaseLabels: true
|
||||
|
||||
@@ -10,8 +10,8 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup Environment
|
||||
run: sudo apt install make valgrind gcc
|
||||
run: sudo apt install make valgrind gcc python
|
||||
- name: Test Suite
|
||||
run: make -C ./tests/main nocov
|
||||
- name: Valgrind Test
|
||||
run: make -C ./tests/main valgrind
|
||||
run: python autogen.py -e -b -r -nf
|
||||
# - name: Valgrind Test
|
||||
# run: make -C ./tests/main valgrind
|
||||
@@ -56,3 +56,6 @@ dkms.conf
|
||||
|
||||
# Experimental folder
|
||||
experimental/
|
||||
|
||||
# Test / Code Coverage build folder
|
||||
build
|
||||
+11
-6
@@ -1,18 +1,23 @@
|
||||
dist: trusty
|
||||
dist: xenial
|
||||
os: linux
|
||||
language: c
|
||||
compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- deadsnakes
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- gcc-7
|
||||
- gcc-9
|
||||
- cmake
|
||||
- python3.8
|
||||
script:
|
||||
- sudo ln -s /usr/bin/gcc-6 /usr/local/bin/gcc
|
||||
- export CC=gcc-7
|
||||
# - make -C ./tests/
|
||||
- make -C ./tests/main/
|
||||
- sudo ln -s /usr/bin/gcc-9 /usr/local/bin/gcc
|
||||
- sudo ln -s /usr/bin/gcov-9 /usr/local/bin/gcov
|
||||
- sudo ln -s /usr/bin/python3.8 /usr/local/bin/python
|
||||
- gcc --version
|
||||
- gcov --version
|
||||
- python --version
|
||||
- python autogen.py -e -b -cv -r -nf
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
@@ -1,7 +1,31 @@
|
||||
# RELEASE.MAJOR.MINOR
|
||||
|
||||
0.24.0
|
||||
A lot of breaking changes, with the library more modular now
|
||||
Comeback of PUBLIC and PRIVATE for the CMC sub-library
|
||||
Callbacks are now optional and can be turned off by defining CMC_NO_CALLBACKS
|
||||
Added EXT library
|
||||
New macro CMC_CAMEL_CASE can change the library's style where the default is snake case
|
||||
Added:
|
||||
./cor/alloc.h
|
||||
./cor/callbacks.h
|
||||
./cor/heap.h
|
||||
Complete rework of tests and code coverage using autogen.py
|
||||
Removed cmc_flags, where now every flag is an enum (CMC_FLAGS_OK, CMC_FLAGS_ERROR, etc)
|
||||
Different include guards
|
||||
New way to generate code using PARAM
|
||||
Code now completely changed by using the CMC_ macro to concatenate tokens
|
||||
Token concatenation with SNAME now uses special macros that allow customization of the suffixes
|
||||
|
||||
0.23.1
|
||||
Added ./cor/bitset.h
|
||||
Added foreach tests
|
||||
Updating foreach macros with the new iterators API
|
||||
Bug fixes for ./cmc/hashmultiset.h
|
||||
|
||||
0.23.0
|
||||
Added ./cmc/bitset.h
|
||||
Added ./cor/flags.h
|
||||
Added ./utl/futils.h
|
||||
Added ./utl/mutex.h
|
||||
Added ./utl/thread.h
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
# This file is useful to format all the source files and header in this library using clang-format
|
||||
|
||||
.PHONY: all cmc dev sac utl tests FORCE
|
||||
|
||||
all: cmc cor dev sac utl tests
|
||||
|
||||
cmc: FORCE
|
||||
clang-format --style=file -i ./src/cmc/*.h
|
||||
|
||||
cor: FORCE
|
||||
clang-format --style=file -i ./src/cor/*.h
|
||||
|
||||
dev: FORCE
|
||||
clang-format --style=file -i ./src/dev/*.h
|
||||
|
||||
sac: FORCE
|
||||
clang-format --style=file -i ./src/sac/*.h
|
||||
|
||||
utl: FORCE
|
||||
clang-format --style=file -i ./src/utl/*.h
|
||||
|
||||
tests: FORCE
|
||||
clang-format --style=file -i ./tests/main/unt/*.c ./tests/main/main.c ./tests/*.c
|
||||
|
||||
FORCE:
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/LeoVen/C-Macro-Collections/blob/master/LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License"/></a>
|
||||
<img src="https://img.shields.io/badge/Version-v0.23.0-orange.svg" alt="Version"/>
|
||||
<img src="https://img.shields.io/badge/Version-v0.24.0-orange.svg" alt="Version"/>
|
||||
<a href="https://travis-ci.org/LeoVen/C-Macro-Collections"><img src="https://travis-ci.org/LeoVen/C-Macro-Collections.svg?branch=master" alt="travis-ci"/></a>
|
||||
<a href="https://codecov.io/gh/LeoVen/C-Macro-Collections"><img src="https://codecov.io/gh/LeoVen/C-Macro-Collections/branch/master/graph/badge.svg" alt="codecov"/></a>
|
||||
<img src="https://github.com/LeoVen/C-Macro-Collections/workflows/Test%20Suit/badge.svg?branch=master" alt="test_suit"/>
|
||||
@@ -21,13 +21,133 @@
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* Project Structure
|
||||
* Available Collections
|
||||
* Features
|
||||
* Overall To-Do
|
||||
* Design Decisions
|
||||
* What to use
|
||||
* How to use
|
||||
* [Installation](#installation)
|
||||
* [Contributing](#contributing)
|
||||
* [Usage](#usage)
|
||||
* [Features](#features)
|
||||
* [Project Structure](#project-structure)
|
||||
* [Available Collections](#available-collections)
|
||||
* [Other Features](#other-features)
|
||||
* [Design Decisions](#design-decisions)
|
||||
* [What to use](#what-to-use)
|
||||
* [Code Review](#code-review)
|
||||
|
||||
## Installation
|
||||
|
||||
No installation is required. The entire library is made of header files and can be directly included into your project.
|
||||
|
||||
## Contributing
|
||||
|
||||
There is a lot to be done. You can check the `TODO` file in the root of the repository or the issues in the github page. Also, tests and documentation are in constant development. Also check out the `STATUS` file for the status on the development of the library.
|
||||
|
||||
## Usage
|
||||
|
||||
The header `macro_collections.h` includes every feature from the library and comes with higher level APIs that help you generate collections from specific sub-libraries with specific extensions.
|
||||
|
||||
Below is a minimal example that makes use of some core functionalities. And a lot of explanation too!
|
||||
|
||||
```c
|
||||
// This is the master header. This will include every feature of the library.
|
||||
// This comes with many helper macros (high level API) and utility functions.
|
||||
#include "macro_collections.h"
|
||||
|
||||
// A PARAM is a standard way to pass required parameters to the lower level API.
|
||||
// It is a tuple of form (PFX, SNAME, SIZE, K, V). In this case, not all of them
|
||||
// are used, so we can leave them empty. We are creating a list of value int.
|
||||
#define MY_LIST_PARAMS (intl, int_list, , , int)
|
||||
|
||||
// High level API. Generate a LIST from the CMC library with the STR extension
|
||||
// using our previously defined PARAMs. Every collections has a CORE part that
|
||||
// needs to be generated first. Then, we can add other parts after. This macro
|
||||
// does all of that for us. The STR part will provide us with a function that
|
||||
// will be used later.
|
||||
C_MACRO_COLLECTIONS_GEN(CMC, LIST, MY_LIST_PARAMS, (STR))
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// Our list type is defined by SNAME and all functions are prefixed by PFX
|
||||
// (PFX can also be thought as the function's namespace). Also, nodes,
|
||||
// entries, iterators and other structures are prefixed by SNAME. So PFX is
|
||||
// for functions and SNAME is for structs, where the main one is simply
|
||||
// 'struct SNAME'.
|
||||
// To initialize a list we need to pass in an initial capacity and something
|
||||
// that is called a function table for the V type.
|
||||
// This function table is a struct with methods that will extract some
|
||||
// (sometimes) necessary behaviour from your custom data type. Things like
|
||||
// hash, comparison and printing. A list doesn't require any of these
|
||||
// functions. That is, the CORE module doesn't use any of them.
|
||||
// But since we are using the STR module, we will need to define the 'str'
|
||||
// function. luckily, for the 'int' type, the library already provides such
|
||||
// function (cmc_i32_str), provided by the /utl/futils.h header file.
|
||||
struct int_list *list = intl_new(32, &(struct int_list_fval){ .str = cmc_i32_str, NULL });
|
||||
|
||||
// Check if the list was successfully initialized. It could fail if the
|
||||
// initial capacity is too big or if 'struct int_list_fval *' is NULL,
|
||||
// because every data structure must have a valid function table.
|
||||
if (!list)
|
||||
return 1;
|
||||
|
||||
// Add some items to the list. The CMC data structures are all dynamically
|
||||
// sized. So there can be as many items as you want as long as you have
|
||||
// enough memory.
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
// Try to add an element to the list. If it fails you can check what
|
||||
// caused it by getting its flag.
|
||||
if (!intl_push_back(list, i))
|
||||
{
|
||||
enum cmc_flags flag = intl_flag(list);
|
||||
// Use cmc_flags_to_str to map the enum error to a string.
|
||||
fprintf(stderr, "%s : push_back failed\n", cmc_flags_to_str[flag]);
|
||||
}
|
||||
}
|
||||
|
||||
// Now we will use the STR module, the _print() function. This is where the
|
||||
// '.str' from the function table comes into play. If we haven't defined it,
|
||||
// the program would've crashed. We also need to define to which file we
|
||||
// will be printing the list's content. In this case, the terminal. Also,
|
||||
// some strings need to be defined. They will be printed: before all elements,
|
||||
// between each one, and after all elements. This is very usefull and can
|
||||
// print a data structure very nicely.
|
||||
intl_print(list, stdout, "[ ", ", ", " ]\n");
|
||||
|
||||
// You should see a nicely printed list in your terminal.
|
||||
|
||||
// Free all of its resources
|
||||
intl_free(list);
|
||||
}
|
||||
```
|
||||
|
||||
Now all you have to do is to compile the source code with `-I /path/to/library/src`. There is no required installation or pre-compilation.
|
||||
|
||||
## Features
|
||||
|
||||
The C Macro Collections library is organized into many other sub-libraries. The following table is a quick overview.
|
||||
|
||||
| Library | Name | Description |
|
||||
| :-----: | -------------------------------- | ------------------------------------------------------------------------------------------- |
|
||||
| CMC | Macro Collections | The main library with dynamically-sized collections |
|
||||
| COR | Core | Core functionalities used by more than one collection, usually from different sub-libraries |
|
||||
| EXT | Extensions | Extension to collections from CMC, SAC and TSC libraries |
|
||||
| INT | Integrations | Macros that facilitate the creation of code that involves more than one type of collection |
|
||||
| SAC | Statically Allocated Collections | Collections with a fixed sized array that don't use any heap allocation |
|
||||
| TSC | Thread-Safe Collections | Collections that allow multiple operations from multiple threads |
|
||||
| UTL | Utilities | General utilities |
|
||||
|
||||
Every macro that generates code for a certain collection can be found with the following template. Some exceptions exist as certain collections don't have or can't have some features. One big example is the `UTL` library, which does not follow this pattern.
|
||||
|
||||
```
|
||||
macro_name := CMC_[ lib ]_[ collection ]_[ part ]_[ file ]
|
||||
|
||||
lib := CMC | COR | DEV | EXT | INT | SAC | TSC
|
||||
collection := BITSET | DEQUE | HASHBIDIMAP | ... | TREEMULTISET | TREESET
|
||||
part := CORE | ITER | INIT | ... | SETF | NODE
|
||||
file := HEADER | SOURCE
|
||||
```
|
||||
|
||||
__Some `collection`s might not be present in a certain `lib`. Check the documentation.__
|
||||
|
||||
Every macro is suffixed by `CMC` and each section is separated by an underscore (`_`). The first section is the library (`lib`). The second is the collection name in all uppercase. Then the `part` (or which module) that you wish to generate. And last, if it is code that should belong to a header file or code that should belong to a source file.
|
||||
|
||||
## Project Structure
|
||||
|
||||
@@ -38,53 +158,46 @@
|
||||
* __src__ - All headers part of the C Macro Collections Library
|
||||
* __cmc__ - The main C Macro Collections Library
|
||||
* __cor__ - Core includes in the C Macro Collections Library
|
||||
* __dev__ - The main C Macro Collections Library for development (containing logging)
|
||||
* __sac__ - Statically Allocated Collections
|
||||
* __utl__ - Utility like ForEach macros, logging, etc
|
||||
* __ext__ - Extensions to the CMC, SAC and TSC collections
|
||||
* __int__ - Integrations between Collections
|
||||
* __sac__ - Statically Allocated Collections
|
||||
* __tsc__ - Thread Safe Collections
|
||||
* __utl__ - Utilities like ForEach macros, logging, etc
|
||||
* __macro\_collections.h__ - Master header containing all collections and utilities
|
||||
* __tests__ - Where all tests are hosted
|
||||
|
||||
## Available Collections
|
||||
|
||||
* Linear Collections
|
||||
* List, LinkedList, Deque, Stack, Queue, SortedList
|
||||
* Sets
|
||||
* HashSet, TreeSet, HashMultiSet
|
||||
* Maps
|
||||
* HashMap, TreeMap, HashMultiMap
|
||||
* Bidirectional Maps
|
||||
* HashBidiMap
|
||||
* Heaps
|
||||
* Heap, IntervalHeap
|
||||
* WIP
|
||||
* BitSet, Matrix, TreeBidiMap, TreeMultiMap, TreeMultiSet
|
||||
Check out the STATUS file at the root of the project for more information.
|
||||
|
||||
__The following table is an overview of all the currently available or upcoming data structures__:
|
||||
|
||||
| Collection <img width=250/> | Abstract Data Type <img width=250/> | Data Structure <img width=250/> | Details |
|
||||
| :--------------------------------: | :---------------------------------: | :-----------------------------: | :-----------------------------------: |
|
||||
| BitSet <br> _bitset.h_ | Set | Dynamic Array | A set of bits that can be individually modified and queried, each identified by a bit index |
|
||||
| Deque <br> _deque.h_ | Double-Ended Queue | Dynamic Circular Array | A circular array that allows `push` and `pop` on both ends (only) at constant time |
|
||||
| HashBidiMap <br> _hashbidimap.h_ | Bidirectional Map | Two Hashtables | A bijection between two sets of unique keys and unique values `K <-> V` using two hashtables |
|
||||
| HashMap <br> _hashmap.h_ | Map | Flat Hashtable | A unique set of keys associated with a value `K -> V` with constant time look up using a hashtable with open addressing and robin hood hashing |
|
||||
| HashMultiMap <br> _hashmultimap.h_ | Multimap | Hashtable | A mapping of multiple keys with one node per key using a hashtable with separate chaining |
|
||||
| HashMultiSet <br> _hashmultiset.h_ | Multiset | Flat Hashtable | A mapping of a value and its multiplicity using a hashtable with open addressing and robin hood hashing |
|
||||
| HashSet <br> _hashset.h_ | Set | Flat Hashtable | A unique set of values with constant time look up using a hashtable with open addressing and robin hood hashing |
|
||||
| Heap <br> _heap.h_ | Priority Queue | Dynamic Array | A binary heap as a dynamic array as an implicit data structure |
|
||||
| IntervalHeap <br> _intervalheap.h_ | Double-Ended Priority Queue | Custom Dynamic Array | A dynamic array of nodes, each hosting one value from the MinHeap and one from the MaxHeap |
|
||||
| LinkedList <br> _linkedlist.h_ | List | Doubly-Linked List | A default doubly-linked list |
|
||||
| List <br> _list.h_ | List | Dynamic Array | A dynamic array with `push` and `pop` anywhere on the array |
|
||||
| Matrix <br> _WIP_ | Regular Matrix | Dynamic Array of Dynamic Arrays | A regular matrix with arbitrary rows and columns |
|
||||
| Queue <br> _queue.h_ | FIFO | Dynamic Circular Array | A queue using a circular array with `enqueue` at the `back` index and `dequeue` at the `front` index |
|
||||
| SortedList <br> _sortedlist.h_ | Sorted List | Sorted Dynamic Array | A lazily sorted dynamic array that is sorted only when necessary |
|
||||
| Stack <br> _stack.h_ | FILO | Dynamic Array | A stack with push and pop at the end of a dynamic array |
|
||||
| TreeBidiMap <br> _WIP_ | Sorted Bidirectional Map | Two AVL Trees | A sorted bijection between two sets of unique keys and unique values `K <-> V` using two AVL trees |
|
||||
| TreeMap <br> _treemap.h_ | Sorted Map | AVL Tree | A unique set of keys associated with a value `K -> V` using an AVL tree with `log(n)` look up and sorted iteration |
|
||||
| TreeMultiMap <br> _WIP_ | Sorted Multimap | AVL Tree | A sorted mapping of multiple keys with one node per key using an AVL Tree of linked-lists |
|
||||
| TreeMultiSet <br> _WIP_ | Sorted Multiset | AVL Tree | A sorted mapping of a value and its multiplicity using an AVL tree |
|
||||
| TreeSet <br> _treeset.h_ | Sorted Set | AVL Tree | A unique set of keys using an AVL tree with `log(n)` look up and sorted iteration |
|
||||
| Collection <img width=250/> | Abstract Data Type <img width=250/> | Data Structure <img width=250/> | Details |
|
||||
| :--------------------------------: | :---------------------------------: | :-----------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------: |
|
||||
| BitSet <br> _bitset.h_ | Set | Dynamic Array | A set of bits that can be individually modified and queried, each identified by a bit index |
|
||||
| Deque <br> _deque.h_ | Double-Ended Queue | Dynamic Circular Array | A circular array that allows `push` and `pop` on both ends (only) at constant time |
|
||||
| HashBidiMap <br> _hashbidimap.h_ | Bidirectional Map | Two Hashtables | A bijection between two sets of unique keys and unique values `K <-> V` using two hashtables |
|
||||
| HashMap <br> _hashmap.h_ | Map | Flat Hashtable | A unique set of keys associated with a value `K -> V` with constant time look up using a hashtable with open addressing and robin hood hashing |
|
||||
| HashMultiMap <br> _hashmultimap.h_ | Multimap | Hashtable | A mapping of multiple keys with one node per key using a hashtable with separate chaining |
|
||||
| HashMultiSet <br> _hashmultiset.h_ | Multiset | Flat Hashtable | A mapping of a value and its multiplicity using a hashtable with open addressing and robin hood hashing |
|
||||
| HashSet <br> _hashset.h_ | Set | Flat Hashtable | A unique set of values with constant time look up using a hashtable with open addressing and robin hood hashing |
|
||||
| Heap <br> _heap.h_ | Priority Queue | Dynamic Array | A binary heap as a dynamic array as an implicit data structure |
|
||||
| IntervalHeap <br> _intervalheap.h_ | Double-Ended Priority Queue | Custom Dynamic Array | A dynamic array of nodes, each hosting one value from the MinHeap and one from the MaxHeap |
|
||||
| LinkedList <br> _linkedlist.h_ | List | Doubly-Linked List | A default doubly-linked list |
|
||||
| List <br> _list.h_ | List | Dynamic Array | A dynamic array with `push` and `pop` anywhere on the array |
|
||||
| Queue <br> _queue.h_ | FIFO | Dynamic Circular Array | A queue using a circular array with `enqueue` at the `back` index and `dequeue` at the `front` index |
|
||||
| SkipList <br> _WIP_ | Sorted List | Skip List | A sorted Linked List with average O(log n) search, insertion and deletion complexity |
|
||||
| SortedList <br> _sortedlist.h_ | Sorted List | Sorted Dynamic Array | A lazily sorted dynamic array that is sorted only when necessary |
|
||||
| Stack <br> _stack.h_ | FILO | Dynamic Array | A stack with push and pop at the end of a dynamic array |
|
||||
| TreeBidiMap <br> _WIP_ | Sorted Bidirectional Map | Two AVL Trees | A sorted bijection between two sets of unique keys and unique values `K <-> V` using two AVL trees |
|
||||
| TreeMap <br> _treemap.h_ | Sorted Map | AVL Tree | A unique set of keys associated with a value `K -> V` using an AVL tree with `log(n)` look up and sorted iteration |
|
||||
| TreeMultiMap <br> _WIP_ | Sorted Multimap | AVL Tree | A sorted mapping of multiple keys with one node per key using an AVL Tree of linked-lists |
|
||||
| TreeMultiSet <br> _WIP_ | Sorted Multiset | AVL Tree | A sorted mapping of a value and its multiplicity using an AVL tree |
|
||||
| TreeSet <br> _treeset.h_ | Sorted Set | AVL Tree | A unique set of keys using an AVL tree with `log(n)` look up and sorted iteration |
|
||||
|
||||
## Features
|
||||
## Other Features
|
||||
|
||||
These are some features within the library that are implemented by all collections.
|
||||
|
||||
### Two-way iterators
|
||||
|
||||
@@ -136,8 +249,8 @@ A priority function works much like the comparator function except that it compa
|
||||
|
||||
The following table shows which functions are required, optional or never used for each Collection:
|
||||
|
||||
| Collection | CMP | CPY | STR | FREE | HASH | PRI |
|
||||
| ---------- | :-: | :-: | :-: | :--: | :--: | :-: |
|
||||
| Collection | CMP | CPY | STR | FREE | HASH | PRI |
|
||||
| ------------ | :------------------------------------------------------: | :------------------------------------------------------: | :------------------------------------------------------: | :------------------------------------------------------: | :------------------------------------------------------: | :------------------------------------------------------: |
|
||||
| Deque |  |  |  |  |  |  |
|
||||
| HashMap |  |  |  |  |  |  |
|
||||
| HashBidiMap |  |  |  |  |  |  |
|
||||
@@ -154,23 +267,13 @@ The following table shows which functions are required, optional or never used f
|
||||
| TreeMap |  |  |  |  |  |  |
|
||||
| TreeSet |  |  |  |  |  |  |
|
||||
|
||||
| Color | Label |
|
||||
| :---: | ----- |
|
||||
|  | Required for basic functionality. |
|
||||
|  | Required for specific functions. |
|
||||
| Color | Label |
|
||||
| :------------------------------------------------------: | ----------------------------------------- |
|
||||
|  | Required for basic functionality. |
|
||||
|  | Required for specific functions. |
|
||||
|  | Required for non-core specific functions. |
|
||||
|  | Optional. |
|
||||
|  | Not Used. |
|
||||
|
||||
## Overall To-Do
|
||||
|
||||
In the long term, these are the steps left for the completion of this library:
|
||||
|
||||
* Complete the implementation of all the functions in the scope of the TODO file for the main collections;
|
||||
* Reorganize and complete all tests for the `cmc` collections;
|
||||
* Make an exact copy of all collections to `dev` with many logging utility, for them to be used under development;
|
||||
* Port all of these collections to be statically allocated and be part of the `sac` library;
|
||||
* Complete all tests for `sac`.
|
||||
|  | Optional. |
|
||||
|  | Not Used. |
|
||||
|
||||
## Design Decisions
|
||||
|
||||
@@ -198,6 +301,8 @@ Modifying a collection will possibly invalidate all iterators currently initiali
|
||||
|
||||
## What to use
|
||||
|
||||
(Outdated)
|
||||
|
||||
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;
|
||||
@@ -210,62 +315,14 @@ The following table shows how each collection is implemented and how well they d
|
||||

|
||||

|
||||
|
||||
## How to use
|
||||
## Code Review
|
||||
|
||||
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 the entire C-Macro-Collections library.
|
||||
Check out some code reviews that covers some parts the project. Most of them were posted a long time ago and are probably outdated.
|
||||
|
||||
### Macros
|
||||
|
||||
> Note here that `SNAME` represents the uppercase name of the collection.
|
||||
|
||||
Every collection is separated by two parts:
|
||||
|
||||
* `HEADER` - Contains all struct definitions and function definitions.
|
||||
* `SOURCE` - Contains all function implementations.
|
||||
|
||||
All collections have three main macros:
|
||||
|
||||
* `CMC_GENERATE_SNAME` - Generates `CMC_GENERATE_SNAME_HEADER` and `CMC_GENERATE_SNAME_SOURCE`.
|
||||
|
||||
Or you can generate each part individually:
|
||||
|
||||
* `CMC_GENERATE_SNAME_HEADER` - Generates all struct definitions and function definitions.
|
||||
* `CMC_GENERATE_SNAME_SOURCE` - Generates all function implementations.
|
||||
|
||||
### Parameters
|
||||
|
||||
When including `macro_collections.h` in your source code you gain access to a macro called `CMC_COLLECTION_GENERATE` with the following parameters:
|
||||
|
||||
* __C__ - Container name in uppercase (*BIDIMAP*, *DEQUE*, *HASHMAP*, *HASHSET*, *HEAP*, *INTERVALHEAP*, *LINKEDLIST*, *LIST*, *MULTIMAP*, *MULTISET*, *QUEUE*, *SORTEDLIST*, *STACK*, *TREEMAP*, *TREESET*).
|
||||
* __PFX__ - Functions prefix or namespace.
|
||||
* __SNAME__ - Structure name (`struct SNAME`).
|
||||
* __K__ - Key type. Only used in *HASHMAP*, *TREEMAP*, *MULTIMAP* and *BIDIMAP*; ignored by others.
|
||||
* __V__ - Value type. Primary type for most collections, or value to be mapped by *HASHMAP*, *TREEMAP*, *MULTIMAP* and *BIDIMAP*.
|
||||
|
||||
**In fact, all macros follow this pattern.** So whenever you see a macro with a bunch of parameters and you don't know what they are, you can check out the above list.
|
||||
|
||||
### For Each
|
||||
|
||||
There are 2 for-each macros:
|
||||
|
||||
* `CMC_FOREACH` - Starts at the start of the collection towards the end.
|
||||
* `CMC_FOREACH_REV` - Starts at the end of the collection towards the start.
|
||||
|
||||
* __PFX__ - Functions prefix or namespace.
|
||||
* __SNAME__ - Structure name.
|
||||
* __TARGET__ - The variable name of the collection you wish to iterate over.
|
||||
* __ITERNAME__ - Iterator variable name.
|
||||
|
||||
For `CMC_FOREACH` and `CMC_FOREACH_REV` you will be able to name the iterator variable through the __ITERNAME__ parameter.
|
||||
|
||||
<hr>
|
||||
|
||||
Check out some code reviews that covers some parts the project:
|
||||
|
||||
| About | Link |
|
||||
|-------|--------|
|
||||
| Unit Test *./utl/test.h* | [](http://codereview.stackexchange.com/q/222954/178948) |
|
||||
| About | Link |
|
||||
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Unit Test *./utl/test.h* | [](http://codereview.stackexchange.com/q/222954/178948) |
|
||||
| Interval Heap *./cmc/intervalheap.h* | [](http://codereview.stackexchange.com/q/223595/178948) |
|
||||
| Hash Set *./cmc/hashset.h* | [](http://codereview.stackexchange.com/q/217333/178948) |
|
||||
| Linked List *./cmc/linkedlist.h* | [](http://codereview.stackexchange.com/q/216737/178948) |
|
||||
| Others | [](http://codereview.stackexchange.com/q/213553/178948) |
|
||||
| Hash Set *./cmc/hashset.h* | [](http://codereview.stackexchange.com/q/217333/178948) |
|
||||
| Linked List *./cmc/linkedlist.h* | [](http://codereview.stackexchange.com/q/216737/178948) |
|
||||
| Others | [](http://codereview.stackexchange.com/q/213553/178948) |
|
||||
@@ -0,0 +1,72 @@
|
||||
Approximate completion of the library
|
||||
|
||||
[ 99 ][ 99 ][ 99 ] %
|
||||
[source][tests][docs]
|
||||
|
||||
## - Finished
|
||||
|
||||
[30][15][01] Library
|
||||
|
||||
[91][45][01] CMC
|
||||
[40][40][05] BitSet
|
||||
[##][##][10] Deque
|
||||
[80][70][00] HashBidiMap
|
||||
[##][##][00] HashMap
|
||||
[##][20][00] HashMultiMap
|
||||
[##][20][00] HashMultiSet
|
||||
[##][40][00] HashSet
|
||||
[##][30][00] Heap
|
||||
[##][40][00] IntervalHeap
|
||||
[90][20][00] LinkedList
|
||||
[90][30][00] List
|
||||
[##][60][00] Queue
|
||||
[00][00][00] SkipList
|
||||
[80][20][00] SortedList
|
||||
[95][90][00] Stack
|
||||
[00][00][00] TreeBidiMap
|
||||
[95][20][00] TreeMap
|
||||
[00][00][00] TreeMultiMap
|
||||
[00][00][00] TreeMultiSet
|
||||
[95][20][00] TreeSet
|
||||
[00][00][00] SAC
|
||||
[00][00][00] BitSet
|
||||
[00][00][00] Deque
|
||||
[00][00][00] HashBidiMap
|
||||
[00][00][00] HashMap
|
||||
[00][00][00] HashMultiMap
|
||||
[00][00][00] HashMultiSet
|
||||
[00][00][00] HashSet
|
||||
[00][00][00] Heap
|
||||
[00][00][00] IntervalHeap
|
||||
[00][00][00] LinkedList
|
||||
[00][00][00] List
|
||||
[00][00][00] Queue
|
||||
[00][00][00] SkipList
|
||||
[00][00][00] SortedList
|
||||
[00][00][00] Stack
|
||||
[00][00][00] TreeBidiMap
|
||||
[00][00][00] TreeMap
|
||||
[00][00][00] TreeMultiMap
|
||||
[00][00][00] TreeMultiSet
|
||||
[00][00][00] TreeSet
|
||||
[00][00][00] TSC
|
||||
[00][00][00] BitSet
|
||||
[00][00][00] Deque
|
||||
[00][00][00] HashBidiMap
|
||||
[00][00][00] HashMap
|
||||
[00][00][00] HashMultiMap
|
||||
[00][00][00] HashMultiSet
|
||||
[00][00][00] HashSet
|
||||
[00][00][00] Heap
|
||||
[00][00][00] IntervalHeap
|
||||
[00][00][00] LinkedList
|
||||
[00][00][00] List
|
||||
[00][00][00] Queue
|
||||
[00][00][00] SkipList
|
||||
[00][00][00] SortedList
|
||||
[00][00][00] Stack
|
||||
[00][00][00] TreeBidiMap
|
||||
[00][00][00] TreeMap
|
||||
[00][00][00] TreeMultiMap
|
||||
[00][00][00] TreeMultiSet
|
||||
[00][00][00] TreeSet
|
||||
@@ -1,19 +1,57 @@
|
||||
TODO
|
||||
|
||||
Patch - Changes that can be released by a patch version
|
||||
Minor - Changes that require a bit more time than a simple patch
|
||||
Major - 1.0.0 version or breaking changes
|
||||
|
||||
The library follows https://semver.org/
|
||||
Check out CHANGELOG
|
||||
|
||||
[/] - In Progress
|
||||
[X] - Finished
|
||||
|
||||
#!! High Priority ----------------------------------------------------------------------------------
|
||||
|
||||
[/] Tests
|
||||
[/] Documentation
|
||||
#!! Next Patch -----------------------------------------------------------------
|
||||
|
||||
#!! Medium Priority --------------------------------------------------------------------------------
|
||||
[ ] Fix BitSet, using capacity vs. counter
|
||||
[ ] #12 - Fix the collections that depend on ITER
|
||||
|
||||
|
||||
#!! Major ----------------------------------------------------------------------
|
||||
|
||||
[ ] Stabilize the library
|
||||
[ ] Add INT library
|
||||
[ ] Add SAC library
|
||||
[ ] Add TSC library
|
||||
[ ] Separate inner Data Structure implementation from the Collection's one
|
||||
[ ] CMC_NAMES - Full customization of function names (see CMC_CAMEL_CASE)
|
||||
[\] Tests
|
||||
[\] Documentation
|
||||
|
||||
|
||||
#!! Minor ----------------------------------------------------------------------
|
||||
|
||||
[ ] #13 - Properly implement HashBidiMap iterator
|
||||
[ ] #10 - Fix Benchmarks and Examples
|
||||
[ ] More SortedList functions
|
||||
[ ] BidiMap's _is_mapping() to check if a mapping K <=> V exists
|
||||
[ ] New asserts - _array_int(), _array_not_in() and str
|
||||
[ ] Add Stack's _peek() and _top() (get by value, get by pointer)
|
||||
[ ] CMC_TIMED for timed blocks
|
||||
[ ] _iter_at() iterator
|
||||
|
||||
|
||||
#!! Patch ----------------------------------------------------------------------
|
||||
|
||||
[ ] MultiSets replace existing value with the new added one
|
||||
[ ] Fix PUBLIC and PRIVATE incompatibility between CMC and EXT
|
||||
|
||||
|
||||
#!! Considerations -------------------------------------------------------------
|
||||
|
||||
[ ] rand.h utility
|
||||
[ ] Redo `while (true)` in hashtables' _insert()
|
||||
[ ] Add to_array and from_array functions
|
||||
|
||||
#!! Being Considered -------------------------------------------------------------------------------
|
||||
|
||||
[ ] Serialization
|
||||
[ ] save {all}
|
||||
[ ] load {all}
|
||||
@@ -22,12 +60,14 @@ TODO
|
||||
[ ] Zip Iterators
|
||||
[ ] Consumer Iterators
|
||||
|
||||
#!! Optimizations ----------------------------------------------------------------------------------
|
||||
|
||||
[ ] Use binary search to find optimum hashtable prime size inside impl_calculate_size
|
||||
[ ] Optimize certain loops that use iterators that can simply use a normal loop
|
||||
#!! Optimizations --------------------------------------------------------------
|
||||
|
||||
#!! Done -------------------------------------------------------------------------------------------
|
||||
[ ] Use binary search to find optimum hashtable prime size inside
|
||||
impl_calculate_size
|
||||
|
||||
|
||||
#!! Done -----------------------------------------------------------------------
|
||||
|
||||
[X] Remove PUBLIC and PRIVATE
|
||||
[X] Utility
|
||||
@@ -62,3 +102,5 @@ TODO
|
||||
[X] Callback utility
|
||||
on_create, on_read, on_update, on_delete, on_resize
|
||||
[X] Replace IntervalHeap node by a simple buffer of two pointers (V (*buffer)[2])
|
||||
[X] PUBLIC and PRIVATE is back (opaque data structures)
|
||||
[X] Add EXT library
|
||||
+399
-68
@@ -1,101 +1,432 @@
|
||||
# A script that automatically expands the macros for code coverage
|
||||
# A script that automatically generates code for code coverage, updates tests
|
||||
# and Makefiles, and creates necessary directories
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from typing import List, Text
|
||||
|
||||
# Compiler settings
|
||||
# Config Script Configuration
|
||||
# Directories Names for directories
|
||||
# Output Where the outputted code is to be put
|
||||
# Build Where the build objects are to be located
|
||||
# Compiler Compiler Configurations
|
||||
# Compilation Tests, code coverage and flags
|
||||
# Macro Expansion Configuration for the code expansion
|
||||
# Collections All collections
|
||||
#
|
||||
# Variables marked as const are to not be modified
|
||||
|
||||
# Directories
|
||||
|
||||
# Output directory
|
||||
# In this directory it is assumed that the following files and directories are
|
||||
# included: main.c, unt folder
|
||||
OUTPUT_DIR = './tests'
|
||||
# All libraries
|
||||
ALL_LIBS = ['CMC']
|
||||
# Directory mapping
|
||||
DIR_MAP = {'HEADER': 'include', 'SOURCE': 'src'}
|
||||
# File extension mapping
|
||||
EXT_MAP = {'HEADER': 'h', 'SOURCE': 'c'}
|
||||
# Where compilation objects will be outputted
|
||||
BUILD_DIR = f'{OUTPUT_DIR}/build'
|
||||
# const
|
||||
INCLUDE_DIR = f"{OUTPUT_DIR}/{DIR_MAP['HEADER']}"
|
||||
# const
|
||||
SRC_DIR = f"{OUTPUT_DIR}/{DIR_MAP['SOURCE']}"
|
||||
# Where object files .o go
|
||||
OBJ_DIR = BUILD_DIR
|
||||
# The name of the main test executable
|
||||
TEST_EXE = f'{OUTPUT_DIR}/main.exe'
|
||||
# Where .gcov files should go
|
||||
GCOV_DIR = f'{BUILD_DIR}/gcov'
|
||||
|
||||
# Compiler
|
||||
|
||||
# Compilation
|
||||
CC = 'gcc'
|
||||
INCLUDE = '-I ./src'
|
||||
# Compilation Flags
|
||||
CFLAGS = ['-Wall', '-Werror']
|
||||
# Link flags
|
||||
LFLAGS = []
|
||||
# Coverage Flags
|
||||
CVFLAGS = ['--coverage', '-O0']
|
||||
# gcov flags
|
||||
GCOV_FLAGS = []
|
||||
# Include to the main Library
|
||||
# const
|
||||
INCLUDE = ['-I', './src']
|
||||
# Include to the test file headers
|
||||
# const
|
||||
TINCLUDE = ['-I', f'{INCLUDE_DIR}']
|
||||
|
||||
# Macro expansion
|
||||
|
||||
# -E Only preprocessor
|
||||
# -P No linemarkers
|
||||
# -C Keep comments, except those inside macros (for UNIQUE_FLAG)
|
||||
FLAGS = '-E -P -C'
|
||||
|
||||
# Used to delimiter where the actual code starts and ends
|
||||
# Used by regex
|
||||
# Needs to be a valid C comment
|
||||
# const
|
||||
EXPAND_FLAGS = '-E -P -C'
|
||||
# Used to delimiter where the actual code starts and ends. Used by regex.
|
||||
# Needs to be a valid C comment.
|
||||
UNIQUE_FLAG = '// C_MACRO_COLLECTIONS_CODE'
|
||||
|
||||
# Temporary file used to expand the macros
|
||||
TMP_FILE = './main.c'
|
||||
|
||||
# Output directory
|
||||
OUTPUT_DIR = './tests/main/src'
|
||||
# Just a realy helpfull overview
|
||||
CONFIG = f'''Directory Settings
|
||||
OUTPUT_DIR = {OUTPUT_DIR}
|
||||
ALL_LIBS = {ALL_LIBS}
|
||||
DIR_MAP = {DIR_MAP}
|
||||
EXT_MAP = {EXT_MAP}
|
||||
BUILD_DIR = {BUILD_DIR}
|
||||
INCLUDE_DIR = {INCLUDE_DIR}
|
||||
SRC_DIR = {SRC_DIR}
|
||||
OBJ_DIR = {OBJ_DIR}
|
||||
GCOV_DIR = {GCOV_DIR}
|
||||
Compiler Settings
|
||||
CC = {CC}
|
||||
CFLAGS = {CFLAGS}
|
||||
LFLAGS = {LFLAGS}
|
||||
CVFLAGS = {CVFLAGS}
|
||||
GCOV_FLAGS = {GCOV_FLAGS}
|
||||
INCLUDE = {INCLUDE}
|
||||
TINCLUDE = {TINCLUDE}
|
||||
Macro Expansion
|
||||
EXPAND_FLAGS = {EXPAND_FLAGS}
|
||||
UNIQUE_FLAG = {UNIQUE_FLAG}
|
||||
TMP_FILE = {TMP_FILE}'''
|
||||
|
||||
collections = [
|
||||
# type, header, pfx, sname, key, val
|
||||
{'t': 'BITSET', 'h': '"cmc/bitset.h"', 'pfx': 'bs', 'sname': 'bitset', 'key': '', 'val': '' },
|
||||
{'t': 'DEQUE', 'h': '"cmc/deque.h"', 'pfx': 'd', 'sname': 'deque', 'key': '', 'val': 'size_t'},
|
||||
{'t': 'HASHBIDIMAP', 'h': '"cmc/hashbidimap.h"', 'pfx': 'hbm', 'sname': 'hashbidimap', 'key': 'size_t', 'val': 'size_t'},
|
||||
{'t': 'HASHMAP', 'h': '"cmc/hashmap.h"', 'pfx': 'hm', 'sname': 'hashmap', 'key': 'size_t', 'val': 'size_t'},
|
||||
{'t': 'HASHMULTIMAP', 'h': '"cmc/hashmultimap.h"', 'pfx': 'hmm', 'sname': 'hashmultimap', 'key': 'size_t', 'val': 'size_t'},
|
||||
{'t': 'HASHMULTISET', 'h': '"cmc/hashmultiset.h"', 'pfx': 'hms', 'sname': 'hashmultiset', 'key': '', 'val': 'size_t'},
|
||||
{'t': 'HASHSET', 'h': '"cmc/hashset.h"', 'pfx': 'hs', 'sname': 'hashset', 'key': '', 'val': 'size_t'},
|
||||
{'t': 'HEAP', 'h': '"cmc/heap.h"', 'pfx': 'h', 'sname': 'heap', 'key': '', 'val': 'size_t'},
|
||||
{'t': 'INTERVALHEAP', 'h': '"cmc/intervalheap.h"', 'pfx': 'ih', 'sname': 'intervalheap', 'key': '', 'val': 'size_t'},
|
||||
{'t': 'LINKEDLIST', 'h': '"cmc/linkedlist.h"', 'pfx': 'll', 'sname': 'linkedlist', 'key': '', 'val': 'size_t'},
|
||||
{'t': 'LIST', 'h': '"cmc/list.h"', 'pfx': 'l', 'sname': 'list', 'key': '', 'val': 'size_t'},
|
||||
{'t': 'QUEUE', 'h': '"cmc/queue.h"', 'pfx': 'q', 'sname': 'queue', 'key': '', 'val': 'size_t'},
|
||||
{'t': 'SORTEDLIST', 'h': '"cmc/sortedlist.h"', 'pfx': 'sl', 'sname': 'sortedlist', 'key': '', 'val': 'size_t'},
|
||||
{'t': 'STACK', 'h': '"cmc/stack.h"', 'pfx': 's', 'sname': 'stack', 'key': '', 'val': 'size_t'},
|
||||
{'t': 'TREEMAP', 'h': '"cmc/treemap.h"', 'pfx': 'tm', 'sname': 'treemap', 'key': 'size_t', 'val': 'size_t'},
|
||||
{'t': 'TREESET', 'h': '"cmc/treeset.h"', 'pfx': 'ts', 'sname': 'treeset', 'key': '', 'val': 'size_t'}
|
||||
|
||||
# All collections that can be used for testing
|
||||
COLLECTIONS = [
|
||||
# header, library, collection, pfx, sname, size, key, val
|
||||
{'h': '"cmc/bitset.h"', 'LIB': 'CMC', 'COLLECTION': 'BITSET', 'PFX': 'bs', 'SNAME': 'bitset', 'SIZE': '', 'K': '', 'V': '' },
|
||||
{'h': '"cmc/deque.h"', 'LIB': 'CMC', 'COLLECTION': 'DEQUE', 'PFX': 'd', 'SNAME': 'deque', 'SIZE': '', 'K': '', 'V': 'size_t'},
|
||||
{'h': '"cmc/hashbidimap.h"', 'LIB': 'CMC', 'COLLECTION': 'HASHBIDIMAP', 'PFX': 'hbm', 'SNAME': 'hashbidimap', 'SIZE': '', 'K': 'size_t', 'V': 'size_t'},
|
||||
{'h': '"cmc/hashmap.h"', 'LIB': 'CMC', 'COLLECTION': 'HASHMAP', 'PFX': 'hm', 'SNAME': 'hashmap', 'SIZE': '', 'K': 'size_t', 'V': 'size_t'},
|
||||
{'h': '"cmc/hashmultimap.h"', 'LIB': 'CMC', 'COLLECTION': 'HASHMULTIMAP', 'PFX': 'hmm', 'SNAME': 'hashmultimap', 'SIZE': '', 'K': 'size_t', 'V': 'size_t'},
|
||||
{'h': '"cmc/hashmultiset.h"', 'LIB': 'CMC', 'COLLECTION': 'HASHMULTISET', 'PFX': 'hms', 'SNAME': 'hashmultiset', 'SIZE': '', 'K': '', 'V': 'size_t'},
|
||||
{'h': '"cmc/hashset.h"', 'LIB': 'CMC', 'COLLECTION': 'HASHSET', 'PFX': 'hs', 'SNAME': 'hashset', 'SIZE': '', 'K': '', 'V': 'size_t'},
|
||||
{'h': '"cmc/heap.h"', 'LIB': 'CMC', 'COLLECTION': 'HEAP', 'PFX': 'h', 'SNAME': 'heap', 'SIZE': '', 'K': '', 'V': 'size_t'},
|
||||
{'h': '"cmc/intervalheap.h"', 'LIB': 'CMC', 'COLLECTION': 'INTERVALHEAP', 'PFX': 'ih', 'SNAME': 'intervalheap', 'SIZE': '', 'K': '', 'V': 'size_t'},
|
||||
{'h': '"cmc/linkedlist.h"', 'LIB': 'CMC', 'COLLECTION': 'LINKEDLIST', 'PFX': 'll', 'SNAME': 'linkedlist', 'SIZE': '', 'K': '', 'V': 'size_t'},
|
||||
{'h': '"cmc/list.h"', 'LIB': 'CMC', 'COLLECTION': 'LIST', 'PFX': 'l', 'SNAME': 'list', 'SIZE': '', 'K': '', 'V': 'size_t'},
|
||||
{'h': '"cmc/queue.h"', 'LIB': 'CMC', 'COLLECTION': 'QUEUE', 'PFX': 'q', 'SNAME': 'queue', 'SIZE': '', 'K': '', 'V': 'size_t'},
|
||||
{'h': '"cmc/sortedlist.h"', 'LIB': 'CMC', 'COLLECTION': 'SORTEDLIST', 'PFX': 'sl', 'SNAME': 'sortedlist', 'SIZE': '', 'K': '', 'V': 'size_t'},
|
||||
{'h': '"cmc/stack.h"', 'LIB': 'CMC', 'COLLECTION': 'STACK', 'PFX': 's', 'SNAME': 'stack', 'SIZE': '', 'K': '', 'V': 'size_t'},
|
||||
{'h': '"cmc/treemap.h"', 'LIB': 'CMC', 'COLLECTION': 'TREEMAP', 'PFX': 'tm', 'SNAME': 'treemap', 'SIZE': '', 'K': 'size_t', 'V': 'size_t'},
|
||||
{'h': '"cmc/treeset.h"', 'LIB': 'CMC', 'COLLECTION': 'TREESET', 'PFX': 'ts', 'SNAME': 'treeset', 'SIZE': '', 'K': '', 'V': 'size_t'}
|
||||
]
|
||||
|
||||
# Create output directory
|
||||
if not os.path.exists(OUTPUT_DIR):
|
||||
os.makedirs(OUTPUT_DIR)
|
||||
|
||||
for data in collections:
|
||||
file = open(TMP_FILE, 'w')
|
||||
def full_path(path: Text) -> Text:
|
||||
'''
|
||||
Returns the full path of a 'path' with ralative paths, e.g. './' or '../'
|
||||
'''
|
||||
return str(pathlib.Path(path).resolve())
|
||||
|
||||
if data['key'] == '' and data['val'] == '':
|
||||
# bitset, no K and no V
|
||||
type_params = ''
|
||||
elif data['key'] != '':
|
||||
# maps, K and V
|
||||
type_params = f', {data["key"]}, {data["val"]}'
|
||||
|
||||
def execute_command(commands: List[Text]):
|
||||
cmd = ' '.join(commands)
|
||||
print(cmd)
|
||||
subprocess.check_call(cmd, shell=True)
|
||||
|
||||
# if cp.returncode != 0:
|
||||
# print('Error when executing the last command')
|
||||
# exit(1)
|
||||
|
||||
|
||||
def assert_executable(program: Text):
|
||||
'''
|
||||
Asserts that a given program is installed and available in PATH.
|
||||
'''
|
||||
if shutil.which(program) is None:
|
||||
raise Exception(f'The required executable {program} was not found in your path')
|
||||
|
||||
|
||||
def assert_dir(directory: Text):
|
||||
'''
|
||||
Given a string 'directory' that is a path to a directory, make sure that it exists.
|
||||
'''
|
||||
if not os.path.exists(directory):
|
||||
os.makedirs(directory)
|
||||
|
||||
|
||||
def assert_structure():
|
||||
'''
|
||||
Git might not commit some required directories. This function asserts that they exist.
|
||||
'''
|
||||
assert_dir(OUTPUT_DIR)
|
||||
|
||||
# include and src
|
||||
for directory in DIR_MAP.values():
|
||||
assert_dir(f'{OUTPUT_DIR}/{directory}')
|
||||
|
||||
# For each library, create a directory for include and src
|
||||
for lib in ALL_LIBS:
|
||||
for directory in DIR_MAP.values():
|
||||
assert_dir(f'{OUTPUT_DIR}/{directory}/{lib.lower()}')
|
||||
|
||||
assert_dir(BUILD_DIR)
|
||||
assert_dir(OBJ_DIR)
|
||||
assert_dir(GCOV_DIR)
|
||||
|
||||
for lib in ALL_LIBS:
|
||||
assert_dir(f'{OBJ_DIR}/{lib.lower()}')
|
||||
|
||||
|
||||
def clean_build(cleanfull: bool):
|
||||
'''
|
||||
Removes all files generated by compilation and code coverage along with folders.
|
||||
'''
|
||||
# -f prevents 'rm' from failing
|
||||
execute_command(['rm', '-r', '-f', f'{GCOV_DIR}/*.gcov'])
|
||||
execute_command(['rm', '-f', TEST_EXE])
|
||||
execute_command(['rm', '-r', '-f', BUILD_DIR])
|
||||
|
||||
if cleanfull:
|
||||
execute_command(['rm', '-r', SRC_DIR])
|
||||
execute_command(['rm', '-r', INCLUDE_DIR])
|
||||
|
||||
|
||||
def expand_code():
|
||||
'''
|
||||
Expands code to be used in tests. This is necessary because code coverage doesn't work with macros.
|
||||
'''
|
||||
# Generate Header and Source separately
|
||||
for ftype in ['HEADER', 'SOURCE']:
|
||||
for data in COLLECTIONS:
|
||||
file = open(TMP_FILE, 'w')
|
||||
|
||||
file.write(
|
||||
f'''
|
||||
#include "macro_collections.h"
|
||||
|
||||
{UNIQUE_FLAG}
|
||||
|
||||
C_MACRO_COLLECTIONS_ALL_{ftype}({data['LIB']}, {data['COLLECTION']}, ({', '.join([data['PFX'], data['SNAME'], data['SIZE'], data['K'], data['V']])}))
|
||||
|
||||
{UNIQUE_FLAG}
|
||||
''')
|
||||
|
||||
file.flush()
|
||||
file.close()
|
||||
|
||||
result = subprocess.getoutput(f'{CC} {EXPAND_FLAGS} {" ".join(INCLUDE)} {TMP_FILE}')
|
||||
|
||||
# (?s) makes '.' match anything, even '\n'
|
||||
match = re.search(fr'(?s){UNIQUE_FLAG}(?P<code>.+){UNIQUE_FLAG}', result)
|
||||
|
||||
if match is None:
|
||||
os.remove(TMP_FILE)
|
||||
print('Didn\'t match FLAG. Probably because compilation failed.', file=sys.stderr)
|
||||
exit(1)
|
||||
|
||||
file = open(f'{OUTPUT_DIR}/{DIR_MAP[ftype]}/{data["LIB"].lower()}/{data["SNAME"]}.{EXT_MAP[ftype]}', 'w')
|
||||
|
||||
if ftype == 'HEADER':
|
||||
file.write(
|
||||
f'''
|
||||
#ifndef CMC_{data['LIB']}_{data['COLLECTION']}_TEST_H
|
||||
#define CMC_{data['LIB']}_{data['COLLECTION']}_TEST_H
|
||||
|
||||
#include "macro_collections.h"
|
||||
{match.group('code')}
|
||||
|
||||
#endif /* CMC_{data['LIB']}_{data['COLLECTION']}_TEST_H */
|
||||
''')
|
||||
else:
|
||||
file.write(
|
||||
f'''
|
||||
#include {data["h"]}
|
||||
|
||||
{match.group("code")}
|
||||
''')
|
||||
|
||||
file.flush()
|
||||
file.close()
|
||||
|
||||
print(f'Generated {data["h"]: >20} -> {OUTPUT_DIR}/{DIR_MAP[ftype]}/{data["LIB"].lower()}/{data["SNAME"]}.{EXT_MAP[ftype]}')
|
||||
|
||||
os.remove(TMP_FILE)
|
||||
|
||||
|
||||
def format_expand():
|
||||
'''
|
||||
Format the files outputted by 'expand_code'.
|
||||
'''
|
||||
cmd = ['clang-format', '--style=file', '--verbose', '-i']
|
||||
dirs_to_format = [f'{OUTPUT_DIR}/{DIR_MAP[ftype]}/{lib.lower()}/*.{EXT_MAP[ftype]}' for ftype in DIR_MAP.keys() for lib in ALL_LIBS]
|
||||
cmd.extend(dirs_to_format)
|
||||
execute_command(cmd)
|
||||
|
||||
|
||||
def format_code(source: bool, tests: bool):
|
||||
'''
|
||||
Format all source files from the main library or test files.
|
||||
'''
|
||||
if source:
|
||||
execute_command(['find', './src/', '-name', '*.h', '|', 'xargs', 'clang-format', '--style=file', '--verbose', '-i'])
|
||||
if tests:
|
||||
execute_command(['find', './tests/', '-name', '*.c', '-o', '-name', '*.h', '|', 'xargs', 'clang-format', '--style=file', '--verbose', '-i'])
|
||||
|
||||
|
||||
def build_tests(with_coverage: bool):
|
||||
'''
|
||||
Build all object files and the main executable for tests
|
||||
'''
|
||||
cflags = CFLAGS.copy()
|
||||
|
||||
if with_coverage:
|
||||
cflags += CVFLAGS
|
||||
else:
|
||||
# only V
|
||||
type_params = f', {data["val"]}'
|
||||
cflags += ['-O3']
|
||||
|
||||
file.write(
|
||||
f'''
|
||||
#include {data['h']}
|
||||
for data in COLLECTIONS:
|
||||
cmd = [CC]
|
||||
cmd += cflags
|
||||
cmd += TINCLUDE # This one needs to go first
|
||||
cmd += INCLUDE
|
||||
cmd += ['-c', f"{SRC_DIR}/{data['LIB'].lower()}/{data['SNAME']}.c"]
|
||||
cmd += ['-o', f"{OBJ_DIR}/{data['LIB'].lower()}/{data['SNAME']}.o"]
|
||||
execute_command(cmd)
|
||||
|
||||
{UNIQUE_FLAG}
|
||||
# Build OUTPUT_DIR/main.c
|
||||
cmd = [CC]
|
||||
cmd += cflags
|
||||
cmd += TINCLUDE # This one needs to go first
|
||||
cmd += INCLUDE
|
||||
cmd += ['-c', f'{OUTPUT_DIR}/main.c']
|
||||
cmd += ['-o', f"{OBJ_DIR}/main.o"]
|
||||
execute_command(cmd)
|
||||
|
||||
CMC_GENERATE_{data['t']}({data['pfx']}, {data['sname']}{type_params})
|
||||
# Link everything producing OUTPUT_DIR/main.exe
|
||||
cmd = [CC]
|
||||
cmd += cflags
|
||||
cmd += LFLAGS
|
||||
cmd += ['-o', TEST_EXE]
|
||||
cmd += [f'{OBJ_DIR}/main.o']
|
||||
cmd += [f'{OBJ_DIR}/{data["LIB"].lower()}/{data["SNAME"]}.o' for data in COLLECTIONS]
|
||||
execute_command(cmd)
|
||||
|
||||
{UNIQUE_FLAG}
|
||||
''')
|
||||
|
||||
file.flush()
|
||||
file.close()
|
||||
def run_tests(coverage: bool):
|
||||
'''
|
||||
Runs tests. If coverage, run gcov.
|
||||
'''
|
||||
execute_command([full_path(TEST_EXE)])
|
||||
|
||||
result = subprocess.getoutput(f'{CC} {FLAGS} {INCLUDE} {TMP_FILE}')
|
||||
if coverage:
|
||||
objects = [f'{OBJ_DIR}/main.gcda']
|
||||
objects += [f'{OBJ_DIR}/{data["LIB"].lower()}/{data["SNAME"]}.gcda' for data in COLLECTIONS]
|
||||
execute_command(['gcov'] + GCOV_FLAGS + objects)
|
||||
execute_command(['mv', '*.gcov', GCOV_DIR])
|
||||
|
||||
# (?s) makes '.' match anything, even '\n'
|
||||
match = re.search(fr'(?s){UNIQUE_FLAG}(?P<code>.+){UNIQUE_FLAG}', result)
|
||||
|
||||
if match is None:
|
||||
os.remove(TMP_FILE)
|
||||
print('Didn\'t match FLAG. Probably because compilation failed.')
|
||||
exit(1)
|
||||
if __name__ == '__main__':
|
||||
p = argparse.ArgumentParser('autogen.py', usage='%(prog)s [options]')
|
||||
|
||||
file = open(f'{OUTPUT_DIR}/{data["sname"]}.c', 'w')
|
||||
p.add_argument('-sc', '--show-config',
|
||||
help='Displays the current configuration',
|
||||
action='store_true',
|
||||
dest='config')
|
||||
|
||||
file.write(f'#include {data["h"]}\n{match.group("code")}')
|
||||
tests = p.add_argument_group('tests', 'For dealing with tests')
|
||||
|
||||
file.flush()
|
||||
file.close()
|
||||
tests.add_argument('-c', '--clean',
|
||||
help='Cleans all build objects',
|
||||
default=False,
|
||||
action='store_true',
|
||||
dest='clean')
|
||||
tests.add_argument('-cf', '--clean-full',
|
||||
help='Cleans all build objects, source and header files, and removes folders',
|
||||
default=False,
|
||||
action='store_true',
|
||||
dest='cleanfull')
|
||||
tests.add_argument('-e', '--expand',
|
||||
help='Expands the header and source files',
|
||||
default=False,
|
||||
action='store_true',
|
||||
dest='expand')
|
||||
tests.add_argument('-nf', '--no-format',
|
||||
help='Does not format the output of expand. Can be used when you might not have clang-format',
|
||||
default=False,
|
||||
action='store_true',
|
||||
dest='noformat')
|
||||
tests.add_argument('-b', '--build',
|
||||
help='Compile the object files and the main executable',
|
||||
default=False,
|
||||
action='store_true',
|
||||
dest='build')
|
||||
tests.add_argument('-r', '--run',
|
||||
help='Runs tests, assuming that it is already built',
|
||||
default=False,
|
||||
action='store_true',
|
||||
dest='run')
|
||||
tests.add_argument('-cv', '--coverage',
|
||||
help='Adds the code coverage flags for compilation',
|
||||
default=False,
|
||||
action='store_true',
|
||||
dest='coverage')
|
||||
tests.add_argument('-rr', '--rerun',
|
||||
help='Compile the object files again and then run the tests',
|
||||
default=False,
|
||||
action='store_true',
|
||||
dest='rerun')
|
||||
|
||||
print(f'Generated {data["h"]: >20} -> {OUTPUT_DIR}/{data["sname"]}.c')
|
||||
source = p.add_argument_group('source', 'For dealing with the source files and formatting')
|
||||
|
||||
os.remove(TMP_FILE)
|
||||
source.add_argument('-fs', '--format-source',
|
||||
help='Format the source code',
|
||||
default=False,
|
||||
action='store_true',
|
||||
dest='fmt_source')
|
||||
source.add_argument('-ft', '--format-tests',
|
||||
help='Format tests files',
|
||||
default=False,
|
||||
action='store_true',
|
||||
dest='fmt_tests')
|
||||
|
||||
# Format all files
|
||||
print('Formating files...')
|
||||
subprocess.call(['clang-format', '--style=file', '-i', f'{OUTPUT_DIR}/*.c'])
|
||||
print('Done')
|
||||
args = p.parse_args()
|
||||
|
||||
if args.config:
|
||||
print(CONFIG)
|
||||
exit(0)
|
||||
|
||||
if args.clean or args.cleanfull:
|
||||
clean_build(args.cleanfull)
|
||||
|
||||
if not args.cleanfull:
|
||||
assert_structure()
|
||||
assert_executable(CC)
|
||||
|
||||
if args.expand:
|
||||
expand_code()
|
||||
if not args.noformat:
|
||||
assert_executable('clang-format')
|
||||
format_expand()
|
||||
else:
|
||||
# In case the next task is to build the code from source
|
||||
# This warning is a very annoying one from gcc
|
||||
CFLAGS += ['-Wno-misleading-indentation']
|
||||
|
||||
if args.fmt_source or args.fmt_tests:
|
||||
assert_executable('find')
|
||||
assert_executable('xargs')
|
||||
format_code(args.fmt_source, args.fmt_tests)
|
||||
|
||||
if args.build:
|
||||
build_tests(args.coverage)
|
||||
if args.run:
|
||||
run_tests(args.coverage)
|
||||
elif args.rerun:
|
||||
build_tests(args.coverage)
|
||||
run_tests(args.coverage)
|
||||
elif args.run:
|
||||
run_tests(args.coverage)
|
||||
@@ -0,0 +1,62 @@
|
||||
#ifndef COUNT
|
||||
#error "Please define COUNT"
|
||||
#endif
|
||||
|
||||
#include "murmurhash.h"
|
||||
|
||||
#include "macro_collections.h"
|
||||
|
||||
#include "../../util/twister.c"
|
||||
|
||||
CMC_CMC_HASHMAP_CORE(PUBLIC, HEADER, (hm, hashmap, , uint64_t, uint64_t))
|
||||
CMC_CMC_HASHMAP_CORE(PUBLIC, SOURCE, (hm, hashmap, , uint64_t, uint64_t))
|
||||
|
||||
int cmp(uint64_t a, uint64_t b)
|
||||
{
|
||||
return (a > b) - (a < b);
|
||||
}
|
||||
|
||||
// size_t hash(uint64_t a)
|
||||
// {
|
||||
// size_t x = (size_t)a;
|
||||
// x = ((x >> 16) ^ x) * 0x45d9f3b;
|
||||
// x = ((x >> 16) ^ x) * 0x45d9f3b;
|
||||
// x = (x >> 16) ^ x;
|
||||
// return x;
|
||||
// }
|
||||
|
||||
size_t hash(uint64_t k)
|
||||
{
|
||||
static size_t seed = 211106232532969;
|
||||
return MurMurHash(&k, sizeof(k), seed);
|
||||
}
|
||||
|
||||
struct hashmap_fkey *fkey = &(struct hashmap_fkey) {
|
||||
.cmp = cmp,
|
||||
.hash = hash,
|
||||
NULL
|
||||
};
|
||||
|
||||
struct hashmap_fval *fval = &(struct hashmap_fval) {
|
||||
.cmp = cmp,
|
||||
.hash = hash,
|
||||
NULL
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
mt_state tw;
|
||||
twist_init(&tw, 50331653);
|
||||
|
||||
struct hashmap *map = hm_new(COUNT, 0.6, fkey, fval);
|
||||
|
||||
for (uint64_t i = 0; i < COUNT; i++)
|
||||
{
|
||||
uint64_t v = twist_uint64(&tw);
|
||||
hm_insert(map, v, v);
|
||||
}
|
||||
|
||||
hm_free(map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#ifndef COUNT
|
||||
#error "Please define COUNT"
|
||||
#endif
|
||||
|
||||
#include "murmurhash.h"
|
||||
|
||||
#include "macro_collections.h"
|
||||
|
||||
#include "../../util/twister.c"
|
||||
|
||||
C_MACRO_COLLECTIONS_ALL(CMC, HASHMULTIMAP, (hmm, hashmultimap, , uint64_t, uint64_t))
|
||||
|
||||
int cmp(uint64_t a, uint64_t b)
|
||||
{
|
||||
return (a > b) - (a < b);
|
||||
}
|
||||
|
||||
// size_t hash(uint64_t a)
|
||||
// {
|
||||
// size_t x = (size_t)a;
|
||||
// x = ((x >> 16) ^ x) * 0x45d9f3b;
|
||||
// x = ((x >> 16) ^ x) * 0x45d9f3b;
|
||||
// x = (x >> 16) ^ x;
|
||||
// return x;
|
||||
// }
|
||||
|
||||
size_t hash(uint64_t k)
|
||||
{
|
||||
static size_t seed = 211106232532969;
|
||||
return MurMurHash(&k, sizeof(k), seed);
|
||||
}
|
||||
|
||||
struct hashmultimap_fkey *fkey = &(struct hashmultimap_fkey) {
|
||||
.cmp = cmp,
|
||||
.hash = hash,
|
||||
NULL
|
||||
};
|
||||
|
||||
struct hashmultimap_fval *fval = &(struct hashmultimap_fval) {
|
||||
.cmp = cmp,
|
||||
.hash = hash,
|
||||
NULL
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
mt_state tw;
|
||||
twist_init(&tw, 50331653);
|
||||
|
||||
struct hashmultimap *map = hmm_new(COUNT, 0.6, fkey, fval);
|
||||
|
||||
for (uint64_t i = 0; i < COUNT; i++)
|
||||
{
|
||||
uint64_t v = twist_uint64(&tw);
|
||||
hmm_insert(map, v, v);
|
||||
}
|
||||
|
||||
hmm_free(map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/hash_bytes.cc
|
||||
|
||||
#ifndef MURMURHASH
|
||||
#define MURMURHASH
|
||||
|
||||
#include <string.h>
|
||||
|
||||
inline size_t unaligned_load(const char *p)
|
||||
{
|
||||
size_t result;
|
||||
memcpy(&result, p, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline size_t load_bytes(const char *p, int n)
|
||||
{
|
||||
size_t result = 0;
|
||||
--n;
|
||||
do
|
||||
{
|
||||
result = (result << 8) + (unsigned char)(p[n]);
|
||||
} while (--n >= 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline size_t shift_mix(size_t v)
|
||||
{
|
||||
return v ^ (v >> 47);
|
||||
}
|
||||
|
||||
size_t MurMurHash(const void *ptr, size_t len, size_t seed)
|
||||
{
|
||||
static const size_t mul = (((size_t)0xc6a4a793UL) << 32UL) + (size_t)0x5bd1e995UL;
|
||||
const char *const buf = (const char *)(ptr);
|
||||
|
||||
// Remove the bytes not divisible by the sizeof(size_t). This
|
||||
// allows the main loop to process the data as 64-bit integers.
|
||||
const size_t len_aligned = len & ~(size_t)0x7;
|
||||
const char *const end = buf + len_aligned;
|
||||
size_t hash = seed ^ (len * mul);
|
||||
for (const char *p = buf; p != end; p += 8)
|
||||
{
|
||||
const size_t data = shift_mix(unaligned_load(p) * mul) * mul;
|
||||
hash ^= data;
|
||||
hash *= mul;
|
||||
}
|
||||
if ((len & 0x7) != 0)
|
||||
{
|
||||
const size_t data = load_bytes(end, len & 0x7);
|
||||
hash ^= data;
|
||||
hash *= mul;
|
||||
}
|
||||
hash = shift_mix(hash) * mul;
|
||||
hash = shift_mix(hash);
|
||||
return hash;
|
||||
}
|
||||
|
||||
#endif /* MURMURHASH */
|
||||
@@ -0,0 +1,57 @@
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
ITERATIONS = 10
|
||||
COUNT = 20000000
|
||||
VERBOSE = False
|
||||
|
||||
NL = '\n'
|
||||
|
||||
INCLUDE = "../../../src"
|
||||
CC = 'gcc'
|
||||
CCPP = 'g++' # LoL
|
||||
OPT = '-O3'
|
||||
|
||||
print(f'Using {CC} compiler')
|
||||
|
||||
|
||||
def execute_command(commands):
|
||||
print(' '.join(commands))
|
||||
subprocess.run(commands, shell=True)
|
||||
|
||||
|
||||
# Common args
|
||||
args = ['-I', INCLUDE, OPT, f'-DCOUNT={COUNT}', '-DCMC_NO_CALLBACKS']
|
||||
|
||||
map_args = [CC, 'hashmap.c', '-o', 'hashmap.exe']
|
||||
mmap_args = [CC, 'hashmultimap.c', '-o', 'hashmultimap.exe']
|
||||
cpp_args = [CCPP, 'unorderedmap.cpp', '-I', INCLUDE, '-o', 'unorderedmap.exe', OPT, f'-DCOUNT={COUNT}']
|
||||
|
||||
map_args.extend(args)
|
||||
mmap_args.extend(args)
|
||||
cpp_args.extend(args)
|
||||
|
||||
execute_command(map_args)
|
||||
execute_command(mmap_args)
|
||||
execute_command(cpp_args)
|
||||
|
||||
programs = ['hashmap.exe', 'hashmultimap.exe', 'unorderedmap.exe']
|
||||
|
||||
for prog in programs:
|
||||
total = 0
|
||||
for i in range(ITERATIONS):
|
||||
print(f'{i}...', end='')
|
||||
sys.stdout.flush()
|
||||
start_time = time.time()
|
||||
subprocess.run(prog, shell=True)
|
||||
|
||||
delta = time.time() - start_time
|
||||
total += delta
|
||||
|
||||
if VERBOSE:
|
||||
print(f'({delta})')
|
||||
|
||||
avg = total / ITERATIONS
|
||||
print(f'{"" if VERBOSE else NL}{avg} seconds for {COUNT} -> AVG[{int((avg * 1e9) / COUNT)} ns] [{prog}]{NL if VERBOSE else ""}')
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef COUNT
|
||||
#error "Please define COUNT"
|
||||
#endif
|
||||
|
||||
#include "murmurhash.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "../../util/twister.c"
|
||||
|
||||
struct IntHasher
|
||||
{
|
||||
std::size_t operator()(const uint64_t& k) const
|
||||
{
|
||||
static size_t seed = 211106232532969;
|
||||
return MurMurHash(&k, sizeof(k), seed);
|
||||
}
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
mt_state tw;
|
||||
twist_init(&tw, 50331653);
|
||||
|
||||
std::unordered_map<uint64_t, uint64_t, IntHasher> map(COUNT);
|
||||
|
||||
for (uint64_t i = 0; i < COUNT; i++)
|
||||
{
|
||||
uint64_t v = twist_uint64(&tw);
|
||||
map.insert({v, v});
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -159,7 +159,7 @@
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/LeoVen/C-Macro-Collections/blob/master/LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License"/></a>
|
||||
<img src="https://img.shields.io/badge/Version-v0.23.0-orange.svg" alt="Version"/>
|
||||
<img src="https://img.shields.io/badge/Version-v0.23.1-orange.svg" alt="Version"/>
|
||||
<a href="https://travis-ci.org/LeoVen/C-Macro-Collections"><img src="https://travis-ci.org/LeoVen/C-Macro-Collections.svg?branch=master" alt="travis-ci"/></a>
|
||||
<a href="https://codecov.io/gh/LeoVen/C-Macro-Collections"><img src="https://codecov.io/gh/LeoVen/C-Macro-Collections/branch/master/graph/badge.svg" alt="codecov"/></a>
|
||||
<img src="https://github.com/LeoVen/C-Macro-Collections/workflows/Test%20Suit/badge.svg?branch=master" alt="test_suit"/>
|
||||
|
||||
+1
-1
@@ -159,7 +159,7 @@
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/LeoVen/C-Macro-Collections/blob/master/LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License"/></a>
|
||||
<img src="https://img.shields.io/badge/Version-v0.23.0-orange.svg" alt="Version"/>
|
||||
<img src="https://img.shields.io/badge/Version-v0.23.1-orange.svg" alt="Version"/>
|
||||
<a href="https://travis-ci.org/LeoVen/C-Macro-Collections"><img src="https://travis-ci.org/LeoVen/C-Macro-Collections.svg?branch=master" alt="travis-ci"/></a>
|
||||
<a href="https://codecov.io/gh/LeoVen/C-Macro-Collections"><img src="https://codecov.io/gh/LeoVen/C-Macro-Collections/branch/master/graph/badge.svg" alt="codecov"/></a>
|
||||
<img src="https://github.com/LeoVen/C-Macro-Collections/workflows/Test%20Suit/badge.svg?branch=master" alt="test_suit"/>
|
||||
|
||||
+1
-1
@@ -161,7 +161,7 @@
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/LeoVen/C-Macro-Collections/blob/master/LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License"/></a>
|
||||
<img src="https://img.shields.io/badge/Version-v0.23.0-orange.svg" alt="Version"/>
|
||||
<img src="https://img.shields.io/badge/Version-v0.23.1-orange.svg" alt="Version"/>
|
||||
<a href="https://travis-ci.org/LeoVen/C-Macro-Collections"><img src="https://travis-ci.org/LeoVen/C-Macro-Collections.svg?branch=master" alt="travis-ci"/></a>
|
||||
<a href="https://codecov.io/gh/LeoVen/C-Macro-Collections"><img src="https://codecov.io/gh/LeoVen/C-Macro-Collections/branch/master/graph/badge.svg" alt="codecov"/></a>
|
||||
<img src="https://github.com/LeoVen/C-Macro-Collections/workflows/Test%20Suit/badge.svg?branch=master" alt="test_suit"/>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/LeoVen/C-Macro-Collections/blob/master/LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License"/></a>
|
||||
<img src="https://img.shields.io/badge/Version-v0.23.0-orange.svg" alt="Version"/>
|
||||
<img src="https://img.shields.io/badge/Version-v0.23.1-orange.svg" alt="Version"/>
|
||||
<a href="https://travis-ci.org/LeoVen/C-Macro-Collections"><img src="https://travis-ci.org/LeoVen/C-Macro-Collections.svg?branch=master" alt="travis-ci"/></a>
|
||||
<a href="https://codecov.io/gh/LeoVen/C-Macro-Collections"><img src="https://codecov.io/gh/LeoVen/C-Macro-Collections/branch/master/graph/badge.svg" alt="codecov"/></a>
|
||||
<img src="https://github.com/LeoVen/C-Macro-Collections/workflows/Test%20Suit/badge.svg?branch=master" alt="test_suit"/>
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Example of In-Order Depth-First Search using:
|
||||
* - A Stack
|
||||
* - Recursion
|
||||
* - Without both
|
||||
*/
|
||||
|
||||
#define CMC_CAMEL_CASE
|
||||
|
||||
#include "macro_collections.h"
|
||||
|
||||
C_MACRO_COLLECTIONS_GEN(CMC, TREESET, (tree, BinaryTree, , , int32_t), (ITER, STR))
|
||||
|
||||
#define MYSTACK (stk, Stack, , , struct BinaryTreeNode *)
|
||||
|
||||
C_MACRO_COLLECTIONS(CMC, STACK, CORE, STRUCT, MYSTACK)
|
||||
C_MACRO_COLLECTIONS(CMC, STACK, CORE, HEADER, MYSTACK)
|
||||
C_MACRO_COLLECTIONS(CMC, STACK, CORE, SOURCE, MYSTACK)
|
||||
|
||||
void DFS(struct BinaryTreeNode *root)
|
||||
{
|
||||
if (!root)
|
||||
return;
|
||||
|
||||
DFS(root->left);
|
||||
|
||||
fprintf(stdout, "%d ", root->value);
|
||||
|
||||
DFS(root->right);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
struct BinaryTree *tree = tree_new(&(struct BinaryTreeFVal){ .cmp = cmc_i32_cmp, .str = cmc_i32_str, NULL });
|
||||
|
||||
for (int i = 1; i <= 10; i++)
|
||||
tree_insert(tree, i);
|
||||
|
||||
int32_t result = 1;
|
||||
|
||||
cmc_assert(tree_min(tree, &result));
|
||||
cmc_assert_equals(int32_t, 1, result);
|
||||
|
||||
cmc_assert(tree_max(tree, &result));
|
||||
cmc_assert_equals(int32_t, 10, result);
|
||||
|
||||
printf("Without Recursion or Stack:\n");
|
||||
tree_print(tree, stdout, "[ ", " ", " ]\n");
|
||||
|
||||
printf("Recursion:\n");
|
||||
fprintf(stdout, "[ ");
|
||||
DFS(tree->root);
|
||||
fprintf(stdout, "]\n");
|
||||
|
||||
printf("Stack:\n");
|
||||
fprintf(stdout, "[ ");
|
||||
struct Stack *stack = stk_new(100, &(struct StackFVal){ NULL });
|
||||
|
||||
struct BinaryTreeNode *node = tree->root;
|
||||
|
||||
while (node || !stk_empty(stack))
|
||||
{
|
||||
if (node)
|
||||
{
|
||||
if (!stk_push(stack, node))
|
||||
cmc_log_error("Could not push to stack %d\n", cmc_flags_to_str[stk_flag(stack)]);
|
||||
|
||||
node = node->left;
|
||||
}
|
||||
else
|
||||
{
|
||||
node = stk_top(stack);
|
||||
|
||||
if (!stk_pop(stack))
|
||||
cmc_log_error("Could not pop from the stack %s\n", cmc_flags_to_str[stk_flag(stack)]);
|
||||
|
||||
fprintf(stdout, "%d ", node->value);
|
||||
|
||||
node = node->right;
|
||||
}
|
||||
}
|
||||
|
||||
stk_free(stack);
|
||||
fprintf(stdout, "]\n");
|
||||
|
||||
tree_free(tree);
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// This is the master header. This will include every feature of the library.
|
||||
// This comes with many helper macros (high level API) and utility functions.
|
||||
#include "macro_collections.h"
|
||||
|
||||
// A PARAM is a standard way to pass required parameters to the lower level API.
|
||||
// It is a tuple of form (PFX, SNAME, SIZE, K, V). In this case, not all of them
|
||||
// are used, so we can leave them empty. We are creating a list of value int.
|
||||
#define MY_LIST_PARAMS (intl, int_list, , , int)
|
||||
|
||||
// High level API. Generate a LIST from the CMC library with the STR extension
|
||||
// using our previously defined PARAMs. Every collections has a CORE part that
|
||||
// needs to be generated first. Then, we can add other parts after. This macro
|
||||
// does all of that for us. The STR part will provide us with a function that
|
||||
// will be used later.
|
||||
C_MACRO_COLLECTIONS_GEN(CMC, LIST, MY_LIST_PARAMS, (STR))
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// Our list type is defined by SNAME and all functions are prefixed by PFX
|
||||
// (PFX can also be thought as the function's namespace). Also, nodes,
|
||||
// entries, iterators and other structures are prefixed by SNAME. So PFX is
|
||||
// for functions and SNAME is for structs, where the main one is simply
|
||||
// 'struct SNAME'.
|
||||
// To initialize a list we need to pass in an initial capacity and something
|
||||
// that is called a function table for the V type.
|
||||
// This function table is a struct with methods that will extract some
|
||||
// (sometimes) necessary behaviour from your custom data type. Things like
|
||||
// hash, comparison and printing. A list doesn't require any of these
|
||||
// functions. That is, the CORE module doesn't use any of them.
|
||||
// But since we are using the STR module, we will need to define the 'str'
|
||||
// function. luckily, for the 'int' type, the library already provides such
|
||||
// function (cmc_i32_str), provided by the /utl/futils.h header file.
|
||||
struct int_list *list = intl_new(32, &(struct int_list_fval){ .str = cmc_i32_str, NULL });
|
||||
|
||||
// Check if the list was successfully initialized. It could fail if the
|
||||
// initial capacity is too big or if 'struct int_list_fval *' is NULL,
|
||||
// because every data structure must have a valid function table.
|
||||
if (!list)
|
||||
return 1;
|
||||
|
||||
// Add some items to the list. The CMC data structures are all dynamically
|
||||
// sized. So there can be as many items as you want as long as you have
|
||||
// enough memory.
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
// Try to add an element to the list. If it fails you can check what
|
||||
// caused it by getting its flag.
|
||||
if (!intl_push_back(list, i))
|
||||
{
|
||||
enum cmc_flags flag = intl_flag(list);
|
||||
// Use cmc_flags_to_str to map the enum error to a string.
|
||||
fprintf(stderr, "%s : push_back failed\n", cmc_flags_to_str[flag]);
|
||||
}
|
||||
}
|
||||
|
||||
// Now we will use the STR module, the _print() function. This is where the
|
||||
// '.str' from the function table comes into play. If we haven't defined it,
|
||||
// the program would've crashed. We also need to define to which file we
|
||||
// will be printing the list's content. In this case, the terminal. Also,
|
||||
// some strings need to be defined. They will be printed: before all elements,
|
||||
// between each one, and after all elements. This is very usefull and can
|
||||
// print a data structure very nicely.
|
||||
intl_print(list, stdout, "[ ", ", ", " ]\n");
|
||||
|
||||
// Free all of its resources
|
||||
intl_free(list);
|
||||
}
|
||||
+14
-14
@@ -1,14 +1,17 @@
|
||||
#include <cmc/stack.h>
|
||||
#include <utl/log.h>
|
||||
#include "macro_collections.h"
|
||||
|
||||
CMC_GENERATE_STACK(stk, stack, int)
|
||||
#define MYSTACK (stk, stack, , , int)
|
||||
|
||||
C_MACRO_COLLECTIONS(CMC, STACK, CORE, STRUCT, MYSTACK)
|
||||
C_MACRO_COLLECTIONS(CMC, STACK, CORE, HEADER, MYSTACK)
|
||||
C_MACRO_COLLECTIONS(CMC, STACK, CORE, SOURCE, MYSTACK)
|
||||
|
||||
struct
|
||||
{
|
||||
struct stack *from;
|
||||
struct stack *aux;
|
||||
struct stack *to;
|
||||
} print_aux = {NULL};
|
||||
} print_aux = { NULL };
|
||||
|
||||
void print_stacks()
|
||||
{
|
||||
@@ -18,10 +21,7 @@ void print_stacks()
|
||||
int ib = print_aux.aux->buffer[i];
|
||||
int ic = print_aux.to->buffer[i];
|
||||
|
||||
printf("| %c | %c | %c |\n",
|
||||
ia == 0 ? 32 : ia + 48,
|
||||
ib == 0 ? 32 : ib + 48,
|
||||
ic == 0 ? 32 : ic + 48);
|
||||
printf("| %c | %c | %c |\n", ia == 0 ? 32 : ia + 48, ib == 0 ? 32 : ib + 48, ic == 0 ? 32 : ic + 48);
|
||||
}
|
||||
|
||||
printf("+---+---+---+\n\n");
|
||||
@@ -50,9 +50,9 @@ void hanoi(int n, struct stack *from, struct stack *aux, struct stack *to)
|
||||
|
||||
int main(int argc, char const *argv[])
|
||||
{
|
||||
struct stack *from = stk_new(10);
|
||||
struct stack *to = stk_new(10);
|
||||
struct stack *aux = stk_new(10);
|
||||
struct stack *from = stk_new(10, &(struct stack_fval){ NULL });
|
||||
struct stack *to = stk_new(10, &(struct stack_fval){ NULL });
|
||||
struct stack *aux = stk_new(10, &(struct stack_fval){ NULL });
|
||||
|
||||
for (int i = 4; i >= 1; i--)
|
||||
stk_push(from, i);
|
||||
@@ -65,9 +65,9 @@ int main(int argc, char const *argv[])
|
||||
|
||||
hanoi(stk_count(from), from, aux, to);
|
||||
|
||||
stk_free(from, NULL);
|
||||
stk_free(to, NULL);
|
||||
stk_free(aux, NULL);
|
||||
stk_free(from);
|
||||
stk_free(to);
|
||||
stk_free(aux);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+20
-21
@@ -1,5 +1,6 @@
|
||||
#include <cmc/list.h>
|
||||
#include <utl/log.h>
|
||||
// Prints a file in the terminal separated by pages
|
||||
|
||||
#include "macro_collections.h"
|
||||
|
||||
#define TAB_SIZE 4
|
||||
#define ROW_INI_CAP DOC_LETTERS_IN_ROW
|
||||
@@ -7,13 +8,11 @@
|
||||
#define DOC_ROWS_IN_PAGE 50
|
||||
#define DOC_MARGIN 4
|
||||
|
||||
CMC_GENERATE_LIST(row, row, char)
|
||||
CMC_GENERATE_LIST(doc, document, struct row *)
|
||||
C_MACRO_COLLECTIONS_ALL(CMC, LIST, (row, row, , , char))
|
||||
C_MACRO_COLLECTIONS_ALL(CMC, LIST, (doc, document, , , struct row *))
|
||||
|
||||
void row_deallocator(struct row *r)
|
||||
{
|
||||
row_free(r, NULL);
|
||||
}
|
||||
struct row_fval *row_funcs = &(struct row_fval){ NULL };
|
||||
struct document_fval *doc_funcs = &(struct document_fval){ .free = row_free };
|
||||
|
||||
struct document *document_load(const char *file_name);
|
||||
void document_empty_line(FILE *fptr);
|
||||
@@ -31,9 +30,9 @@ struct document *document_load(const char *file_name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct row *initial_row = row_new(ROW_INI_CAP);
|
||||
struct row *initial_row = row_new(ROW_INI_CAP, row_funcs);
|
||||
|
||||
struct document *doc = doc_new(100);
|
||||
struct document *doc = doc_new(100, doc_funcs);
|
||||
doc_push_back(doc, initial_row);
|
||||
|
||||
int ch;
|
||||
@@ -46,7 +45,7 @@ struct document *document_load(const char *file_name)
|
||||
|
||||
if (c == '\n')
|
||||
{
|
||||
struct row *new_row = row_new(ROW_INI_CAP);
|
||||
struct row *new_row = row_new(ROW_INI_CAP, row_funcs);
|
||||
doc_push_back(doc, new_row);
|
||||
}
|
||||
else if (c == '\t')
|
||||
@@ -61,7 +60,7 @@ struct document *document_load(const char *file_name)
|
||||
|
||||
if (left > 0)
|
||||
{
|
||||
struct row *new_row = row_new(ROW_INI_CAP);
|
||||
struct row *new_row = row_new(ROW_INI_CAP, row_funcs);
|
||||
doc_push_back(doc, new_row);
|
||||
|
||||
while (left > 0)
|
||||
@@ -73,7 +72,7 @@ struct document *document_load(const char *file_name)
|
||||
}
|
||||
else if (DOC_LETTERS_IN_ROW == row_count(current_row))
|
||||
{
|
||||
struct row *new_row = row_new(ROW_INI_CAP);
|
||||
struct row *new_row = row_new(ROW_INI_CAP, row_funcs);
|
||||
row_push_back(new_row, c);
|
||||
doc_push_back(doc, new_row);
|
||||
}
|
||||
@@ -86,12 +85,12 @@ struct document *document_load(const char *file_name)
|
||||
|
||||
void document_empty_line(FILE *fptr)
|
||||
{
|
||||
fputs("|", fptr);
|
||||
fputs("\t|", fptr);
|
||||
for (size_t i = 0; i < DOC_LETTERS_IN_ROW + DOC_MARGIN * 2; i++)
|
||||
{
|
||||
fputc(' ', fptr);
|
||||
}
|
||||
fputs("|\n", fptr);
|
||||
fputs("\t|\n", fptr);
|
||||
}
|
||||
|
||||
void document_page_outline(FILE *fptr, int outline /* 0 - header, 1 - footer */)
|
||||
@@ -102,7 +101,7 @@ void document_page_outline(FILE *fptr, int outline /* 0 - header, 1 - footer */)
|
||||
#ifdef DOC_PAGE_NUMBER
|
||||
static intmax_t page = 1;
|
||||
|
||||
fputs("|", fptr);
|
||||
fputs("\t|", fptr);
|
||||
for (size_t i = 0; i < (DOC_LETTERS_IN_ROW + DOC_MARGIN) - 8; i++)
|
||||
{
|
||||
fputc(' ', fptr);
|
||||
@@ -116,8 +115,8 @@ void document_page_outline(FILE *fptr, int outline /* 0 - header, 1 - footer */)
|
||||
#endif
|
||||
}
|
||||
|
||||
fputs("+", fptr);
|
||||
for (size_t i = 0; i < DOC_LETTERS_IN_ROW + DOC_MARGIN * 2; i++)
|
||||
fputs("\t+", fptr);
|
||||
for (size_t i = 0; i < DOC_LETTERS_IN_ROW + DOC_MARGIN * 2 + 3; i++)
|
||||
{
|
||||
fputc('-', fptr);
|
||||
}
|
||||
@@ -130,7 +129,7 @@ void document_page_outline(FILE *fptr, int outline /* 0 - header, 1 - footer */)
|
||||
void document_page_margin(FILE *fptr, int margin /* 0 - first margin, 1 - second margin */)
|
||||
{
|
||||
if (margin == 0)
|
||||
fputs("|", fptr);
|
||||
fputs("\t|", fptr);
|
||||
|
||||
for (size_t i = 0; i < DOC_MARGIN; i++)
|
||||
{
|
||||
@@ -138,7 +137,7 @@ void document_page_margin(FILE *fptr, int margin /* 0 - first margin, 1 - second
|
||||
}
|
||||
|
||||
if (margin == 1)
|
||||
fputs("|\n", fptr);
|
||||
fputs("\t|\n", fptr);
|
||||
}
|
||||
|
||||
void document_print(struct document *doc, FILE *fptr)
|
||||
@@ -202,7 +201,7 @@ int main(int argc, char const *argv[])
|
||||
|
||||
document_print(doc, stdout);
|
||||
|
||||
doc_free(doc, row_deallocator);
|
||||
doc_free(doc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#include "cmc/bitset.h"
|
||||
#include <math.h>
|
||||
|
||||
CMC_CMC_BITSET_CORE(PUBLIC, HEADER, (bs, bitset))
|
||||
CMC_CMC_BITSET_CORE(PUBLIC, SOURCE, (bs, bitset))
|
||||
|
||||
// All the prime numbers up to 1 billion
|
||||
// With -O3:
|
||||
// 28.583 s runtime
|
||||
// 120 MB RAM
|
||||
// 490 MB file size
|
||||
int main(void)
|
||||
{
|
||||
const size_t n = 1000000000;
|
||||
|
||||
struct bitset *set = bs_new(n);
|
||||
|
||||
if (!set)
|
||||
return 1;
|
||||
|
||||
bs_set_range(set, 0, n);
|
||||
|
||||
size_t up_to = sqrt((double)n) + 1;
|
||||
for (size_t i = 2; i < up_to; ++i)
|
||||
{
|
||||
if (bs_get(set, i))
|
||||
{
|
||||
for (size_t j = 2 * i; j < n; j += i)
|
||||
bs_clear(set, j);
|
||||
}
|
||||
}
|
||||
|
||||
FILE *file = fopen("primes.txt", "w");
|
||||
|
||||
for (size_t i = 2; i < n; i++)
|
||||
{
|
||||
if (bs_get(set, i))
|
||||
fprintf(file, "%" PRIuMAX " ", i);
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
}
|
||||
+520
-533
File diff suppressed because it is too large.
Load diff
+481
-817
File diff suppressed because it is too large.
Load diff
+1305
-1395
File diff suppressed because it is too large.
Load diff
+788
-1182
File diff suppressed because it is too large.
Load diff
+1000
-1405
File diff suppressed because it is too large.
Load diff
+828
-1470
File diff suppressed because it is too large.
Load diff
+617
-1233
File diff suppressed because it is too large.
Load diff
+454
-732
File diff suppressed because it is too large.
Load diff
+862
-1136
File diff suppressed because it is too large.
Load diff
+582
-1079
File diff suppressed because it is too large.
Load diff
+559
-1005
File diff suppressed because it is too large.
Load diff
+422
-725
File diff suppressed because it is too large.
Load diff
+578
-846
File diff suppressed because it is too large.
Load diff
+371
-635
File diff suppressed because it is too large.
Load diff
+859
-1239
File diff suppressed because it is too large.
Load diff
+731
-1315
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* cor/alloc.h
|
||||
*
|
||||
* Creation Date: 24/05/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CMC_COR_ALLOC_H
|
||||
#define CMC_COR_ALLOC_H
|
||||
|
||||
#ifdef CMC_CAMEL_CASE
|
||||
#define CMC_ALLOC_NODE_NAME CMCAllocNode
|
||||
#else
|
||||
#define CMC_ALLOC_NODE_NAME cmc_alloc_node
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* struct cmc_alloc_node
|
||||
*
|
||||
* Custom allocation node. Allows collections to use custom allocation
|
||||
* functions. The cmc_alloc_node_default is the default heap allocator provided
|
||||
* by the standard library.
|
||||
*/
|
||||
static struct CMC_ALLOC_NODE_NAME
|
||||
{
|
||||
void *(*malloc)(size_t);
|
||||
void *(*calloc)(size_t, size_t);
|
||||
void *(*realloc)(void *, size_t);
|
||||
void (*free)(void *);
|
||||
} cmc_alloc_node_default = { malloc, calloc, realloc, free };
|
||||
|
||||
#endif /* CMC_COR_ALLOC_H */
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* cor/bitset.h
|
||||
*
|
||||
* Creation Date: 20/05/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Things commonly used by bitset collections.
|
||||
*/
|
||||
|
||||
#ifndef CMC_COR_BITSET_H
|
||||
#define CMC_COR_BITSET_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Defines the underlaying data type for the bitset array */
|
||||
/* Possible values: uint64_t, uint32_t, uint16_t, uint8_t, size_t */
|
||||
#ifndef CMC_BITSET_WORD_TYPE
|
||||
#define CMC_BITSET_WORD_TYPE uint32_t
|
||||
#endif /* CMC_BITSET_WORD_TYPE */
|
||||
|
||||
typedef CMC_BITSET_WORD_TYPE cmc_bitset_word;
|
||||
|
||||
/**
|
||||
* cmc_bit_to_index
|
||||
*
|
||||
* Translates a bit index to a word index
|
||||
*/
|
||||
static inline size_t cmc_bidx_to_widx(size_t idx)
|
||||
{
|
||||
/* Calculate how many shifts based on the size of cmc_bitset_word */
|
||||
static const size_t shift =
|
||||
((sizeof(cmc_bitset_word) * 8) >> 6) > 0
|
||||
? 6
|
||||
: ((sizeof(cmc_bitset_word) * 8) >> 5) > 0 ? 5 : ((sizeof(cmc_bitset_word) * 8) >> 4) > 0 ? 4 : 3;
|
||||
|
||||
return idx >> shift;
|
||||
}
|
||||
|
||||
#endif /* CMC_COR_BITSET_H */
|
||||
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* cor/callbacks.h
|
||||
*
|
||||
* Creation Date: 24/05/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CMC_COR_CALLBACKS_H
|
||||
#define CMC_COR_CALLBACKS_H
|
||||
|
||||
#ifdef CMC_CAMEL_CASE
|
||||
#define CMC_CALLBACKS_NAME CMCCallbacks
|
||||
#else
|
||||
#define CMC_CALLBACKS_NAME cmc_callbacks
|
||||
#endif
|
||||
|
||||
#ifdef CMC_NO_CALLBACKS
|
||||
|
||||
#define CMC_CALLBACKS_DECL
|
||||
#define CMC_CALLBACKS_MAYBE_UNUSED(param) ((void)param) /* Prevent -Wunused-parameter */
|
||||
#define CMC_CALLBACKS_GET(ds) NULL /* Helps with compatibility */
|
||||
#define CMC_CALLBACKS_ASSIGN(ds, cb)
|
||||
#define CMC_CALLBACKS_CALL(ds, cb)
|
||||
|
||||
#else
|
||||
|
||||
#define CMC_CALLBACKS_DECL struct CMC_CALLBACKS_NAME *callbacks
|
||||
#define CMC_CALLBACKS_MAYBE_UNUSED(param)
|
||||
#define CMC_CALLBACKS_GET(ds) (ds)->callbacks
|
||||
#define CMC_CALLBACKS_ASSIGN(ds, cb) CMC_CALLBACKS_GET(ds) = cb
|
||||
#define CMC_CALLBACKS_CALL(ds, cb) \
|
||||
if (CMC_CALLBACKS_GET(ds) && CMC_CALLBACKS_GET(ds)->cb) \
|
||||
CMC_CALLBACKS_GET(ds)->cb();
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* struct cmc_callbacks
|
||||
*
|
||||
* Callback node. Each collection will call one of these functions when:
|
||||
* - create : an element was successfully added to the collection
|
||||
* - read : the collection was successfully queried about an element
|
||||
* - update : an element in the collection was successfully updated
|
||||
* - delete : an element was successfully removed from the collection
|
||||
* - resize : the collection was full and successfully resized
|
||||
*/
|
||||
struct CMC_CALLBACKS_NAME
|
||||
{
|
||||
void (*create)(void);
|
||||
void (*read)(void);
|
||||
void (*update)(void);
|
||||
void (*delete)(void);
|
||||
void (*resize)(void);
|
||||
};
|
||||
|
||||
#endif /* CMC_COR_CALLBACKS_H */
|
||||
+66
-46
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* core.h
|
||||
* cor/core.h
|
||||
*
|
||||
* Creation Date: 17/03/2020
|
||||
*
|
||||
@@ -9,17 +9,24 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Core includes and structs used in the library.
|
||||
* Core includes and macros for the entire library.
|
||||
*
|
||||
* In here you will find:
|
||||
* struct cmc_string
|
||||
* struct cmc_alloc_node
|
||||
* struct cmc_callbacks
|
||||
* cmc_flags
|
||||
* Here you will find:
|
||||
* - CMC_
|
||||
* - CMC_TO_STRING
|
||||
* - CMC_INTERNAL_PREFIX_[ITER|NODE|ENTRY|FKEY|FVAL]
|
||||
* - CMC_DEF_[ITER|NODE|ENTRY|FKEY|FVAL]
|
||||
* - CMC_PARAM_[PFX|SNAME|SIZE|K|V]
|
||||
*/
|
||||
|
||||
#ifndef CMC_CORE_H
|
||||
#define CMC_CORE_H
|
||||
#ifndef CMC_COR_CORE_H
|
||||
#define CMC_COR_CORE_H
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define CMC_UNUSED __attribute__((__unused__))
|
||||
#else
|
||||
#define CMC_UNUSED
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
@@ -28,54 +35,67 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "alloc.h"
|
||||
#include "callbacks.h"
|
||||
#include "flags.h"
|
||||
#include "ftable.h"
|
||||
|
||||
#define CMC__(A, B) A##B
|
||||
#define CMC_(A, B) CMC__(A, B)
|
||||
|
||||
#define CMC_TO_STRING_(X) #X
|
||||
#define CMC_TO_STRING(X) CMC_TO_STRING_(X)
|
||||
|
||||
/**
|
||||
* struct cmc_string
|
||||
*
|
||||
* Used by all collections when calling the to_string function.
|
||||
*/
|
||||
struct cmc_string
|
||||
{
|
||||
char s[400];
|
||||
};
|
||||
#if defined(CMC_CAMEL_CASE)
|
||||
#define CMC_INTERNAL_PREFIX_ITER Iter
|
||||
#define CMC_INTERNAL_PREFIX_NODE Node
|
||||
#define CMC_INTERNAL_PREFIX_ENTRY Entry
|
||||
#define CMC_INTERNAL_PREFIX_FVAL FVal
|
||||
#define CMC_INTERNAL_PREFIX_FKEY FKey
|
||||
#else
|
||||
#define CMC_INTERNAL_PREFIX_ITER _iter
|
||||
#define CMC_INTERNAL_PREFIX_NODE _node
|
||||
#define CMC_INTERNAL_PREFIX_ENTRY _entry
|
||||
#define CMC_INTERNAL_PREFIX_FVAL _fval
|
||||
#define CMC_INTERNAL_PREFIX_FKEY _fkey
|
||||
#endif
|
||||
|
||||
static const size_t cmc_string_len = 400;
|
||||
#define CMC_DEF_ITER(SNAME) CMC_(SNAME, CMC_INTERNAL_PREFIX_ITER)
|
||||
#define CMC_DEF_NODE(SNAME) CMC_(SNAME, CMC_INTERNAL_PREFIX_NODE)
|
||||
#define CMC_DEF_ENTRY(SNAME) CMC_(SNAME, CMC_INTERNAL_PREFIX_ENTRY)
|
||||
#define CMC_DEF_FVAL(SNAME) CMC_(SNAME, CMC_INTERNAL_PREFIX_FVAL)
|
||||
#define CMC_DEF_FKEY(SNAME) CMC_(SNAME, CMC_INTERNAL_PREFIX_FKEY)
|
||||
|
||||
/**
|
||||
* struct cmc_alloc_node
|
||||
*
|
||||
* Custom allocation node. Allows collections to use custom allocation
|
||||
* functions.
|
||||
* Code to get specific arguments from tuples.
|
||||
*/
|
||||
static struct cmc_alloc_node
|
||||
{
|
||||
void *(*malloc)(size_t);
|
||||
void *(*calloc)(size_t, size_t);
|
||||
void *(*realloc)(void *, size_t);
|
||||
void (*free)(void *);
|
||||
} cmc_alloc_node_default = { malloc, calloc, realloc, free };
|
||||
#define CMC_TUP_0_(A, ...) A
|
||||
#define CMC_TUP_0(TUP) CMC_TUP_0_ TUP
|
||||
#define CMC_TUP_1_(A, B, ...) B
|
||||
#define CMC_TUP_1(TUP) CMC_TUP_1_ TUP
|
||||
#define CMC_TUP_2_(A, B, C, ...) C
|
||||
#define CMC_TUP_2(TUP) CMC_TUP_2_ TUP
|
||||
#define CMC_TUP_3_(A, B, C, D, ...) D
|
||||
#define CMC_TUP_3(TUP) CMC_TUP_3_ TUP
|
||||
#define CMC_TUP_4_(A, B, C, D, E, ...) E
|
||||
#define CMC_TUP_4(TUP) CMC_TUP_4_ TUP
|
||||
|
||||
/**
|
||||
* struct cmc_callbacks
|
||||
* A PARAM is a unified way to pass arguments to all macros that generate code.
|
||||
* It is a tuple that contains the following parameters in order:
|
||||
*
|
||||
* Callback node. Each collection will call one of these functions when:
|
||||
* - create : an element was successfully added to the collection
|
||||
* - read : the collection was successfully queried about an element
|
||||
* - update : an element in the collection was successfully updated
|
||||
* - delete : an element was successfully removed from the collection
|
||||
* - resize : the collection was full and successfully resized
|
||||
* PFX - Functions prefix
|
||||
* SNAME - `struct` name
|
||||
* SIZE - Size for SAC library
|
||||
* K - Key type
|
||||
* V - Value type
|
||||
*
|
||||
* PARAMS := (PFX, SNAME, SIZE, K, V)
|
||||
*/
|
||||
struct cmc_callbacks
|
||||
{
|
||||
void (*create)(void);
|
||||
void (*read)(void);
|
||||
void (*update)(void);
|
||||
void (*delete)(void);
|
||||
void (*resize)(void);
|
||||
};
|
||||
#define CMC_PARAM_PFX CMC_TUP_0
|
||||
#define CMC_PARAM_SNAME CMC_TUP_1
|
||||
#define CMC_PARAM_SIZE CMC_TUP_2
|
||||
#define CMC_PARAM_K CMC_TUP_3
|
||||
#define CMC_PARAM_V CMC_TUP_4
|
||||
|
||||
#endif /* CMC_CORE_H */
|
||||
#endif /* CMC_COR_CORE_H */
|
||||
+23
-21
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* flags.h
|
||||
* cor/flags.h
|
||||
*
|
||||
* Creation Date: 14/05/2020
|
||||
*
|
||||
@@ -8,36 +8,38 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CMC_FLAGS_H
|
||||
#define CMC_FLAGS_H
|
||||
#ifndef CMC_COR_FLAGS_H
|
||||
#define CMC_COR_FLAGS_H
|
||||
|
||||
#include "core.h"
|
||||
|
||||
/**
|
||||
* cmc_flags
|
||||
* enum cmc_flags
|
||||
*
|
||||
* Defines common error codes used by the entire library.
|
||||
*/
|
||||
static struct
|
||||
// clang-format off
|
||||
enum cmc_flags
|
||||
{
|
||||
int OK; // No errors
|
||||
int ALLOC; // Allocation failed
|
||||
int EMPTY; // The collection is empty when it should not
|
||||
int NOT_FOUND; // Key or value not found
|
||||
int INVALID; // Invalid argument or operation
|
||||
int RANGE; // Index out of range
|
||||
int DUPLICATE; // Duplicate key or value
|
||||
int ERROR; // Generic error, usually caused by algorithm error
|
||||
int THREAD; // Generic error regarding threads
|
||||
int MUTEX; // Generic error regarding mutexes
|
||||
} cmc_flags = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
CMC_FLAG_OK = 0, // No errors
|
||||
CMC_FLAG_ALLOC = 1, // Allocation failed
|
||||
CMC_FLAG_EMPTY = 2, // The collection is empty when it should not
|
||||
CMC_FLAG_NOT_FOUND = 3, // Key or value not found
|
||||
CMC_FLAG_INVALID = 4, // Invalid argument or operation
|
||||
CMC_FLAG_RANGE = 5, // Index out of range
|
||||
CMC_FLAG_DUPLICATE = 6, // Duplicate key or value
|
||||
CMC_FLAG_ERROR = 7, // Generic error, usually caused by algorithm error
|
||||
CMC_FLAG_THREAD = 8, // Generic error regarding threads
|
||||
CMC_FLAG_MUTEX = 9 // Generic error regarding mutexes
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
/**
|
||||
* cmc_flags_to_str
|
||||
*
|
||||
* Maps the error codes to their character representation.
|
||||
*/
|
||||
const char *cmc_flags_to_str[10] = { "OK", "ALLOC", "EMPTY",
|
||||
"NOT_FOUND", "INVALID", "RANGE",
|
||||
"DUPLICATE", "ERROR", "THREAD",
|
||||
"MUTEX" };
|
||||
CMC_UNUSED static const char *cmc_flags_to_str[10] = { "OK", "ALLOC", "EMPTY", "NOT_FOUND", "INVALID",
|
||||
"RANGE", "DUPLICATE", "ERROR", "THREAD", "MUTEX" };
|
||||
|
||||
#endif /* CMC_FLAGS_H */
|
||||
#endif /* CMC_COR_FLAGS_H */
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* cor/ftable.h
|
||||
*
|
||||
* Creation Date: 27/05/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Type definitions for Functions Tables.
|
||||
*/
|
||||
|
||||
#ifndef CMC_COR_FTABLE_H
|
||||
#define CMC_COR_FTABLE_H
|
||||
|
||||
/**
|
||||
* Where T can either be K or V
|
||||
*/
|
||||
#define CMC_DEF_FTAB_CMP(T) int (*cmp)(T, T)
|
||||
#define CMC_DEF_FTAB_CPY(T) T (*cpy)(T)
|
||||
#define CMC_DEF_FTAB_STR(T) bool (*str)(FILE *, T)
|
||||
#define CMC_DEF_FTAB_FREE(T) void (*free)(T)
|
||||
#define CMC_DEF_FTAB_HASH(T) size_t (*hash)(T)
|
||||
#define CMC_DEF_FTAB_PRI(T) int (*pri)(T, T)
|
||||
|
||||
#endif /* CMC_COR_FTABLE_H */
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* hashtable.h
|
||||
* cor/hashtable.h
|
||||
*
|
||||
* Creation Date: 17/03/2020
|
||||
*
|
||||
@@ -12,8 +12,8 @@
|
||||
* Things commonly used by hashtable-based collections.
|
||||
*/
|
||||
|
||||
#ifndef CMC_IMPL_HASHTABLE_H
|
||||
#define CMC_IMPL_HASHTABLE_H
|
||||
#ifndef CMC_COR_HASHTABLE_H
|
||||
#define CMC_COR_HASHTABLE_H
|
||||
|
||||
#include "core.h"
|
||||
|
||||
@@ -83,4 +83,4 @@ static const size_t cmc_hashtable_primes[] = {
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
#endif /* CMC_IMPL_HASHTABLE_H */
|
||||
#endif /* CMC_COR_HASHTABLE_H */
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* cor/heap.h
|
||||
*
|
||||
* Creation Date: 01/06/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Things commonly used by heap collections.
|
||||
*/
|
||||
|
||||
#ifndef CMC_COR_HEAP_H
|
||||
#define CMC_COR_HEAP_H
|
||||
|
||||
/**
|
||||
* enum cmc_heap_order
|
||||
*
|
||||
* Defines the two possible heaps:
|
||||
* - Max Heap has the greatest element at the top
|
||||
* - Min Heap has the smallest element at the top
|
||||
*/
|
||||
enum cmc_heap_order
|
||||
{
|
||||
CMC_MAX_HEAP = 1,
|
||||
CMC_MIN_HEAP = -1
|
||||
};
|
||||
|
||||
#endif /* CMC_COR_HEAP_H */
|
||||
-654
@@ -1,654 +0,0 @@
|
||||
/**
|
||||
* deque.h
|
||||
*
|
||||
* Creation Date: 21/06/2019
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
/********************************************************************* DEQUE */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef CMC_DEQUE_H
|
||||
#define CMC_DEQUE_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include "utl/log.h"
|
||||
|
||||
#define DEQUE_GENERATE(PFX, SNAME, FMOD, V) \
|
||||
DEQUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
|
||||
DEQUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
|
||||
|
||||
#define DEQUE_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \
|
||||
DEQUE_GENERATE_HEADER(PFX, SNAME, FMOD, V)
|
||||
|
||||
#define DEQUE_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \
|
||||
DEQUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
|
||||
|
||||
/* HEADER ********************************************************************/
|
||||
#define DEQUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
|
||||
\
|
||||
/* Deque Structure */ \
|
||||
typedef struct SNAME##_s \
|
||||
{ \
|
||||
/* Dynamic circular array of elements */ \
|
||||
V *buffer; \
|
||||
\
|
||||
/* Current circular array capacity */ \
|
||||
size_t capacity; \
|
||||
\
|
||||
/* Current amount of elements */ \
|
||||
size_t count; \
|
||||
\
|
||||
/* Index representing the front of the deque */ \
|
||||
size_t front; \
|
||||
\
|
||||
/* Index representing the back of the deque */ \
|
||||
size_t back; \
|
||||
\
|
||||
/* Function that returns an iterator to the start of the deque */ \
|
||||
struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
|
||||
\
|
||||
/* Function that returns an iterator to the end of the deque */ \
|
||||
struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
|
||||
\
|
||||
} SNAME, *SNAME##_ptr; \
|
||||
\
|
||||
/* Deque Iterator */ \
|
||||
typedef struct SNAME##_iter_s \
|
||||
{ \
|
||||
/* Target deque */ \
|
||||
struct SNAME##_s *target; \
|
||||
\
|
||||
/* Cursor's position (index) */ \
|
||||
size_t cursor; \
|
||||
\
|
||||
/* Keeps track of relative index to the iteration of elements */ \
|
||||
size_t index; \
|
||||
\
|
||||
/* If the iterator has reached the start of the iteration */ \
|
||||
bool start; \
|
||||
\
|
||||
/* If the iterator has reached the end of the iteration */ \
|
||||
bool end; \
|
||||
\
|
||||
} SNAME##_iter, *SNAME##_iter_ptr; \
|
||||
\
|
||||
/* Collection Functions */ \
|
||||
/* Collection Allocation and Deallocation */ \
|
||||
FMOD SNAME *PFX##_new(size_t capacity); \
|
||||
FMOD void PFX##_clear(SNAME *_deque_); \
|
||||
FMOD void PFX##_free(SNAME *_deque_); \
|
||||
/* Collection Input and Output */ \
|
||||
FMOD bool PFX##_push_front(SNAME *_deque_, V element); \
|
||||
FMOD bool PFX##_push_back(SNAME *_deque_, V element); \
|
||||
FMOD bool PFX##_pop_front(SNAME *_deque_); \
|
||||
FMOD bool PFX##_pop_back(SNAME *_deque_); \
|
||||
/* Conditional Input and Output */ \
|
||||
FMOD bool PFX##_push_front_if(SNAME *_deque_, V element, bool condition); \
|
||||
FMOD bool PFX##_push_back_if(SNAME *_deque_, V element, bool condition); \
|
||||
FMOD bool PFX##_pop_front_if(SNAME *_deque_, bool condition); \
|
||||
FMOD bool PFX##_pop_back_if(SNAME *_deque_, bool condition); \
|
||||
/* Element Access */ \
|
||||
FMOD V PFX##_front(SNAME *_deque_); \
|
||||
FMOD V PFX##_back(SNAME *_deque_); \
|
||||
/* Collection State */ \
|
||||
FMOD bool PFX##_contains(SNAME *_deque_, V element, int (*comparator)(V, V)); \
|
||||
FMOD bool PFX##_empty(SNAME *_deque_); \
|
||||
FMOD bool PFX##_full(SNAME *_deque_); \
|
||||
FMOD size_t PFX##_count(SNAME *_deque_); \
|
||||
FMOD size_t PFX##_capacity(SNAME *_deque_); \
|
||||
\
|
||||
/* Iterator Functions */ \
|
||||
/* Iterator Allocation and Deallocation */ \
|
||||
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \
|
||||
FMOD void PFX##_iter_free(SNAME##_iter *iter); \
|
||||
/* Iterator Initialization */ \
|
||||
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \
|
||||
/* Iterator State */ \
|
||||
FMOD bool PFX##_iter_start(SNAME##_iter *iter); \
|
||||
FMOD bool PFX##_iter_end(SNAME##_iter *iter); \
|
||||
/* Iterator Movement */ \
|
||||
FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \
|
||||
FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \
|
||||
FMOD bool PFX##_iter_next(SNAME##_iter *iter); \
|
||||
FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \
|
||||
/* Iterator Access */ \
|
||||
FMOD V PFX##_iter_value(SNAME##_iter *iter); \
|
||||
FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \
|
||||
FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \
|
||||
\
|
||||
/* Default Value */ \
|
||||
static inline V PFX##_impl_default_value(void) \
|
||||
{ \
|
||||
V _empty_value_; \
|
||||
\
|
||||
memset(&_empty_value_, 0, sizeof(V)); \
|
||||
\
|
||||
return _empty_value_; \
|
||||
} \
|
||||
\
|
||||
/* SOURCE ********************************************************************/
|
||||
#define DEQUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \
|
||||
\
|
||||
/* Implementation Detail Functions */ \
|
||||
static bool PFX##_impl_grow(SNAME *_deque_); \
|
||||
static SNAME##_iter PFX##_impl_it_start(SNAME *_deque_); \
|
||||
static SNAME##_iter PFX##_impl_it_end(SNAME *_deque_); \
|
||||
\
|
||||
FMOD SNAME *PFX##_new(size_t capacity) \
|
||||
{ \
|
||||
if (capacity < 1) \
|
||||
{ \
|
||||
log_warn("Invalid capacity for %s given: %s", "Heap", capacity); \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
SNAME *_deque_ = malloc(sizeof(SNAME)); \
|
||||
\
|
||||
if (!_deque_) \
|
||||
{ \
|
||||
log_info("%s allocation failed", "Deque"); \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
_deque_->buffer = malloc(sizeof(V) * capacity); \
|
||||
\
|
||||
if (!_deque_->buffer) \
|
||||
{ \
|
||||
log_info("%s allocation failed", "Deque buffer"); \
|
||||
free(_deque_); \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
memset(_deque_->buffer, 0, sizeof(V) * capacity); \
|
||||
\
|
||||
_deque_->capacity = capacity; \
|
||||
_deque_->count = 0; \
|
||||
_deque_->front = 0; \
|
||||
_deque_->back = 0; \
|
||||
\
|
||||
_deque_->it_start = PFX##_impl_it_start; \
|
||||
_deque_->it_end = PFX##_impl_it_end; \
|
||||
\
|
||||
log_info("Deque at %p successfully allocated", _deque_); \
|
||||
\
|
||||
return _deque_; \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_clear(SNAME *_deque_) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
\
|
||||
memset(_deque_->buffer, 0, sizeof(V) * _deque_->capacity); \
|
||||
\
|
||||
_deque_->count = 0; \
|
||||
_deque_->front = 0; \
|
||||
_deque_->back = 0; \
|
||||
\
|
||||
log_trace("Deque at %p cleared", _deque_); \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_free(SNAME *_deque_) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
\
|
||||
free(_deque_->buffer); \
|
||||
\
|
||||
uintptr_t address = (uintptr_t)(void *)_deque_; \
|
||||
\
|
||||
free(_deque_); \
|
||||
\
|
||||
log_info("Heap at %p successfully deallocated", address); \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_push_front(SNAME *_deque_, V element) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
\
|
||||
if (PFX##_full(_deque_)) \
|
||||
{ \
|
||||
if (!PFX##_impl_grow(_deque_)) \
|
||||
{ \
|
||||
log_info("Deque at %p failed to be reallocated", _deque_); \
|
||||
return false; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
_deque_->front = (_deque_->front == 0) ? _deque_->capacity - 1 : _deque_->front - 1; \
|
||||
\
|
||||
_deque_->buffer[_deque_->front] = element; \
|
||||
\
|
||||
log_trace("Element added at %" PRIuMAX " to Deque at %p", _deque_->front, _deque_); \
|
||||
\
|
||||
_deque_->count++; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_push_back(SNAME *_deque_, V element) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
\
|
||||
if (PFX##_full(_deque_)) \
|
||||
{ \
|
||||
if (!PFX##_impl_grow(_deque_)) \
|
||||
{ \
|
||||
log_info("Deque at %p failed to be reallocated", _deque_); \
|
||||
return false; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
_deque_->buffer[_deque_->back] = element; \
|
||||
\
|
||||
log_trace("Element added at %" PRIuMAX " to Deque at %p", _deque_->back, _deque_); \
|
||||
\
|
||||
_deque_->back = (_deque_->back == _deque_->capacity - 1) ? 0 : _deque_->back + 1; \
|
||||
\
|
||||
_deque_->count++; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_pop_front(SNAME *_deque_) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
\
|
||||
if (PFX##_empty(_deque_)) \
|
||||
{ \
|
||||
log_debug("Attempt of removing an element from empty Deque at %p", _deque_); \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
_deque_->buffer[_deque_->front] = PFX##_impl_default_value(); \
|
||||
\
|
||||
log_trace("Element removed from %" PRIuMAX " to Deque at %p", _deque_->front, _deque_); \
|
||||
\
|
||||
_deque_->front = (_deque_->front == _deque_->capacity - 1) ? 0 : _deque_->front + 1; \
|
||||
\
|
||||
_deque_->count--; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_pop_back(SNAME *_deque_) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
{ \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
} \
|
||||
\
|
||||
if (PFX##_empty(_deque_)) \
|
||||
{ \
|
||||
log_debug("Attempt of removing an element from empty Deque at %p", _deque_); \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
_deque_->back = (_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1; \
|
||||
\
|
||||
_deque_->buffer[_deque_->back] = PFX##_impl_default_value(); \
|
||||
\
|
||||
log_trace("Element removed from %" PRIuMAX " to Deque at %p", _deque_->back, _deque_); \
|
||||
\
|
||||
_deque_->count--; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_push_front_if(SNAME *_deque_, V element, bool condition) \
|
||||
{ \
|
||||
if (condition) \
|
||||
return PFX##_push_front(_deque_, element); \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_push_back_if(SNAME *_deque_, V element, bool condition) \
|
||||
{ \
|
||||
if (condition) \
|
||||
return PFX##_push_back(_deque_, element); \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_pop_front_if(SNAME *_deque_, bool condition) \
|
||||
{ \
|
||||
if (condition) \
|
||||
return PFX##_pop_front(_deque_); \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_pop_back_if(SNAME *_deque_, bool condition) \
|
||||
{ \
|
||||
if (condition) \
|
||||
return PFX##_pop_back(_deque_); \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
FMOD V PFX##_front(SNAME *_deque_) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
\
|
||||
if (PFX##_empty(_deque_)) \
|
||||
{ \
|
||||
log_debug("Attempt to access element from empty Deque at %p", _deque_); \
|
||||
\
|
||||
PFX##_impl_default_value(); \
|
||||
} \
|
||||
\
|
||||
log_trace("Element access at %" PRIuMAX "", _deque_->front); \
|
||||
\
|
||||
return _deque_->buffer[_deque_->front]; \
|
||||
} \
|
||||
\
|
||||
FMOD V PFX##_back(SNAME *_deque_) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
\
|
||||
if (PFX##_empty(_deque_)) \
|
||||
{ \
|
||||
log_debug("Attempt to access element from empty Deque at %p", _deque_); \
|
||||
\
|
||||
PFX##_impl_default_value(); \
|
||||
} \
|
||||
\
|
||||
size_t index = (_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1; \
|
||||
\
|
||||
log_trace("Element access at %" PRIuMAX "", index); \
|
||||
\
|
||||
return _deque_->buffer[index]; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_contains(SNAME *_deque_, V element, int (*comparator)(V, V)) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
\
|
||||
if (comparator == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "comparator"); \
|
||||
\
|
||||
for (size_t i = _deque_->front, j = 0; j < _deque_->count; i = (i + 1) % _deque_->count, j++) \
|
||||
{ \
|
||||
if (comparator(_deque_->buffer[i], element) == 0) \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_empty(SNAME *_deque_) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
\
|
||||
return _deque_->count == 0; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_full(SNAME *_deque_) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
\
|
||||
return _deque_->count >= _deque_->capacity; \
|
||||
} \
|
||||
\
|
||||
FMOD size_t PFX##_count(SNAME *_deque_) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
\
|
||||
return _deque_->count; \
|
||||
} \
|
||||
\
|
||||
FMOD size_t PFX##_capacity(SNAME *_deque_) \
|
||||
{ \
|
||||
if (_deque_ == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "_deque_"); \
|
||||
\
|
||||
return _deque_->capacity; \
|
||||
} \
|
||||
\
|
||||
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \
|
||||
{ \
|
||||
SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \
|
||||
\
|
||||
if (!iter) \
|
||||
{ \
|
||||
log_info("%s allocation failed", "Deque Iterator"); \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
PFX##_iter_init(iter, target); \
|
||||
\
|
||||
log_info("Deque Iterator allocated at %p referencing Heap at %p", iter, target); \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_iter_free(SNAME##_iter *iter) \
|
||||
{ \
|
||||
uintptr_t address = (uintptr_t)(void *)iter; \
|
||||
\
|
||||
free(iter); \
|
||||
\
|
||||
log_info("Deque Iterator deallocated at %" PRIxPTR "", address); \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \
|
||||
{ \
|
||||
if (target == NULL) \
|
||||
log_fatal("Heap Iterator at %p initialized with null pointer target", iter); \
|
||||
\
|
||||
if (PFX##_empty(target)) \
|
||||
log_warn("Deque Iterator at %p initialized with empty target", iter); \
|
||||
\
|
||||
iter->target = target; \
|
||||
iter->cursor = target->front; \
|
||||
iter->index = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = PFX##_empty(target); \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_iter_start(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "iter"); \
|
||||
\
|
||||
return PFX##_empty(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_iter_end(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "iter"); \
|
||||
\
|
||||
return PFX##_empty(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "iter"); \
|
||||
\
|
||||
iter->cursor = iter->target->front; \
|
||||
iter->index = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = PFX##_empty(iter->target); \
|
||||
\
|
||||
log_trace("Deque Iterator at %p with cursor at %" PRIuMAX "", iter, iter->cursor); \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "iter"); \
|
||||
\
|
||||
if (PFX##_empty(iter->target)) \
|
||||
iter->cursor = 0; \
|
||||
else \
|
||||
iter->cursor = (iter->target->back == 0) ? iter->target->capacity - 1 : iter->target->back - 1; \
|
||||
\
|
||||
iter->index = iter->target->count - 1; \
|
||||
iter->start = PFX##_empty(iter->target); \
|
||||
iter->end = true; \
|
||||
\
|
||||
log_trace("Deque Iterator at %p with cursor at %" PRIuMAX "", iter, iter->cursor); \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_iter_next(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "iter"); \
|
||||
\
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
iter->start = PFX##_empty(iter->target); \
|
||||
\
|
||||
if (iter->index == iter->target->count - 1) \
|
||||
{ \
|
||||
log_trace("Deque Iterator at %p reached the end of Deque %p", iter, iter->target); \
|
||||
iter->end = true; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
iter->cursor = (iter->cursor + 1) % (iter->target->capacity); \
|
||||
iter->index++; \
|
||||
\
|
||||
log_trace("Deque Iterator at %p moved to %" PRIuMAX "", iter, iter->cursor); \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "iter"); \
|
||||
\
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
iter->end = PFX##_empty(iter->target); \
|
||||
\
|
||||
if (iter->index == 0) \
|
||||
{ \
|
||||
log_trace("Deque Iterator at %p reached the start of Deque %p", iter, iter->target); \
|
||||
iter->start = true; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; \
|
||||
iter->index--; \
|
||||
\
|
||||
log_trace("Deque Iterator at %p moved to %" PRIuMAX "", iter, iter->cursor); \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "iter"); \
|
||||
\
|
||||
if (PFX##_empty(iter->target)) \
|
||||
{ \
|
||||
log_debug("Attempt to access element from iterator %p with empty target %p", iter, iter->target); \
|
||||
PFX##_impl_default_value(); \
|
||||
} \
|
||||
\
|
||||
log_trace("Element access at %" PRIuMAX "", iter->cursor); \
|
||||
\
|
||||
return iter->target->buffer[iter->cursor]; \
|
||||
} \
|
||||
\
|
||||
FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "iter"); \
|
||||
\
|
||||
if (PFX##_empty(iter->target)) \
|
||||
{ \
|
||||
log_debug("Attempt to access element from iterator %p with empty target %p", iter, iter->target); \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
log_trace("Element access at %" PRIuMAX "", iter->cursor); \
|
||||
\
|
||||
return &(iter->target->buffer[iter->cursor]); \
|
||||
} \
|
||||
\
|
||||
FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter == NULL) \
|
||||
log_fatal("Invalid null pointer parameter: %s", "iter"); \
|
||||
\
|
||||
return iter->index; \
|
||||
} \
|
||||
\
|
||||
static bool PFX##_impl_grow(SNAME *_deque_) \
|
||||
{ \
|
||||
size_t new_capacity = _deque_->capacity * 2; \
|
||||
\
|
||||
V *new_buffer = malloc(sizeof(V) * new_capacity); \
|
||||
\
|
||||
if (!new_buffer) \
|
||||
{ \
|
||||
log_info("%s reallocation failed", "Deque buffer"); \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
for (size_t i = _deque_->front, j = 0; j < _deque_->count; i = (i + 1) % _deque_->capacity, j++) \
|
||||
{ \
|
||||
new_buffer[j] = _deque_->buffer[i]; \
|
||||
} \
|
||||
\
|
||||
free(_deque_->buffer); \
|
||||
\
|
||||
_deque_->buffer = new_buffer; \
|
||||
_deque_->capacity = new_capacity; \
|
||||
_deque_->front = 0; \
|
||||
_deque_->back = _deque_->count; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
static SNAME##_iter PFX##_impl_it_start(SNAME *_deque_) \
|
||||
{ \
|
||||
SNAME##_iter iter; \
|
||||
\
|
||||
PFX##_iter_init(&iter, _deque_); \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
static SNAME##_iter PFX##_impl_it_end(SNAME *_deque_) \
|
||||
{ \
|
||||
SNAME##_iter iter; \
|
||||
\
|
||||
PFX##_iter_init(&iter, _deque_); \
|
||||
PFX##_iter_to_end(&iter); \
|
||||
\
|
||||
return iter; \
|
||||
}
|
||||
|
||||
#endif /* CMC_DEQUE_H */
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* ext/cmc/bitset.h
|
||||
*
|
||||
* Creation Date: 08/06/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CMC_EXT_CMC_BITSET_H
|
||||
#define CMC_EXT_CMC_BITSET_H
|
||||
|
||||
#include "../../cor/core.h"
|
||||
|
||||
/**
|
||||
* All the EXT parts of CMC BitSet.
|
||||
*/
|
||||
#define CMC_EXT_CMC_BITSET_PARTS PLACEHOLDER
|
||||
|
||||
#define CMC_EXT_CMC_BITSET_PLACEHOLDER(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_BITSET_PLACEHOLDER_HEADER(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_BITSET_PLACEHOLDER_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_BITSET_PLACEHOLDER_HEADER_(PFX, SNAME, V)
|
||||
#define CMC_EXT_CMC_BITSET_PLACEHOLDER_SOURCE_(PFX, SNAME, V)
|
||||
|
||||
#endif /* CMC_EXT_CMC_BITSET_H */
|
||||
@@ -0,0 +1,426 @@
|
||||
/**
|
||||
* ext/cmc/deque.h
|
||||
*
|
||||
* Creation Date: 25/05/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CMC_EXT_CMC_DEQUE_H
|
||||
#define CMC_EXT_CMC_DEQUE_H
|
||||
|
||||
#include "../../cor/core.h"
|
||||
|
||||
/**
|
||||
* All the EXT parts of CMC Deque.
|
||||
*/
|
||||
#define CMC_EXT_CMC_DEQUE_PARTS INIT, ITER, STR
|
||||
|
||||
/**
|
||||
* INIT
|
||||
*
|
||||
* The part 'INIT' gives a new way of initializing a collection. The collection
|
||||
* struct is not heap allocated, only its internal structure (nodes, buffers).
|
||||
*/
|
||||
#define CMC_EXT_CMC_DEQUE_INIT(PARAMS) \
|
||||
CMC_EXT_CMC_DEQUE_INIT_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_DEQUE_INIT_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_DEQUE_INIT_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_DEQUE_INIT_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_DEQUE_INIT_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_DEQUE_INIT_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_DEQUE_INIT_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
struct SNAME CMC_(PFX, _init)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val); \
|
||||
struct SNAME CMC_(PFX, _init_custom)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val, \
|
||||
struct CMC_ALLOC_NODE_NAME * alloc, struct CMC_CALLBACKS_NAME * callbacks); \
|
||||
void CMC_(PFX, _release)(struct SNAME _deque_);
|
||||
|
||||
#define CMC_EXT_CMC_DEQUE_INIT_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
struct SNAME CMC_(PFX, _init)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val) \
|
||||
{ \
|
||||
return CMC_(PFX, _init_custom)(capacity, f_val, NULL, NULL); \
|
||||
} \
|
||||
\
|
||||
struct SNAME CMC_(PFX, _init_custom)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val, \
|
||||
struct CMC_ALLOC_NODE_NAME * alloc, struct CMC_CALLBACKS_NAME * callbacks) \
|
||||
{ \
|
||||
CMC_CALLBACKS_MAYBE_UNUSED(callbacks); \
|
||||
\
|
||||
struct SNAME _deque_ = { 0 }; \
|
||||
\
|
||||
if (capacity < 1) \
|
||||
return _deque_; \
|
||||
\
|
||||
if (!f_val) \
|
||||
return _deque_; \
|
||||
\
|
||||
if (!alloc) \
|
||||
alloc = &cmc_alloc_node_default; \
|
||||
\
|
||||
_deque_.buffer = alloc->calloc(capacity, sizeof(V)); \
|
||||
\
|
||||
if (!_deque_.buffer) \
|
||||
return _deque_; \
|
||||
\
|
||||
_deque_.capacity = capacity; \
|
||||
_deque_.count = 0; \
|
||||
_deque_.front = 0; \
|
||||
_deque_.back = 0; \
|
||||
_deque_.flag = CMC_FLAG_OK; \
|
||||
_deque_.f_val = f_val; \
|
||||
_deque_.alloc = alloc; \
|
||||
CMC_CALLBACKS_ASSIGN(&_deque_, callbacks); \
|
||||
\
|
||||
return _deque_; \
|
||||
} \
|
||||
\
|
||||
void CMC_(PFX, _release)(struct SNAME _deque_) \
|
||||
{ \
|
||||
if (_deque_.f_val->free) \
|
||||
{ \
|
||||
for (size_t i = _deque_.front, j = 0; j < _deque_.count; j++) \
|
||||
{ \
|
||||
_deque_.f_val->free(_deque_.buffer[i]); \
|
||||
\
|
||||
i = (i + 1) % _deque_.capacity; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
_deque_.alloc->free(_deque_.buffer); \
|
||||
}
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*/
|
||||
#define CMC_EXT_CMC_DEQUE_ITER(PARAMS) \
|
||||
CMC_EXT_CMC_DEQUE_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_DEQUE_ITER_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_DEQUE_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_DEQUE_ITER_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_DEQUE_ITER_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_DEQUE_ITER_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_DEQUE_ITER_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
/* Deque Iterator */ \
|
||||
struct CMC_DEF_ITER(SNAME) \
|
||||
{ \
|
||||
/* Target deque */ \
|
||||
struct SNAME *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; \
|
||||
}; \
|
||||
\
|
||||
/* Iterator Initialization */ \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target); \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target); \
|
||||
/* Iterator State */ \
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
/* Iterator Movement */ \
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index); \
|
||||
/* Iterator Access */ \
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
|
||||
#define CMC_EXT_CMC_DEQUE_ITER_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = target->front; \
|
||||
iter.index = 0; \
|
||||
iter.start = true; \
|
||||
iter.end = CMC_(PFX, _empty)(target); \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
if (iter.target->back == 0) \
|
||||
iter.cursor = iter.target->capacity - 1; \
|
||||
else \
|
||||
iter.cursor = iter.target->back - 1; \
|
||||
\
|
||||
iter.index = iter.target->count - 1; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
iter.cursor = 0; \
|
||||
iter.index = 0; \
|
||||
} \
|
||||
\
|
||||
iter.start = CMC_(PFX, _empty)(target); \
|
||||
iter.end = true; \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->target->front; \
|
||||
iter->index = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = false; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
if (iter->target->back == 0) \
|
||||
iter->cursor = iter->target->capacity - 1; \
|
||||
else \
|
||||
iter->cursor = iter->target->back - 1; \
|
||||
\
|
||||
iter->index = iter->target->count - 1; \
|
||||
\
|
||||
iter->start = false; \
|
||||
iter->end = true; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor = (iter->cursor + 1) % (iter->target->capacity); \
|
||||
iter->index++; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; \
|
||||
iter->index--; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index + steps >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->index += steps; \
|
||||
iter->cursor = (iter->cursor + steps) % iter->target->capacity; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index < steps) \
|
||||
return false; \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->index -= steps; \
|
||||
\
|
||||
/* Prevent underflow */ \
|
||||
if (iter->cursor < steps) \
|
||||
iter->cursor += iter->target->capacity; \
|
||||
\
|
||||
iter->cursor -= steps; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator was able to be positioned at the */ \
|
||||
/* given index */ \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index) \
|
||||
{ \
|
||||
if (index >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index > index) \
|
||||
return CMC_(PFX, _iter_rewind)(iter, iter->index - index); \
|
||||
else if (iter->index < index) \
|
||||
return CMC_(PFX, _iter_advance)(iter, index - iter->index); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (V){ 0 }; \
|
||||
\
|
||||
return iter->target->buffer[iter->cursor]; \
|
||||
} \
|
||||
\
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return NULL; \
|
||||
\
|
||||
return &(iter->target->buffer[iter->cursor]); \
|
||||
} \
|
||||
\
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return iter->index; \
|
||||
}
|
||||
|
||||
/**
|
||||
* STR
|
||||
*/
|
||||
#define CMC_EXT_CMC_DEQUE_STR(PARAMS) \
|
||||
CMC_EXT_CMC_DEQUE_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_DEQUE_STR_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_DEQUE_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_DEQUE_STR_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_DEQUE_STR_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_DEQUE_STR_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_DEQUE_STR_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _deque_, FILE * fptr); \
|
||||
bool CMC_(PFX, _print)(struct SNAME * _deque_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end);
|
||||
|
||||
#define CMC_EXT_CMC_DEQUE_STR_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _deque_, FILE * fptr) \
|
||||
{ \
|
||||
struct SNAME *d_ = _deque_; \
|
||||
\
|
||||
return 0 <= fprintf(fptr, \
|
||||
"struct %s<%s> " \
|
||||
"at %p { " \
|
||||
"buffer:%p, " \
|
||||
"capacity:%" PRIuMAX ", " \
|
||||
"count:%" PRIuMAX ", " \
|
||||
"front:%" PRIuMAX ", " \
|
||||
"back:%" PRIuMAX ", " \
|
||||
"flag:%d, " \
|
||||
"f_val:%p, " \
|
||||
"alloc:%p, " \
|
||||
"callbacks:%p }", \
|
||||
CMC_TO_STRING(SNAME), CMC_TO_STRING(V), d_, d_->buffer, d_->capacity, d_->count, \
|
||||
d_->front, d_->back, d_->flag, d_->f_val, d_->alloc, CMC_CALLBACKS_GET(d_)); \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _print)(struct SNAME * _deque_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end) \
|
||||
{ \
|
||||
fprintf(fptr, "%s", start); \
|
||||
\
|
||||
for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) \
|
||||
{ \
|
||||
if (!_deque_->f_val->str(fptr, _deque_->buffer[i])) \
|
||||
return false; \
|
||||
\
|
||||
i = (i + 1) % _deque_->capacity; \
|
||||
\
|
||||
if (j + 1 < _deque_->count) \
|
||||
fprintf(fptr, "%s", separator); \
|
||||
} \
|
||||
\
|
||||
fprintf(fptr, "%s", end); \
|
||||
\
|
||||
return true; \
|
||||
}
|
||||
|
||||
#endif /* CMC_EXT_CMC_DEQUE_H */
|
||||
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* ext/cmc/hashbidimap.h
|
||||
*
|
||||
* Creation Date: 26/05/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CMC_EXT_CMC_HASHBIDIMAP_H
|
||||
#define CMC_EXT_CMC_HASHBIDIMAP_H
|
||||
|
||||
#include "../../cor/core.h"
|
||||
|
||||
/**
|
||||
* All the EXT parts of CMC HashBidiMap.
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHBIDIMAP_PARTS STR
|
||||
|
||||
/**
|
||||
* STR
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHBIDIMAP_STR(PARAMS) \
|
||||
CMC_EXT_CMC_HASHBIDIMAP_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHBIDIMAP_STR_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_HASHBIDIMAP_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHBIDIMAP_STR_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_K(PARAMS), \
|
||||
CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHBIDIMAP_STR_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_HASHBIDIMAP_STR_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_K(PARAMS), \
|
||||
CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHBIDIMAP_STR_HEADER_(PFX, SNAME, K, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _map_, FILE * fptr); \
|
||||
bool CMC_(PFX, _print)(struct SNAME * _map_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end, const char *key_val_sep);
|
||||
|
||||
#define CMC_EXT_CMC_HASHBIDIMAP_STR_SOURCE_(PFX, SNAME, K, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _map_, FILE * fptr) \
|
||||
{ \
|
||||
struct SNAME *m_ = _map_; \
|
||||
\
|
||||
return 0 <= fprintf(fptr, \
|
||||
"struct %s<%s, %s> " \
|
||||
"at %p { " \
|
||||
"buffer:%p, " \
|
||||
"capacity:%" PRIuMAX ", " \
|
||||
"count:%" PRIuMAX ", " \
|
||||
"load:%lf, " \
|
||||
"flag:%d, " \
|
||||
"f_key:%p, " \
|
||||
"f_val:%p, " \
|
||||
"alloc:%p, " \
|
||||
"callbacks:%p }", \
|
||||
CMC_TO_STRING(SNAME), CMC_TO_STRING(K), CMC_TO_STRING(V), m_, m_->buffer, m_->capacity, \
|
||||
m_->count, m_->load, m_->flag, m_->f_key, m_->f_val, m_->alloc, CMC_CALLBACKS_GET(m_)); \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _print)(struct SNAME * _map_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end, const char *key_val_sep) \
|
||||
{ \
|
||||
fprintf(fptr, "%s", start); \
|
||||
\
|
||||
size_t last = 0; \
|
||||
for (size_t i = _map_->capacity; i > 0; i--) \
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *entry = _map_->buffer[i - 1][0]; \
|
||||
\
|
||||
if (entry && entry != CMC_ENTRY_DELETED) \
|
||||
{ \
|
||||
last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
for (size_t i = 0; i < _map_->capacity; i++) \
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *entry = _map_->buffer[i][0]; \
|
||||
\
|
||||
if (entry && entry != CMC_ENTRY_DELETED) \
|
||||
{ \
|
||||
if (!_map_->f_key->str(fptr, entry->key)) \
|
||||
return false; \
|
||||
\
|
||||
fprintf(fptr, "%s", key_val_sep); \
|
||||
\
|
||||
if (!_map_->f_val->str(fptr, entry->value)) \
|
||||
return false; \
|
||||
\
|
||||
if (i + 1 < last) \
|
||||
fprintf(fptr, "%s", separator); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
fprintf(fptr, "%s", end); \
|
||||
\
|
||||
return true; \
|
||||
}
|
||||
|
||||
#endif /* CMC_EXT_CMC_HASHBIDIMAP_H */
|
||||
@@ -0,0 +1,524 @@
|
||||
/**
|
||||
* ext/cmc/hashmap.h
|
||||
*
|
||||
* Creation Date: 25/05/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CMC_EXT_CMC_HASHMAP_H
|
||||
#define CMC_EXT_CMC_HASHMAP_H
|
||||
|
||||
#include "../../cor/core.h"
|
||||
|
||||
/**
|
||||
* All the EXT parts of CMC HashMap.
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHMAP_PARTS INIT, ITER, STR
|
||||
|
||||
/**
|
||||
* INIT
|
||||
*
|
||||
* The part 'INIT' gives a new way of initializing a collection. The collection
|
||||
* struct is not heap allocated, only its internal structure (nodes, buffers).
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHMAP_INIT(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMAP_INIT_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMAP_INIT_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_HASHMAP_INIT_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMAP_INIT_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_K(PARAMS), \
|
||||
CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHMAP_INIT_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMAP_INIT_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_K(PARAMS), \
|
||||
CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHMAP_INIT_HEADER_(PFX, SNAME, K, V) \
|
||||
\
|
||||
struct SNAME CMC_(PFX, _init)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, \
|
||||
struct CMC_DEF_FVAL(SNAME) * f_val); \
|
||||
struct SNAME CMC_(PFX, _init_custom)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, \
|
||||
struct CMC_DEF_FVAL(SNAME) * f_val, struct CMC_ALLOC_NODE_NAME * alloc, \
|
||||
struct CMC_CALLBACKS_NAME * callbacks); \
|
||||
void CMC_(PFX, _release)(struct SNAME _map_);
|
||||
|
||||
#define CMC_EXT_CMC_HASHMAP_INIT_SOURCE_(PFX, SNAME, K, V) \
|
||||
\
|
||||
struct SNAME CMC_(PFX, _init)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, \
|
||||
struct CMC_DEF_FVAL(SNAME) * f_val) \
|
||||
{ \
|
||||
return CMC_(PFX, _init_custom)(capacity, load, f_key, f_val, NULL, NULL); \
|
||||
} \
|
||||
\
|
||||
struct SNAME CMC_(PFX, _init_custom)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key, \
|
||||
struct CMC_DEF_FVAL(SNAME) * f_val, struct CMC_ALLOC_NODE_NAME * alloc, \
|
||||
struct CMC_CALLBACKS_NAME * callbacks) \
|
||||
{ \
|
||||
CMC_CALLBACKS_MAYBE_UNUSED(callbacks); \
|
||||
\
|
||||
struct SNAME _map_ = { 0 }; \
|
||||
\
|
||||
if (capacity == 0 || load <= 0 || load >= 1) \
|
||||
return _map_; \
|
||||
\
|
||||
/* Prevent integer overflow */ \
|
||||
if (capacity >= UINTMAX_MAX * load) \
|
||||
return _map_; \
|
||||
\
|
||||
if (!f_key || !f_val) \
|
||||
return _map_; \
|
||||
\
|
||||
size_t real_capacity = CMC_(PFX, _impl_calculate_size)(capacity / load); \
|
||||
\
|
||||
if (!alloc) \
|
||||
alloc = &cmc_alloc_node_default; \
|
||||
\
|
||||
_map_.buffer = alloc->calloc(real_capacity, sizeof(struct CMC_DEF_ENTRY(SNAME))); \
|
||||
\
|
||||
if (!_map_.buffer) \
|
||||
return _map_; \
|
||||
\
|
||||
_map_.count = 0; \
|
||||
_map_.capacity = real_capacity; \
|
||||
_map_.load = load; \
|
||||
_map_.flag = CMC_FLAG_OK; \
|
||||
_map_.f_key = f_key; \
|
||||
_map_.f_val = f_val; \
|
||||
_map_.alloc = alloc; \
|
||||
CMC_CALLBACKS_ASSIGN(&_map_, callbacks); \
|
||||
\
|
||||
return _map_; \
|
||||
} \
|
||||
\
|
||||
void CMC_(PFX, _release)(struct SNAME _map_) \
|
||||
{ \
|
||||
if (_map_.f_key->free || _map_.f_val->free) \
|
||||
{ \
|
||||
for (size_t i = 0; i < _map_.capacity; i++) \
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *entry = &(_map_.buffer[i]); \
|
||||
\
|
||||
if (entry->state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
if (_map_.f_key->free) \
|
||||
_map_.f_key->free(entry->key); \
|
||||
if (_map_.f_val->free) \
|
||||
_map_.f_val->free(entry->value); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
_map_.alloc->free(_map_.buffer); \
|
||||
}
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHMAP_ITER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMAP_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMAP_ITER_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_HASHMAP_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMAP_ITER_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_K(PARAMS), \
|
||||
CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHMAP_ITER_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMAP_ITER_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_K(PARAMS), \
|
||||
CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHMAP_ITER_HEADER_(PFX, SNAME, K, V) \
|
||||
\
|
||||
/* HashMap Iterator */ \
|
||||
struct CMC_DEF_ITER(SNAME) \
|
||||
{ \
|
||||
/* Target hashmap */ \
|
||||
struct SNAME *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; \
|
||||
}; \
|
||||
\
|
||||
/* Iterator Initialization */ \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target); \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target); \
|
||||
/* Iterator State */ \
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
/* Iterator Movement */ \
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index); \
|
||||
/* Iterator Access */ \
|
||||
K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
|
||||
#define CMC_EXT_CMC_HASHMAP_ITER_SOURCE_(PFX, SNAME, K, V) \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = 0; \
|
||||
iter.index = 0; \
|
||||
iter.first = 0; \
|
||||
iter.last = 0; \
|
||||
iter.start = true; \
|
||||
iter.end = CMC_(PFX, _empty)(target); \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
for (size_t i = 0; i < target->capacity; i++) \
|
||||
{ \
|
||||
if (target->buffer[i].state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.first = i; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
iter.cursor = iter.first; \
|
||||
\
|
||||
for (size_t i = target->capacity; i > 0; i--) \
|
||||
{ \
|
||||
if (target->buffer[i - 1].state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = 0; \
|
||||
iter.index = 0; \
|
||||
iter.first = 0; \
|
||||
iter.last = 0; \
|
||||
iter.start = CMC_(PFX, _empty)(target); \
|
||||
iter.end = true; \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
for (size_t i = 0; i < target->capacity; i++) \
|
||||
{ \
|
||||
if (target->buffer[i].state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.first = i; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
for (size_t i = target->capacity; i > 0; i--) \
|
||||
{ \
|
||||
if (target->buffer[i - 1].state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
iter.cursor = iter.last; \
|
||||
iter.index = target->count - 1; \
|
||||
} \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->first; \
|
||||
iter->index = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->last; \
|
||||
iter->index = iter->target->count - 1; \
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
iter->end = true; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
struct CMC_DEF_ENTRY(SNAME) *scan = &(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
iter->index++; \
|
||||
\
|
||||
while (1) \
|
||||
{ \
|
||||
iter->cursor++; \
|
||||
scan = &(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
if (scan->state == CMC_ES_FILLED) \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
struct CMC_DEF_ENTRY(SNAME) *scan = &(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
iter->index--; \
|
||||
\
|
||||
while (1) \
|
||||
{ \
|
||||
iter->cursor--; \
|
||||
scan = &(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
if (scan->state == CMC_ES_FILLED) \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index + steps >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
CMC_(PFX, _iter_next)(iter); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index < steps) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
CMC_(PFX, _iter_prev)(iter); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator was able to be positioned at the */ \
|
||||
/* given index */ \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index) \
|
||||
{ \
|
||||
if (index >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index > index) \
|
||||
return CMC_(PFX, _iter_rewind)(iter, iter->index - index); \
|
||||
else if (iter->index < index) \
|
||||
return CMC_(PFX, _iter_advance)(iter, index - iter->index); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (K){ 0 }; \
|
||||
\
|
||||
return iter->target->buffer[iter->cursor].key; \
|
||||
} \
|
||||
\
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (V){ 0 }; \
|
||||
\
|
||||
return iter->target->buffer[iter->cursor].value; \
|
||||
} \
|
||||
\
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return NULL; \
|
||||
\
|
||||
return &(iter->target->buffer[iter->cursor].value); \
|
||||
} \
|
||||
\
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return iter->index; \
|
||||
}
|
||||
|
||||
/**
|
||||
* STR
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHMAP_STR(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMAP_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMAP_STR_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_HASHMAP_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMAP_STR_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_K(PARAMS), \
|
||||
CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHMAP_STR_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMAP_STR_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_K(PARAMS), \
|
||||
CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHMAP_STR_HEADER_(PFX, SNAME, K, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _map_, FILE * fptr); \
|
||||
bool CMC_(PFX, _print)(struct SNAME * _map_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end, const char *key_val_sep);
|
||||
|
||||
#define CMC_EXT_CMC_HASHMAP_STR_SOURCE_(PFX, SNAME, K, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _map_, FILE * fptr) \
|
||||
{ \
|
||||
struct SNAME *m_ = _map_; \
|
||||
\
|
||||
return 0 <= fprintf(fptr, \
|
||||
"struct %s<%s, %s> " \
|
||||
"at %p { " \
|
||||
"buffer:%p, " \
|
||||
"capacity:%" PRIuMAX ", " \
|
||||
"count:%" PRIuMAX ", " \
|
||||
"load:%lf, " \
|
||||
"flag:%d, " \
|
||||
"f_key:%p, " \
|
||||
"f_val:%p, " \
|
||||
"alloc:%p, " \
|
||||
"callbacks:%p }", \
|
||||
CMC_TO_STRING(SNAME), CMC_TO_STRING(K), CMC_TO_STRING(V), m_, m_->buffer, m_->capacity, \
|
||||
m_->count, m_->load, m_->flag, m_->f_key, m_->f_val, m_->alloc, CMC_CALLBACKS_GET(m_)); \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _print)(struct SNAME * _map_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end, const char *key_val_sep) \
|
||||
{ \
|
||||
fprintf(fptr, "%s", start); \
|
||||
\
|
||||
size_t last = 0; \
|
||||
for (size_t i = _map_->capacity; i > 0; i--) \
|
||||
{ \
|
||||
if ((_map_->buffer[i - 1]).state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
for (size_t i = 0; i < _map_->capacity; i++) \
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *entry = &(_map_->buffer[i]); \
|
||||
\
|
||||
if (entry->state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
if (!_map_->f_key->str(fptr, entry->key)) \
|
||||
return false; \
|
||||
\
|
||||
fprintf(fptr, "%s", key_val_sep); \
|
||||
\
|
||||
if (!_map_->f_val->str(fptr, entry->value)) \
|
||||
return false; \
|
||||
\
|
||||
if (i + 1 < last) \
|
||||
fprintf(fptr, "%s", separator); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
fprintf(fptr, "%s", end); \
|
||||
\
|
||||
return true; \
|
||||
}
|
||||
|
||||
#endif /* CMC_EXT_CMC_HASHMAP_H */
|
||||
@@ -0,0 +1,457 @@
|
||||
/**
|
||||
* ext/cmc/hashmultimap.h
|
||||
*
|
||||
* Creation Date: 29/05/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CMC_EXT_CMC_HASHMULTIMAP_H
|
||||
#define CMC_EXT_CMC_HASHMULTIMAP_H
|
||||
|
||||
#include "../../cor/core.h"
|
||||
|
||||
/**
|
||||
* All the EXT parts of CMC HashMultiMap.
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHMULTIMAP_PARTS ITER, STR
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHMULTIMAP_ITER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMULTIMAP_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMULTIMAP_ITER_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTIMAP_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMULTIMAP_ITER_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_K(PARAMS), \
|
||||
CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTIMAP_ITER_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMULTIMAP_ITER_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_K(PARAMS), \
|
||||
CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTIMAP_ITER_HEADER_(PFX, SNAME, K, V) \
|
||||
\
|
||||
/* HashMultiMap Iterator */ \
|
||||
struct CMC_DEF_ITER(SNAME) \
|
||||
{ \
|
||||
/* Target hashmultimap */ \
|
||||
struct SNAME *target; \
|
||||
\
|
||||
/* Current entry */ \
|
||||
struct CMC_DEF_ENTRY(SNAME) * curr_entry; \
|
||||
\
|
||||
/* 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; \
|
||||
}; \
|
||||
\
|
||||
/* Iterator Initialization */ \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target); \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target); \
|
||||
/* Iterator State */ \
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
/* Iterator Movement */ \
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index); \
|
||||
/* Iterator Access */ \
|
||||
K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTIMAP_ITER_SOURCE_(PFX, SNAME, K, V) \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.curr_entry = NULL; \
|
||||
iter.cursor = 0; \
|
||||
iter.index = 0; \
|
||||
iter.first = 0; \
|
||||
iter.last = 0; \
|
||||
iter.start = true; \
|
||||
iter.end = CMC_(PFX, _empty)(target); \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
for (size_t i = 0; i < target->capacity; i++) \
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i][0]; \
|
||||
\
|
||||
if (entry && entry != CMC_ENTRY_DELETED) \
|
||||
{ \
|
||||
iter.curr_entry = target->buffer[i][0]; \
|
||||
iter.first = i; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
iter.cursor = iter.first; \
|
||||
\
|
||||
for (size_t i = target->capacity; i > 0; i--) \
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i - 1][1]; \
|
||||
\
|
||||
if (entry && entry != CMC_ENTRY_DELETED) \
|
||||
{ \
|
||||
iter.last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.curr_entry = NULL; \
|
||||
iter.cursor = 0; \
|
||||
iter.index = 0; \
|
||||
iter.first = 0; \
|
||||
iter.last = 0; \
|
||||
iter.start = CMC_(PFX, _empty)(target); \
|
||||
iter.end = true; \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
for (size_t i = 0; i < target->capacity; i++) \
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i][0]; \
|
||||
\
|
||||
if (entry && entry != CMC_ENTRY_DELETED) \
|
||||
{ \
|
||||
iter.first = i; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
for (size_t i = target->capacity; i > 0; i--) \
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *entry = target->buffer[i - 1][1]; \
|
||||
\
|
||||
if (entry && entry != CMC_ENTRY_DELETED) \
|
||||
{ \
|
||||
iter.curr_entry = target->buffer[i - 1][1]; \
|
||||
iter.last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
iter.cursor = iter.last; \
|
||||
iter.index = target->count - 1; \
|
||||
} \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->first; \
|
||||
iter->index = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
iter->curr_entry = iter->target->buffer[iter->first][0]; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->last; \
|
||||
iter->index = iter->target->count - 1; \
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
iter->end = true; \
|
||||
iter->curr_entry = iter->target->buffer[iter->last][1]; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->curr_entry->next != NULL) \
|
||||
{ \
|
||||
iter->curr_entry = iter->curr_entry->next; \
|
||||
iter->index++; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (iter->cursor == iter->last) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->cursor++; \
|
||||
\
|
||||
while (iter->target->buffer[iter->cursor][0] == NULL) \
|
||||
iter->cursor++; \
|
||||
\
|
||||
iter->curr_entry = iter->target->buffer[iter->cursor][0]; \
|
||||
\
|
||||
iter->index++; \
|
||||
} \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->curr_entry->prev != NULL) \
|
||||
{ \
|
||||
iter->curr_entry = iter->curr_entry->prev; \
|
||||
iter->index--; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (iter->cursor == iter->first) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->cursor--; \
|
||||
\
|
||||
while (iter->target->buffer[iter->cursor][1] == NULL) \
|
||||
iter->cursor--; \
|
||||
\
|
||||
iter->curr_entry = iter->target->buffer[iter->cursor][1]; \
|
||||
\
|
||||
iter->index--; \
|
||||
} \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index + steps >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
CMC_(PFX, _iter_next)(iter); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index < steps) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
CMC_(PFX, _iter_prev)(iter); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator was able to be positioned at the */ \
|
||||
/* given index */ \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index) \
|
||||
{ \
|
||||
if (index >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index > index) \
|
||||
return CMC_(PFX, _iter_rewind)(iter, iter->index - index); \
|
||||
else if (iter->index < index) \
|
||||
return CMC_(PFX, _iter_advance)(iter, index - iter->index); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (K){ 0 }; \
|
||||
\
|
||||
return iter->curr_entry->key; \
|
||||
} \
|
||||
\
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (V){ 0 }; \
|
||||
\
|
||||
return iter->curr_entry->value; \
|
||||
} \
|
||||
\
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return NULL; \
|
||||
\
|
||||
return &(iter->curr_entry->value); \
|
||||
} \
|
||||
\
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return iter->index; \
|
||||
}
|
||||
|
||||
/**
|
||||
* STR
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHMULTIMAP_STR(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMULTIMAP_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMULTIMAP_STR_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTIMAP_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMULTIMAP_STR_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_K(PARAMS), \
|
||||
CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTIMAP_STR_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMULTIMAP_STR_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_K(PARAMS), \
|
||||
CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTIMAP_STR_HEADER_(PFX, SNAME, K, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _map_, FILE * fptr); \
|
||||
bool CMC_(PFX, _print)(struct SNAME * _map_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end, const char *key_val_sep);
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTIMAP_STR_SOURCE_(PFX, SNAME, K, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _map_, FILE * fptr) \
|
||||
{ \
|
||||
struct SNAME *m_ = _map_; \
|
||||
\
|
||||
return 0 <= fprintf(fptr, \
|
||||
"struct %s<%s, %s> " \
|
||||
"at %p { " \
|
||||
"buffer:%p, " \
|
||||
"capacity:%" PRIuMAX ", " \
|
||||
"count:%" PRIuMAX ", " \
|
||||
"load:%lf, " \
|
||||
"flag:%d, " \
|
||||
"f_key:%p, " \
|
||||
"f_val:%p, " \
|
||||
"alloc:%p, " \
|
||||
"callbacks:%p }", \
|
||||
CMC_TO_STRING(SNAME), CMC_TO_STRING(K), CMC_TO_STRING(V), m_, m_->buffer, m_->capacity, \
|
||||
m_->count, m_->load, m_->flag, m_->f_key, m_->f_val, m_->alloc, CMC_CALLBACKS_GET(m_)); \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _print)(struct SNAME * _map_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end, const char *key_val_sep) \
|
||||
{ \
|
||||
fprintf(fptr, "%s", start); \
|
||||
\
|
||||
size_t last = 0; \
|
||||
for (size_t i = _map_->capacity; i > 0; i--) \
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *entry = _map_->buffer[i - 1][1]; \
|
||||
\
|
||||
if (entry && entry != CMC_ENTRY_DELETED) \
|
||||
{ \
|
||||
last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
for (size_t i = 0; i < _map_->capacity; i++) \
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *scan = _map_->buffer[i][0]; \
|
||||
\
|
||||
while (scan != NULL) \
|
||||
{ \
|
||||
if (!_map_->f_key->str(fptr, scan->key)) \
|
||||
return false; \
|
||||
\
|
||||
fprintf(fptr, "%s", key_val_sep); \
|
||||
\
|
||||
if (!_map_->f_val->str(fptr, scan->value)) \
|
||||
return false; \
|
||||
\
|
||||
scan = scan->next; \
|
||||
\
|
||||
if (i + 1 < last) \
|
||||
fprintf(fptr, "%s", separator); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
fprintf(fptr, "%s", end); \
|
||||
\
|
||||
return true; \
|
||||
}
|
||||
|
||||
#endif /* CMC_EXT_CMC_HASHMULTIMAP_H */
|
||||
@@ -0,0 +1,698 @@
|
||||
/**
|
||||
* ext/cmc/hashmultiset.h
|
||||
*
|
||||
* Creation Date: 30/05/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CMC_EXT_CMC_HASHMULTISET_H
|
||||
#define CMC_EXT_CMC_HASHMULTISET_H
|
||||
|
||||
#include "../../cor/core.h"
|
||||
|
||||
/**
|
||||
* All the EXT parts of CMC HashMultiSet.
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHMULTISET_PARTS ITER, SETF, STR
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHMULTISET_ITER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMULTISET_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMULTISET_ITER_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTISET_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMULTISET_ITER_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTISET_ITER_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMULTISET_ITER_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTISET_ITER_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
/* HashMultiSet Iterator */ \
|
||||
struct CMC_DEF_ITER(SNAME) \
|
||||
{ \
|
||||
/* Target HashMultiset */ \
|
||||
struct SNAME *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; \
|
||||
}; \
|
||||
\
|
||||
/* Iterator Initialization */ \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target); \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target); \
|
||||
/* Iterator State */ \
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
/* Iterator Movement */ \
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index); \
|
||||
/* Iterator Access */ \
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
size_t CMC_(PFX, _iter_multiplicity)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTISET_ITER_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = 0; \
|
||||
iter.index = 0; \
|
||||
iter.first = 0; \
|
||||
iter.last = 0; \
|
||||
iter.start = true; \
|
||||
iter.end = CMC_(PFX, _empty)(target); \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
for (size_t i = 0; i < target->capacity; i++) \
|
||||
{ \
|
||||
if (target->buffer[i].state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.first = i; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
iter.cursor = iter.first; \
|
||||
\
|
||||
for (size_t i = target->capacity; i > 0; i--) \
|
||||
{ \
|
||||
if (target->buffer[i - 1].state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = 0; \
|
||||
iter.index = 0; \
|
||||
iter.first = 0; \
|
||||
iter.last = 0; \
|
||||
iter.start = CMC_(PFX, _empty)(target); \
|
||||
iter.end = true; \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
for (size_t i = 0; i < target->capacity; i++) \
|
||||
{ \
|
||||
if (target->buffer[i].state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.first = i; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
for (size_t i = target->capacity; i > 0; i--) \
|
||||
{ \
|
||||
if (target->buffer[i - 1].state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
iter.cursor = iter.last; \
|
||||
iter.index = target->count - 1; \
|
||||
} \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->first; \
|
||||
iter->index = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->last; \
|
||||
iter->index = iter->target->count - 1; \
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
iter->end = true; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
struct CMC_DEF_ENTRY(SNAME) *scan = &(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
iter->index++; \
|
||||
\
|
||||
while (1) \
|
||||
{ \
|
||||
iter->cursor++; \
|
||||
scan = &(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
if (scan->state == CMC_ES_FILLED) \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
struct CMC_DEF_ENTRY(SNAME) *scan = &(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
iter->index--; \
|
||||
\
|
||||
while (1) \
|
||||
{ \
|
||||
iter->cursor--; \
|
||||
scan = &(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
if (scan->state == CMC_ES_FILLED) \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index + steps >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
CMC_(PFX, _iter_next)(iter); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index < steps) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
CMC_(PFX, _iter_prev)(iter); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator was able to be positioned at the */ \
|
||||
/* given index */ \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index) \
|
||||
{ \
|
||||
if (index >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index > index) \
|
||||
return CMC_(PFX, _iter_rewind)(iter, iter->index - index); \
|
||||
else if (iter->index < index) \
|
||||
return CMC_(PFX, _iter_advance)(iter, index - iter->index); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (V){ 0 }; \
|
||||
\
|
||||
return iter->target->buffer[iter->cursor].value; \
|
||||
} \
|
||||
\
|
||||
size_t CMC_(PFX, _iter_multiplicity)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return 0; \
|
||||
\
|
||||
return iter->target->buffer[iter->cursor].multiplicity; \
|
||||
} \
|
||||
\
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return iter->index; \
|
||||
}
|
||||
|
||||
/**
|
||||
* SETF
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHMULTISET_SETF(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMULTISET_SETF_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMULTISET_SETF_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTISET_SETF_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMULTISET_SETF_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTISET_SETF_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMULTISET_SETF_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTISET_SETF_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
/* Set Operations */ \
|
||||
struct SNAME *CMC_(PFX, _union)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
struct SNAME *CMC_(PFX, _intersection)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
struct SNAME *CMC_(PFX, _difference)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
struct SNAME *CMC_(PFX, _summation)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
struct SNAME *CMC_(PFX, _symmetric_difference)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_subset)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_superset)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_proper_subset)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_proper_superset)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_disjointset)(struct SNAME * _set1_, struct SNAME * _set2_);
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTISET_SETF_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _union)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
return NULL; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter1 = CMC_(PFX, _iter_start)(_set1_); \
|
||||
struct CMC_DEF_ITER(SNAME) iter2 = CMC_(PFX, _iter_start)(_set2_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter1); CMC_(PFX, _iter_next)(&iter1)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter1); \
|
||||
\
|
||||
size_t m1 = CMC_(PFX, _iter_multiplicity)(&iter1); \
|
||||
size_t m2 = CMC_(PFX, _impl_multiplicity_of)(_set2_, value); \
|
||||
size_t max_ = m1 > m2 ? m1 : m2; \
|
||||
\
|
||||
CMC_(PFX, _update)(_set_r_, value, max_); \
|
||||
} \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter2); CMC_(PFX, _iter_next)(&iter2)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter2); \
|
||||
\
|
||||
size_t m1 = CMC_(PFX, _impl_multiplicity_of)(_set1_, value); \
|
||||
size_t m2 = CMC_(PFX, _iter_multiplicity)(&iter2); \
|
||||
size_t max_ = m1 > m2 ? m1 : m2; \
|
||||
\
|
||||
CMC_(PFX, _update)(_set_r_, value, max_); \
|
||||
} \
|
||||
\
|
||||
CMC_CALLBACKS_ASSIGN(_set_r_, _set1_->callbacks); \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _intersection)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
return NULL; \
|
||||
\
|
||||
struct SNAME *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; \
|
||||
struct SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set_A_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
size_t m1 = CMC_(PFX, _iter_multiplicity)(&iter); \
|
||||
size_t m2 = CMC_(PFX, _impl_multiplicity_of)(_set_B_, value); \
|
||||
size_t max_ = m1 < m2 ? m1 : m2; \
|
||||
\
|
||||
CMC_(PFX, _update)(_set_r_, value, max_); \
|
||||
} \
|
||||
\
|
||||
CMC_CALLBACKS_ASSIGN(_set_r_, _set1_->callbacks); \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _difference)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
return NULL; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
size_t m1 = CMC_(PFX, _iter_multiplicity)(&iter); \
|
||||
size_t m2 = CMC_(PFX, _impl_multiplicity_of)(_set2_, value); \
|
||||
\
|
||||
if (m1 > m2) \
|
||||
CMC_(PFX, _update)(_set_r_, value, m1 - m2); \
|
||||
} \
|
||||
\
|
||||
CMC_CALLBACKS_ASSIGN(_set_r_, _set1_->callbacks); \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _summation)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
return NULL; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter1 = CMC_(PFX, _iter_start)(_set1_); \
|
||||
struct CMC_DEF_ITER(SNAME) iter2 = CMC_(PFX, _iter_start)(_set2_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter1); CMC_(PFX, _iter_next)(&iter1)) \
|
||||
{ \
|
||||
CMC_(PFX, _insert_many) \
|
||||
(_set_r_, CMC_(PFX, _iter_value)(&iter1), CMC_(PFX, _iter_multiplicity)(&iter1)); \
|
||||
} \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter2); CMC_(PFX, _iter_next)(&iter2)) \
|
||||
{ \
|
||||
CMC_(PFX, _insert_many) \
|
||||
(_set_r_, CMC_(PFX, _iter_value)(&iter2), CMC_(PFX, _iter_multiplicity)(&iter2)); \
|
||||
} \
|
||||
\
|
||||
CMC_CALLBACKS_ASSIGN(_set_r_, _set1_->callbacks); \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _symmetric_difference)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
return NULL; \
|
||||
struct CMC_DEF_ITER(SNAME) iter1 = CMC_(PFX, _iter_start)(_set1_); \
|
||||
struct CMC_DEF_ITER(SNAME) iter2 = CMC_(PFX, _iter_start)(_set2_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter1); CMC_(PFX, _iter_next)(&iter1)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter1); \
|
||||
\
|
||||
size_t m1 = CMC_(PFX, _iter_multiplicity)(&iter1); \
|
||||
size_t m2 = CMC_(PFX, _impl_multiplicity_of)(_set2_, value); \
|
||||
\
|
||||
if (m1 != m2) \
|
||||
{ \
|
||||
if (m1 > m2) \
|
||||
CMC_(PFX, _update)(_set_r_, value, m1 - m2); \
|
||||
else \
|
||||
CMC_(PFX, _update)(_set_r_, value, m2 - m1); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter2); CMC_(PFX, _iter_next)(&iter2)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter2); \
|
||||
\
|
||||
size_t m1 = CMC_(PFX, _impl_multiplicity_of)(_set1_, value); \
|
||||
size_t m2 = CMC_(PFX, _iter_multiplicity)(&iter2); \
|
||||
\
|
||||
if (m1 != m2) \
|
||||
{ \
|
||||
if (m1 > m2) \
|
||||
CMC_(PFX, _update)(_set_r_, value, m1 - m2); \
|
||||
else \
|
||||
CMC_(PFX, _update)(_set_r_, value, m2 - m1); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
CMC_CALLBACKS_ASSIGN(_set_r_, _set1_->callbacks); \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _is_subset)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
if (_set1_->count > _set2_->count) \
|
||||
return false; \
|
||||
\
|
||||
if (CMC_(PFX, _empty)(_set1_)) \
|
||||
return true; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
size_t m1 = CMC_(PFX, _iter_multiplicity)(&iter); \
|
||||
size_t m2 = CMC_(PFX, _impl_multiplicity_of)(_set2_, value); \
|
||||
\
|
||||
if (m1 > m2) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _is_superset)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
return CMC_(PFX, _is_subset)(_set2_, _set1_); \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _is_proper_subset)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
if (_set1_->count >= _set2_->count) \
|
||||
return false; \
|
||||
\
|
||||
if (CMC_(PFX, _empty)(_set1_)) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(_set2_)) \
|
||||
return true; \
|
||||
else \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
size_t m1 = CMC_(PFX, _iter_multiplicity)(&iter); \
|
||||
size_t m2 = CMC_(PFX, _impl_multiplicity_of)(_set2_, value); \
|
||||
\
|
||||
if (m1 >= m2) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _is_proper_superset)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
return CMC_(PFX, _is_proper_subset)(_set2_, _set1_); \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _is_disjointset)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(_set1_)) \
|
||||
return true; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_entry)(_set2_, value) != NULL) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
}
|
||||
|
||||
/**
|
||||
* STR
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHMULTISET_STR(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMULTISET_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMULTISET_STR_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTISET_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMULTISET_STR_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTISET_STR_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_HASHMULTISET_STR_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTISET_STR_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _set_, FILE * fptr); \
|
||||
bool CMC_(PFX, _print)(struct SNAME * _set_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end, const char *key_val_sep);
|
||||
|
||||
#define CMC_EXT_CMC_HASHMULTISET_STR_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _set_, FILE * fptr) \
|
||||
{ \
|
||||
struct SNAME *s_ = _set_; \
|
||||
\
|
||||
return 0 <= fprintf(fptr, \
|
||||
"struct %s<%s> " \
|
||||
"at %p { " \
|
||||
"buffer:%p, " \
|
||||
"capacity:%" PRIuMAX ", " \
|
||||
"count:%" PRIuMAX ", " \
|
||||
"cardinality:%" PRIuMAX ", " \
|
||||
"load:%lf, " \
|
||||
"flag:%d, " \
|
||||
"f_val:%p, " \
|
||||
"alloc:%p, " \
|
||||
"callbacks:%p }", \
|
||||
CMC_TO_STRING(SNAME), CMC_TO_STRING(V), s_, s_->buffer, s_->capacity, s_->count, \
|
||||
s_->cardinality, s_->load, s_->flag, s_->f_val, s_->alloc, CMC_CALLBACKS_GET(s_)); \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _print)(struct SNAME * _set_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end, const char *val_mul_sep) \
|
||||
{ \
|
||||
fprintf(fptr, "%s", start); \
|
||||
\
|
||||
size_t last = 0; \
|
||||
for (size_t i = _set_->capacity; i > 0; i--) \
|
||||
{ \
|
||||
if ((_set_->buffer[i - 1]).state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
for (size_t i = 0; i < _set_->capacity; i++) \
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *entry = &(_set_->buffer[i]); \
|
||||
\
|
||||
if (entry->state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
if (!_set_->f_val->str(fptr, entry->value)) \
|
||||
return false; \
|
||||
\
|
||||
fprintf(fptr, "%s", val_mul_sep); \
|
||||
\
|
||||
if (fprintf(fptr, "%" PRIuMAX "", entry->multiplicity) < 0) \
|
||||
return false; \
|
||||
\
|
||||
if (i + 1 < last) \
|
||||
fprintf(fptr, "%s", separator); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
fprintf(fptr, "%s", end); \
|
||||
\
|
||||
return true; \
|
||||
}
|
||||
|
||||
#endif /* CMC_EXT_CMC_HASHMULTISET_H */
|
||||
@@ -0,0 +1,666 @@
|
||||
/**
|
||||
* ext/cmc/hashset.h
|
||||
*
|
||||
* Creation Date: 29/05/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CMC_EXT_CMC_HASHSET_H
|
||||
#define CMC_EXT_CMC_HASHSET_H
|
||||
|
||||
#include "../../cor/core.h"
|
||||
|
||||
/**
|
||||
* All the EXT parts of CMC HashSet.
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHSET_PARTS ITER, SETF, STR
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHSET_ITER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHSET_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHSET_ITER_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_HASHSET_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHSET_ITER_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHSET_ITER_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_HASHSET_ITER_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHSET_ITER_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
/* HashSet Iterator */ \
|
||||
struct CMC_DEF_ITER(SNAME) \
|
||||
{ \
|
||||
/* Target HashSet */ \
|
||||
struct SNAME *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; \
|
||||
}; \
|
||||
\
|
||||
/* Iterator Initialization */ \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target); \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target); \
|
||||
/* Iterator State */ \
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
/* Iterator Movement */ \
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index); \
|
||||
/* Iterator Access */ \
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
|
||||
#define CMC_EXT_CMC_HASHSET_ITER_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = 0; \
|
||||
iter.index = 0; \
|
||||
iter.first = 0; \
|
||||
iter.last = 0; \
|
||||
iter.start = true; \
|
||||
iter.end = CMC_(PFX, _empty)(target); \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
for (size_t i = 0; i < target->capacity; i++) \
|
||||
{ \
|
||||
if (target->buffer[i].state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.first = i; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
iter.cursor = iter.first; \
|
||||
\
|
||||
for (size_t i = target->capacity; i > 0; i--) \
|
||||
{ \
|
||||
if (target->buffer[i - 1].state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = 0; \
|
||||
iter.index = 0; \
|
||||
iter.first = 0; \
|
||||
iter.last = 0; \
|
||||
iter.start = CMC_(PFX, _empty)(target); \
|
||||
iter.end = true; \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
for (size_t i = 0; i < target->capacity; i++) \
|
||||
{ \
|
||||
if (target->buffer[i].state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.first = i; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
for (size_t i = target->capacity; i > 0; i--) \
|
||||
{ \
|
||||
if (target->buffer[i - 1].state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
iter.last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
iter.cursor = iter.last; \
|
||||
iter.index = target->count - 1; \
|
||||
} \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->first; \
|
||||
iter->index = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->last; \
|
||||
iter->index = iter->target->count - 1; \
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
iter->end = true; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
struct CMC_DEF_ENTRY(SNAME) *scan = &(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
iter->index++; \
|
||||
\
|
||||
while (1) \
|
||||
{ \
|
||||
iter->cursor++; \
|
||||
scan = &(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
if (scan->state == CMC_ES_FILLED) \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
struct CMC_DEF_ENTRY(SNAME) *scan = &(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
iter->index--; \
|
||||
\
|
||||
while (1) \
|
||||
{ \
|
||||
iter->cursor--; \
|
||||
scan = &(iter->target->buffer[iter->cursor]); \
|
||||
\
|
||||
if (scan->state == CMC_ES_FILLED) \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index + steps >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
CMC_(PFX, _iter_next)(iter); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index < steps) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
CMC_(PFX, _iter_prev)(iter); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator was able to be positioned at the */ \
|
||||
/* given index */ \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index) \
|
||||
{ \
|
||||
if (index >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index > index) \
|
||||
return CMC_(PFX, _iter_rewind)(iter, iter->index - index); \
|
||||
else if (iter->index < index) \
|
||||
return CMC_(PFX, _iter_advance)(iter, index - iter->index); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (V){ 0 }; \
|
||||
\
|
||||
return iter->target->buffer[iter->cursor].value; \
|
||||
} \
|
||||
\
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return iter->index; \
|
||||
}
|
||||
|
||||
/**
|
||||
* SETF
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHSET_SETF(PARAMS) \
|
||||
CMC_EXT_CMC_HASHSET_SETF_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHSET_SETF_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_HASHSET_SETF_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHSET_SETF_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHSET_SETF_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_HASHSET_SETF_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHSET_SETF_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
/* Set Operations */ \
|
||||
struct SNAME *CMC_(PFX, _union)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
struct SNAME *CMC_(PFX, _intersection)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
struct SNAME *CMC_(PFX, _difference)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
struct SNAME *CMC_(PFX, _symmetric_difference)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_subset)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_superset)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_proper_subset)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_proper_superset)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_disjointset)(struct SNAME * _set1_, struct SNAME * _set2_);
|
||||
|
||||
#define CMC_EXT_CMC_HASHSET_SETF_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _union)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
{ \
|
||||
_set1_->flag = CMC_FLAG_ALLOC; \
|
||||
_set2_->flag = CMC_FLAG_ALLOC; \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter1 = CMC_(PFX, _iter_start)(_set1_); \
|
||||
struct CMC_DEF_ITER(SNAME) iter2 = CMC_(PFX, _iter_start)(_set2_); \
|
||||
\
|
||||
/* TODO turn this into a normal loop and check for errors */ \
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter1); CMC_(PFX, _iter_next)(&iter1)) \
|
||||
{ \
|
||||
CMC_(PFX, _insert)(_set_r_, CMC_(PFX, _iter_value)(&iter1)); \
|
||||
} \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter2); CMC_(PFX, _iter_next)(&iter2)) \
|
||||
{ \
|
||||
CMC_(PFX, _insert)(_set_r_, CMC_(PFX, _iter_value)(&iter2)); \
|
||||
} \
|
||||
\
|
||||
CMC_CALLBACKS_ASSIGN(_set_r_, _set1_->callbacks); \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _intersection)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
{ \
|
||||
_set1_->flag = CMC_FLAG_ALLOC; \
|
||||
_set2_->flag = CMC_FLAG_ALLOC; \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; \
|
||||
struct SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set_A_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_entry)(_set_B_, value) != NULL) \
|
||||
CMC_(PFX, _insert)(_set_r_, value); \
|
||||
} \
|
||||
\
|
||||
CMC_CALLBACKS_ASSIGN(_set_r_, _set1_->callbacks); \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _difference)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
{ \
|
||||
_set1_->flag = CMC_FLAG_ALLOC; \
|
||||
_set2_->flag = CMC_FLAG_ALLOC; \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_entry)(_set2_, value) == NULL) \
|
||||
CMC_(PFX, _insert)(_set_r_, value); \
|
||||
} \
|
||||
\
|
||||
CMC_CALLBACKS_ASSIGN(_set_r_, _set1_->callbacks); \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _symmetric_difference)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* Callbacks are added later */ \
|
||||
struct SNAME *_set_r_ = \
|
||||
CMC_(PFX, _new_custom)(_set1_->capacity, _set1_->load, _set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
{ \
|
||||
_set1_->flag = CMC_FLAG_ALLOC; \
|
||||
_set2_->flag = CMC_FLAG_ALLOC; \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter1 = CMC_(PFX, _iter_start)(_set1_); \
|
||||
struct CMC_DEF_ITER(SNAME) iter2 = CMC_(PFX, _iter_start)(_set2_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter1); CMC_(PFX, _iter_next)(&iter1)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter1); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_entry)(_set2_, value) == NULL) \
|
||||
CMC_(PFX, _insert)(_set_r_, value); \
|
||||
} \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter2); CMC_(PFX, _iter_next)(&iter2)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter2); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_entry)(_set1_, value) == NULL) \
|
||||
CMC_(PFX, _insert)(_set_r_, value); \
|
||||
} \
|
||||
\
|
||||
CMC_CALLBACKS_ASSIGN(_set_r_, _set1_->callbacks); \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
/* Is _set1_ a subset of _set2_ ? */ \
|
||||
/* A set X is a subset of a set Y when: X <= Y */ \
|
||||
/* If X is a subset of Y, then Y is a superset of X */ \
|
||||
bool CMC_(PFX, _is_subset)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
_set1_->flag = CMC_FLAG_OK; \
|
||||
_set2_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
/* If the cardinality of _set1_ is greater than that of _set2_, */ \
|
||||
/* then it is safe to say that _set1_ can't be a subset of _set2_ */ \
|
||||
if (_set1_->count > _set2_->count) \
|
||||
return false; \
|
||||
\
|
||||
/* The empty set is a subset of all sets */ \
|
||||
if (CMC_(PFX, _empty)(_set1_)) \
|
||||
return true; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_entry)(_set2_, value) == NULL) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Is _set1_ a superset of _set2_ ? */ \
|
||||
/* A set X is a superset of a set Y when: X >= Y */ \
|
||||
/* If X is a superset of Y, then Y is a subset of X */ \
|
||||
bool CMC_(PFX, _is_superset)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
return CMC_(PFX, _is_subset)(_set2_, _set1_); \
|
||||
} \
|
||||
\
|
||||
/* Is _set1_ a proper subset of _set2_ ? */ \
|
||||
/* A set X is a proper subset of a set Y when: X < Y */ \
|
||||
/* If X is a proper subset of Y, then Y is a proper superset of X */ \
|
||||
bool CMC_(PFX, _is_proper_subset)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
_set1_->flag = CMC_FLAG_OK; \
|
||||
_set2_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
/* If the cardinality of _set1_ is greater than or equal to that of */ \
|
||||
/* _set2_, then it is safe to say that _set1_ can't be a proper */ \
|
||||
/* subset of _set2_ */ \
|
||||
if (_set1_->count >= _set2_->count) \
|
||||
return false; \
|
||||
\
|
||||
if (CMC_(PFX, _empty)(_set1_)) \
|
||||
{ \
|
||||
/* The empty set is a proper subset of all non-empty sets */ \
|
||||
if (!CMC_(PFX, _empty)(_set2_)) \
|
||||
return true; \
|
||||
/* The empty set is not a proper subset of itself (this is true */ \
|
||||
/* for any set) */ \
|
||||
else \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_entry)(_set2_, value) == NULL) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Is _set1_ a proper superset of _set2_ ? */ \
|
||||
/* A set X is a proper superset of a set Y when: X > Y */ \
|
||||
/* If X is a proper superset of Y, then Y is a proper subset of X */ \
|
||||
bool CMC_(PFX, _is_proper_superset)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
return CMC_(PFX, _is_proper_subset)(_set2_, _set1_); \
|
||||
} \
|
||||
\
|
||||
/* Is _set1_ a disjointset of _set2_ ? */ \
|
||||
/* A set X is a disjointset of a set Y if their intersection is empty, */ \
|
||||
/* that is, if there are no elements in common between the two */ \
|
||||
bool CMC_(PFX, _is_disjointset)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
_set1_->flag = CMC_FLAG_OK; \
|
||||
_set2_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
/* The intersection of an empty set with any other set will result */ \
|
||||
/* in an empty set */ \
|
||||
if (CMC_(PFX, _empty)(_set1_)) \
|
||||
return true; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_entry)(_set2_, value) != NULL) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
}
|
||||
|
||||
/**
|
||||
* STR
|
||||
*/
|
||||
#define CMC_EXT_CMC_HASHSET_STR(PARAMS) \
|
||||
CMC_EXT_CMC_HASHSET_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHSET_STR_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_HASHSET_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HASHSET_STR_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHSET_STR_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_HASHSET_STR_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HASHSET_STR_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _set_, FILE * fptr); \
|
||||
bool CMC_(PFX, _print)(struct SNAME * _set_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end);
|
||||
|
||||
#define CMC_EXT_CMC_HASHSET_STR_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _set_, FILE * fptr) \
|
||||
{ \
|
||||
struct SNAME *s_ = _set_; \
|
||||
\
|
||||
return 0 <= fprintf(fptr, \
|
||||
"struct %s<%s> " \
|
||||
"at %p { " \
|
||||
"buffer:%p, " \
|
||||
"capacity:%" PRIuMAX ", " \
|
||||
"count:%" PRIuMAX ", " \
|
||||
"load:%lf, " \
|
||||
"flag:%d, " \
|
||||
"f_val:%p, " \
|
||||
"alloc:%p, " \
|
||||
"callbacks: %p }", \
|
||||
CMC_TO_STRING(SNAME), CMC_TO_STRING(V), s_, s_->buffer, s_->capacity, s_->count, s_->load, \
|
||||
s_->flag, s_->f_val, s_->alloc, CMC_CALLBACKS_GET(s_)); \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _print)(struct SNAME * _set_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end) \
|
||||
{ \
|
||||
fprintf(fptr, "%s", start); \
|
||||
\
|
||||
size_t last = 0; \
|
||||
for (size_t i = _set_->capacity; i > 0; i--) \
|
||||
{ \
|
||||
if ((_set_->buffer[i - 1]).state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
last = i - 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
for (size_t i = 0; i < _set_->capacity; i++) \
|
||||
{ \
|
||||
struct CMC_DEF_ENTRY(SNAME) *entry = &(_set_->buffer[i]); \
|
||||
\
|
||||
if (entry->state == CMC_ES_FILLED) \
|
||||
{ \
|
||||
if (!_set_->f_val->str(fptr, entry->value)) \
|
||||
return false; \
|
||||
\
|
||||
if (i + 1 < last) \
|
||||
fprintf(fptr, "%s", separator); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
fprintf(fptr, "%s", end); \
|
||||
\
|
||||
return true; \
|
||||
}
|
||||
|
||||
#endif /* CMC_EXT_CMC_HASHSET_H */
|
||||
@@ -0,0 +1,305 @@
|
||||
/**
|
||||
* ext/cmc/heap.h
|
||||
*
|
||||
* Creation Date: 01/06/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CMC_EXT_CMC_HEAP_H
|
||||
#define CMC_EXT_CMC_HEAP_H
|
||||
|
||||
#include "../../cor/core.h"
|
||||
|
||||
/**
|
||||
* All the EXT parts of CMC Heap.
|
||||
*/
|
||||
#define CMC_EXT_CMC_HEAP_PARTS ITER, STR
|
||||
|
||||
#define CMC_EXT_CMC_HEAP_ITER(PARAMS) \
|
||||
CMC_EXT_CMC_HEAP_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HEAP_ITER_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_HEAP_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HEAP_ITER_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HEAP_ITER_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_HEAP_ITER_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HEAP_ITER_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
/* Heap Iterator */ \
|
||||
struct CMC_DEF_ITER(SNAME) \
|
||||
{ \
|
||||
/* Target heap */ \
|
||||
struct SNAME *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; \
|
||||
}; \
|
||||
\
|
||||
/* Iterator Initialization */ \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target); \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target); \
|
||||
/* Iterator State */ \
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
/* Iterator Movement */ \
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index); \
|
||||
/* Iterator Access */ \
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
|
||||
#define CMC_EXT_CMC_HEAP_ITER_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = 0; \
|
||||
iter.start = true; \
|
||||
iter.end = CMC_(PFX, _empty)(target); \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = 0; \
|
||||
iter.start = CMC_(PFX, _empty)(target); \
|
||||
iter.end = true; \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
iter.cursor = target->count - 1; \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->target->count - 1; \
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
iter->end = true; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor++; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor--; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->cursor + steps >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor += steps; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->cursor < steps) \
|
||||
return false; \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor -= steps; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator was able to be positioned at the */ \
|
||||
/* given index */ \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index) \
|
||||
{ \
|
||||
if (index >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor > index) \
|
||||
return CMC_(PFX, _iter_rewind)(iter, iter->cursor - index); \
|
||||
else if (iter->cursor < index) \
|
||||
return CMC_(PFX, _iter_advance)(iter, index - iter->cursor); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (V){ 0 }; \
|
||||
\
|
||||
return iter->target->buffer[iter->cursor]; \
|
||||
} \
|
||||
\
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return iter->cursor; \
|
||||
}
|
||||
|
||||
/**
|
||||
* STR
|
||||
*/
|
||||
#define CMC_EXT_CMC_HEAP_STR(PARAMS) \
|
||||
CMC_EXT_CMC_HEAP_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HEAP_STR_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_HEAP_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_HEAP_STR_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HEAP_STR_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_HEAP_STR_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_HEAP_STR_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _heap_, FILE * fptr); \
|
||||
bool CMC_(PFX, _print)(struct SNAME * _heap_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end);
|
||||
|
||||
#define CMC_EXT_CMC_HEAP_STR_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _heap_, FILE * fptr) \
|
||||
{ \
|
||||
struct SNAME *h_ = _heap_; \
|
||||
const char *t = h_->HO == 1 ? "MaxHeap" : "MinHeap"; \
|
||||
\
|
||||
return 0 <= fprintf(fptr, \
|
||||
"struct %s<%s> " \
|
||||
"at %p { " \
|
||||
"buffer:%p, " \
|
||||
"capacity:%" PRIuMAX ", " \
|
||||
"count:%" PRIuMAX ", " \
|
||||
"type:%s, " \
|
||||
"flag:%d, " \
|
||||
"f_val:%p, " \
|
||||
"alloc:%p, " \
|
||||
"callbacks: %p}", \
|
||||
CMC_TO_STRING(SNAME), CMC_TO_STRING(V), h_, h_->buffer, h_->capacity, h_->count, t, \
|
||||
h_->flag, h_->f_val, h_->alloc, CMC_CALLBACKS_GET(h_)); \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _print)(struct SNAME * _heap_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end) \
|
||||
{ \
|
||||
fprintf(fptr, "%s", start); \
|
||||
\
|
||||
for (size_t i = 0; i < _heap_->count; i++) \
|
||||
{ \
|
||||
if (!_heap_->f_val->str(fptr, _heap_->buffer[i])) \
|
||||
return false; \
|
||||
\
|
||||
if (i + 1 < _heap_->count) \
|
||||
fprintf(fptr, "%s", separator); \
|
||||
} \
|
||||
\
|
||||
fprintf(fptr, "%s", end); \
|
||||
\
|
||||
return true; \
|
||||
}
|
||||
|
||||
#endif /* CMC_EXT_CMC_HEAP_H */
|
||||
@@ -0,0 +1,307 @@
|
||||
/**
|
||||
* ext/cmc/intervalheap.h
|
||||
*
|
||||
* Creation Date: 02/06/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CMC_EXT_CMC_INTERVALHEAP_H
|
||||
#define CMC_EXT_CMC_INTERVALHEAP_H
|
||||
|
||||
#include "../../cor/core.h"
|
||||
|
||||
/**
|
||||
* All the EXT parts of CMC IntervalHeap.
|
||||
*/
|
||||
#define CMC_EXT_CMC_INTERVALHEAP_PARTS ITER, STR
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*/
|
||||
#define CMC_EXT_CMC_INTERVALHEAP_ITER(PARAMS) \
|
||||
CMC_EXT_CMC_INTERVALHEAP_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_INTERVALHEAP_ITER_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_INTERVALHEAP_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_INTERVALHEAP_ITER_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_INTERVALHEAP_ITER_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_INTERVALHEAP_ITER_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_INTERVALHEAP_ITER_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
/* IntervalHeap Iterator */ \
|
||||
struct CMC_DEF_ITER(SNAME) \
|
||||
{ \
|
||||
/* Target IntervalHeap */ \
|
||||
struct SNAME *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; \
|
||||
}; \
|
||||
\
|
||||
/* Iterator Initialization */ \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target); \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target); \
|
||||
/* Iterator State */ \
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
/* Iterator Movement */ \
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index); \
|
||||
/* Iterator Access */ \
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
|
||||
#define CMC_EXT_CMC_INTERVALHEAP_ITER_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = 0; \
|
||||
iter.start = true; \
|
||||
iter.end = CMC_(PFX, _empty)(target); \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = 0; \
|
||||
iter.start = CMC_(PFX, _empty)(target); \
|
||||
iter.end = true; \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
iter.cursor = target->count - 1; \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->target->count - 1; \
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
iter->end = true; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor++; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor--; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->cursor + steps >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor += steps; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->cursor < steps) \
|
||||
return false; \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor -= steps; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator was able to be positioned at the */ \
|
||||
/* given index */ \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index) \
|
||||
{ \
|
||||
if (index >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor > index) \
|
||||
return CMC_(PFX, _iter_rewind)(iter, iter->cursor - index); \
|
||||
else if (iter->cursor < index) \
|
||||
return CMC_(PFX, _iter_advance)(iter, index - iter->cursor); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (V){ 0 }; \
|
||||
\
|
||||
return iter->target->buffer[iter->cursor / 2][iter->cursor % 2]; \
|
||||
} \
|
||||
\
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return iter->cursor; \
|
||||
}
|
||||
|
||||
/**
|
||||
* STR
|
||||
*/
|
||||
#define CMC_EXT_CMC_INTERVALHEAP_STR(PARAMS) \
|
||||
CMC_EXT_CMC_INTERVALHEAP_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_INTERVALHEAP_STR_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_INTERVALHEAP_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_INTERVALHEAP_STR_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_INTERVALHEAP_STR_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_INTERVALHEAP_STR_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_INTERVALHEAP_STR_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _heap_, FILE * fptr); \
|
||||
bool CMC_(PFX, _print)(struct SNAME * _heap_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end);
|
||||
|
||||
#define CMC_EXT_CMC_INTERVALHEAP_STR_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _heap_, FILE * fptr) \
|
||||
{ \
|
||||
struct SNAME *h_ = _heap_; \
|
||||
\
|
||||
return 0 <= fprintf(fptr, \
|
||||
"struct %s<%s> " \
|
||||
"at %p { " \
|
||||
"buffer:%p, " \
|
||||
"capacity:%" PRIuMAX ", " \
|
||||
"size:%" PRIuMAX ", " \
|
||||
"count:%" PRIuMAX ", " \
|
||||
"flag:%d, " \
|
||||
"f_val:%p, " \
|
||||
"alloc:%p, " \
|
||||
"callbacks:%p }", \
|
||||
CMC_TO_STRING(SNAME), CMC_TO_STRING(V), h_, h_->buffer, h_->capacity, h_->size, h_->count, \
|
||||
h_->flag, h_->f_val, h_->alloc, CMC_CALLBACKS_GET(h_)); \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _print)(struct SNAME * _heap_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end) \
|
||||
{ \
|
||||
fprintf(fptr, "%s", start); \
|
||||
\
|
||||
for (size_t i = 0; i < _heap_->count; i++) \
|
||||
{ \
|
||||
if (!_heap_->f_val->str(fptr, _heap_->buffer[i / 2][i % 2])) \
|
||||
return false; \
|
||||
\
|
||||
if (i + 1 < _heap_->count) \
|
||||
fprintf(fptr, "%s", separator); \
|
||||
} \
|
||||
\
|
||||
fprintf(fptr, "%s", end); \
|
||||
\
|
||||
return true; \
|
||||
}
|
||||
|
||||
#endif /* CMC_EXT_CMC_INTERVALHEAP_H */
|
||||
@@ -0,0 +1,567 @@
|
||||
/**
|
||||
* ext/cmc/linkedlist.h
|
||||
*
|
||||
* Creation Date: 03/06/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CMC_EXT_CMC_LINKEDLIST_H
|
||||
#define CMC_EXT_CMC_LINKEDLIST_H
|
||||
|
||||
#include "../../cor/core.h"
|
||||
|
||||
/**
|
||||
* All the EXT parts of CMC LinkedList.
|
||||
*/
|
||||
#define CMC_EXT_CMC_LINKEDLIST_PARTS ITER, NODE, STR
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*/
|
||||
#define CMC_EXT_CMC_LINKEDLIST_ITER(PARAMS) \
|
||||
CMC_EXT_CMC_LINKEDLIST_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_LINKEDLIST_ITER_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_LINKEDLIST_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_LINKEDLIST_ITER_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_LINKEDLIST_ITER_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_LINKEDLIST_ITER_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_LINKEDLIST_ITER_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
/* LinkedList Iterator */ \
|
||||
struct CMC_DEF_ITER(SNAME) \
|
||||
{ \
|
||||
/* Target Linked List */ \
|
||||
struct SNAME *target; \
|
||||
\
|
||||
/* Cursor's current node */ \
|
||||
struct CMC_DEF_NODE(SNAME) * 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; \
|
||||
}; \
|
||||
\
|
||||
/* Iterator Initialization */ \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target); \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target); \
|
||||
/* Iterator State */ \
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
/* Iterator Movement */ \
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index); \
|
||||
/* Iterator Access */ \
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _iter_node)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
|
||||
#define CMC_EXT_CMC_LINKEDLIST_ITER_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = target->head; \
|
||||
iter.index = 0; \
|
||||
iter.start = true; \
|
||||
iter.end = CMC_(PFX, _empty)(target); \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = target->tail; \
|
||||
iter.index = 0; \
|
||||
iter.start = CMC_(PFX, _empty)(target); \
|
||||
iter.end = true; \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
iter.index = target->count - 1; \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->target->head; \
|
||||
iter->index = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->target->tail; \
|
||||
iter->index = iter->target->count - 1; \
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
iter->end = true; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor->next == NULL) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor = iter->cursor->next; \
|
||||
iter->index++; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor->prev == NULL) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor = iter->cursor->prev; \
|
||||
iter->index--; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor->next == NULL) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index + steps >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->index += steps; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
iter->cursor = iter->cursor->next; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor->prev == NULL) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index < steps) \
|
||||
return false; \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->index -= steps; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
iter->cursor = iter->cursor->prev; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator was able to be positioned at the */ \
|
||||
/* given index */ \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index) \
|
||||
{ \
|
||||
if (index >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index > index) \
|
||||
return CMC_(PFX, _iter_rewind)(iter, iter->index - index); \
|
||||
else if (iter->index < index) \
|
||||
return CMC_(PFX, _iter_advance)(iter, index - iter->index); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (V){ 0 }; \
|
||||
\
|
||||
return iter->cursor->value; \
|
||||
} \
|
||||
\
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return NULL; \
|
||||
\
|
||||
return &(iter->cursor->value); \
|
||||
} \
|
||||
\
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return iter->index; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _iter_node)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return iter->cursor; \
|
||||
}
|
||||
|
||||
/**
|
||||
* NODE
|
||||
*/
|
||||
#define CMC_EXT_CMC_LINKEDLIST_NODE(PARAMS) \
|
||||
CMC_EXT_CMC_LINKEDLIST_NODE_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_LINKEDLIST_NODE_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_LINKEDLIST_NODE_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_LINKEDLIST_NODE_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_LINKEDLIST_NODE_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_LINKEDLIST_NODE_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_LINKEDLIST_NODE_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
/* Node Allocation and Deallocation */ \
|
||||
struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _new_node)(struct SNAME * _list_, V value); \
|
||||
void CMC_(PFX, _free_node)(struct SNAME * _list_, struct CMC_DEF_NODE(SNAME) * _node_); \
|
||||
/* Node Access Relative to a Linked List */ \
|
||||
struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _head)(struct SNAME * _list_); \
|
||||
struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _get_node)(struct SNAME * _list_, size_t index); \
|
||||
struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _tail)(struct SNAME * _list_); \
|
||||
/* Input and Output Relative to a Node */ \
|
||||
bool CMC_(PFX, _add_next)(struct SNAME * _owner_, struct CMC_DEF_NODE(SNAME) * _node_, V value); \
|
||||
bool CMC_(PFX, _add_prev)(struct SNAME * _owner_, struct CMC_DEF_NODE(SNAME) * _node_, V value); \
|
||||
bool CMC_(PFX, _del_next)(struct SNAME * _owner_, struct CMC_DEF_NODE(SNAME) * _node_); \
|
||||
bool CMC_(PFX, _del_curr)(struct SNAME * _owner_, struct CMC_DEF_NODE(SNAME) * _node_); \
|
||||
bool CMC_(PFX, _del_prev)(struct SNAME * _owner_, struct CMC_DEF_NODE(SNAME) * _node_); \
|
||||
/* Node Access Relative to a Linked List Node */ \
|
||||
struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _next_node)(struct CMC_DEF_NODE(SNAME) * _node_); \
|
||||
struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _prev_node)(struct CMC_DEF_NODE(SNAME) * _node_);
|
||||
|
||||
#define CMC_EXT_CMC_LINKEDLIST_NODE_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _new_node)(struct SNAME * _list_, V value) \
|
||||
{ \
|
||||
struct CMC_DEF_NODE(SNAME) *_node_ = _list_->alloc->malloc(sizeof(struct CMC_DEF_NODE(SNAME))); \
|
||||
\
|
||||
if (!_node_) \
|
||||
{ \
|
||||
_list_->flag = CMC_FLAG_ALLOC; \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
_node_->value = value; \
|
||||
_node_->next = NULL; \
|
||||
_node_->prev = NULL; \
|
||||
\
|
||||
return _node_; \
|
||||
} \
|
||||
\
|
||||
void CMC_(PFX, _free_node)(struct SNAME * _list_, struct CMC_DEF_NODE(SNAME) * _node_) \
|
||||
{ \
|
||||
_list_->alloc->free(_node_); \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _head)(struct SNAME * _list_) \
|
||||
{ \
|
||||
return _list_->head; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _get_node)(struct SNAME * _list_, size_t index) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(_list_)) \
|
||||
{ \
|
||||
_list_->flag = CMC_FLAG_EMPTY; \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
if (index >= _list_->count) \
|
||||
{ \
|
||||
_list_->flag = CMC_FLAG_RANGE; \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_NODE(SNAME) *_node_ = NULL; \
|
||||
\
|
||||
if (index <= _list_->count / 2) \
|
||||
{ \
|
||||
_node_ = _list_->head; \
|
||||
for (size_t i = 0; i < index; i++) \
|
||||
{ \
|
||||
_node_ = _node_->next; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
_node_ = _list_->tail; \
|
||||
for (size_t i = _list_->count - 1; i > index; i--) \
|
||||
{ \
|
||||
_node_ = _node_->prev; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
_list_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
return _node_; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _tail)(struct SNAME * _list_) \
|
||||
{ \
|
||||
return _list_->tail; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _add_next)(struct SNAME * _owner_, struct CMC_DEF_NODE(SNAME) * _node_, V value) \
|
||||
{ \
|
||||
struct CMC_DEF_NODE(SNAME) *new_node = CMC_(PFX, _new_node)(_owner_, value); \
|
||||
\
|
||||
if (!new_node) \
|
||||
return false; \
|
||||
\
|
||||
new_node->next = _node_->next; \
|
||||
\
|
||||
if (_node_->next != NULL) \
|
||||
_node_->next->prev = new_node; \
|
||||
else \
|
||||
_owner_->tail = new_node; \
|
||||
\
|
||||
new_node->prev = _node_; \
|
||||
_node_->next = new_node; \
|
||||
\
|
||||
_owner_->count++; \
|
||||
_owner_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _add_prev)(struct SNAME * _owner_, struct CMC_DEF_NODE(SNAME) * _node_, V value) \
|
||||
{ \
|
||||
struct CMC_DEF_NODE(SNAME) *new_node = CMC_(PFX, _new_node)(_owner_, value); \
|
||||
\
|
||||
if (!new_node) \
|
||||
return false; \
|
||||
\
|
||||
new_node->prev = _node_->prev; \
|
||||
\
|
||||
if (_node_->prev != NULL) \
|
||||
_node_->prev->next = new_node; \
|
||||
else \
|
||||
_owner_->head = new_node; \
|
||||
\
|
||||
new_node->next = _node_; \
|
||||
_node_->prev = new_node; \
|
||||
\
|
||||
_owner_->count++; \
|
||||
_owner_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _del_next)(struct SNAME * _owner_, struct CMC_DEF_NODE(SNAME) * _node_) \
|
||||
{ \
|
||||
if (_node_->next == NULL) \
|
||||
{ \
|
||||
_owner_->flag = CMC_FLAG_INVALID; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_NODE(SNAME) *tmp = _node_->next; \
|
||||
\
|
||||
_node_->next = _node_->next->next; \
|
||||
\
|
||||
if (tmp->next != NULL) \
|
||||
tmp->next->prev = _node_; \
|
||||
else \
|
||||
_owner_->tail = _node_; \
|
||||
\
|
||||
_owner_->alloc->free(tmp); \
|
||||
\
|
||||
_owner_->count--; \
|
||||
_owner_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _del_curr)(struct SNAME * _owner_, struct CMC_DEF_NODE(SNAME) * _node_) \
|
||||
{ \
|
||||
if (_node_->prev != NULL) \
|
||||
_node_->prev->next = _node_->next; \
|
||||
else \
|
||||
_owner_->head = _node_->next; \
|
||||
\
|
||||
if (_node_->next != NULL) \
|
||||
_node_->next->prev = _node_->prev; \
|
||||
else \
|
||||
_owner_->tail = _node_->prev; \
|
||||
\
|
||||
_owner_->alloc->free(_node_); \
|
||||
\
|
||||
_owner_->count--; \
|
||||
_owner_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _del_prev)(struct SNAME * _owner_, struct CMC_DEF_NODE(SNAME) * _node_) \
|
||||
{ \
|
||||
if (_node_->prev == NULL) \
|
||||
{ \
|
||||
_owner_->flag = CMC_FLAG_INVALID; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_NODE(SNAME) *tmp = _node_->prev; \
|
||||
\
|
||||
_node_->prev = _node_->prev->prev; \
|
||||
\
|
||||
if (tmp->prev != NULL) \
|
||||
tmp->prev->next = _node_; \
|
||||
else \
|
||||
_owner_->head = _node_; \
|
||||
\
|
||||
_owner_->alloc->free(tmp); \
|
||||
\
|
||||
_owner_->count--; \
|
||||
_owner_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _next_node)(struct CMC_DEF_NODE(SNAME) * _node_) \
|
||||
{ \
|
||||
return _node_->next; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _prev_node)(struct CMC_DEF_NODE(SNAME) * _node_) \
|
||||
{ \
|
||||
return _node_->prev; \
|
||||
}
|
||||
|
||||
/**
|
||||
* STR
|
||||
*/
|
||||
#define CMC_EXT_CMC_LINKEDLIST_STR(PARAMS) \
|
||||
CMC_EXT_CMC_LINKEDLIST_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_LINKEDLIST_STR_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_LINKEDLIST_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_LINKEDLIST_STR_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_LINKEDLIST_STR_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_LINKEDLIST_STR_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_LINKEDLIST_STR_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _list_, FILE * fptr); \
|
||||
bool CMC_(PFX, _print)(struct SNAME * _list_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end);
|
||||
|
||||
#define CMC_EXT_CMC_LINKEDLIST_STR_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _list_, FILE * fptr) \
|
||||
{ \
|
||||
struct SNAME *l_ = _list_; \
|
||||
\
|
||||
return 0 <= fprintf(fptr, \
|
||||
"struct %s<%s> " \
|
||||
"at %p { " \
|
||||
"count:%" PRIuMAX ", " \
|
||||
"head:%p, " \
|
||||
"tail:%p, " \
|
||||
"flag:%d, " \
|
||||
"f_val:%p, " \
|
||||
"alloc:%p, " \
|
||||
"callbacks:%p }", \
|
||||
CMC_TO_STRING(SNAME), CMC_TO_STRING(V), l_, l_->count, l_->head, l_->tail, l_->flag, \
|
||||
l_->f_val, l_->alloc, CMC_CALLBACKS_GET(l_)); \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _print)(struct SNAME * _list_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end) \
|
||||
{ \
|
||||
fprintf(fptr, "%s", start); \
|
||||
\
|
||||
struct CMC_DEF_NODE(SNAME) *scan = _list_->head; \
|
||||
\
|
||||
while (scan != NULL) \
|
||||
{ \
|
||||
if (!_list_->f_val->str(fptr, scan->value)) \
|
||||
return false; \
|
||||
\
|
||||
scan = scan->next; \
|
||||
\
|
||||
if (scan) \
|
||||
fprintf(fptr, "%s", separator); \
|
||||
} \
|
||||
\
|
||||
fprintf(fptr, "%s", end); \
|
||||
\
|
||||
return true; \
|
||||
}
|
||||
|
||||
#endif /* CMC_EXT_CMC_LINKEDLIST_H */
|
||||
@@ -0,0 +1,492 @@
|
||||
/**
|
||||
* ext/cmc/list.h
|
||||
*
|
||||
* Creation Date: 04/06/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CMC_EXT_CMC_LIST_H
|
||||
#define CMC_EXT_CMC_LIST_H
|
||||
|
||||
#include "../../cor/core.h"
|
||||
|
||||
/**
|
||||
* All the EXT parts of CMC List.
|
||||
*/
|
||||
#define CMC_EXT_CMC_LIST_PARTS ITER, SEQ, STR
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*/
|
||||
#define CMC_EXT_CMC_LIST_ITER(PARAMS) \
|
||||
CMC_EXT_CMC_LIST_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_LIST_ITER_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_LIST_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_LIST_ITER_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_LIST_ITER_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_LIST_ITER_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_LIST_ITER_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
/* List Iterator */ \
|
||||
struct CMC_DEF_ITER(SNAME) \
|
||||
{ \
|
||||
/* Target List */ \
|
||||
struct SNAME *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; \
|
||||
}; \
|
||||
\
|
||||
/* Iterator Initialization */ \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target); \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target); \
|
||||
/* Iterator State */ \
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
/* Iterator Movement */ \
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index); \
|
||||
/* Iterator Access */ \
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
|
||||
#define CMC_EXT_CMC_LIST_ITER_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = 0; \
|
||||
iter.start = true; \
|
||||
iter.end = CMC_(PFX, _empty)(target); \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = 0; \
|
||||
iter.start = CMC_(PFX, _empty)(target); \
|
||||
iter.end = true; \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
iter.cursor = target->count - 1; \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
iter->cursor = iter->target->count - 1; \
|
||||
iter->end = true; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor++; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor--; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->cursor + steps >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor += steps; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->cursor < steps) \
|
||||
return false; \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor -= steps; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator was able to be positioned at the */ \
|
||||
/* given index */ \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index) \
|
||||
{ \
|
||||
if (index >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor > index) \
|
||||
return CMC_(PFX, _iter_rewind)(iter, iter->cursor - index); \
|
||||
else if (iter->cursor < index) \
|
||||
return CMC_(PFX, _iter_advance)(iter, index - iter->cursor); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (V){ 0 }; \
|
||||
\
|
||||
return iter->target->buffer[iter->cursor]; \
|
||||
} \
|
||||
\
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return NULL; \
|
||||
\
|
||||
return &(iter->target->buffer[iter->cursor]); \
|
||||
} \
|
||||
\
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return iter->cursor; \
|
||||
}
|
||||
|
||||
/**
|
||||
* SEQ
|
||||
*/
|
||||
#define CMC_EXT_CMC_LIST_SEQ(PARAMS) \
|
||||
CMC_EXT_CMC_LIST_SEQ_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_LIST_SEQ_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_LIST_SEQ_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_LIST_SEQ_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_LIST_SEQ_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_LIST_SEQ_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_LIST_SEQ_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
/* List Sequence Input and Output */ \
|
||||
bool CMC_(PFX, _seq_push_front)(struct SNAME * _list_, V * values, size_t size); \
|
||||
bool CMC_(PFX, _seq_push_at)(struct SNAME * _list_, V * values, size_t size, size_t index); \
|
||||
bool CMC_(PFX, _seq_push_back)(struct SNAME * _list_, V * values, size_t size); \
|
||||
bool CMC_(PFX, _seq_pop_at)(struct SNAME * _list_, size_t from, size_t to); \
|
||||
struct SNAME *CMC_(PFX, _seq_sublist)(struct SNAME * _list_, size_t from, size_t to);
|
||||
|
||||
#define CMC_EXT_CMC_LIST_SEQ_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _seq_push_front)(struct SNAME * _list_, V * values, size_t size) \
|
||||
{ \
|
||||
if (size == 0) \
|
||||
{ \
|
||||
_list_->flag = CMC_FLAG_INVALID; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (!CMC_(PFX, _fits)(_list_, size)) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _resize)(_list_, _list_->count + size)) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
memmove(_list_->buffer + size, _list_->buffer, _list_->count * sizeof(V)); \
|
||||
\
|
||||
memcpy(_list_->buffer, values, size * sizeof(V)); \
|
||||
\
|
||||
_list_->count += size; \
|
||||
_list_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
CMC_CALLBACKS_CALL(_list_, create); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _seq_push_at)(struct SNAME * _list_, V * values, size_t size, size_t index) \
|
||||
{ \
|
||||
if (size == 0) \
|
||||
{ \
|
||||
_list_->flag = CMC_FLAG_INVALID; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (index > _list_->count) \
|
||||
{ \
|
||||
_list_->flag = CMC_FLAG_RANGE; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (index == 0) \
|
||||
return CMC_(PFX, _seq_push_front)(_list_, values, size); \
|
||||
else if (index == _list_->count) \
|
||||
return CMC_(PFX, _seq_push_back)(_list_, values, size); \
|
||||
\
|
||||
if (!CMC_(PFX, _fits)(_list_, size)) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _resize)(_list_, _list_->count + size)) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
memmove(_list_->buffer + index + size, _list_->buffer + index, (_list_->count - index) * sizeof(V)); \
|
||||
\
|
||||
memcpy(_list_->buffer + index, values, size * sizeof(V)); \
|
||||
\
|
||||
_list_->count += size; \
|
||||
_list_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
CMC_CALLBACKS_CALL(_list_, create); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _seq_push_back)(struct SNAME * _list_, V * values, size_t size) \
|
||||
{ \
|
||||
if (size == 0) \
|
||||
{ \
|
||||
_list_->flag = CMC_FLAG_INVALID; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (!CMC_(PFX, _fits)(_list_, size)) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _resize)(_list_, _list_->count + size)) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
memcpy(_list_->buffer + _list_->count, values, size * sizeof(V)); \
|
||||
\
|
||||
_list_->count += size; \
|
||||
_list_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
CMC_CALLBACKS_CALL(_list_, create); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _seq_pop_at)(struct SNAME * _list_, size_t from, size_t to) \
|
||||
{ \
|
||||
if (from > to) \
|
||||
{ \
|
||||
_list_->flag = CMC_FLAG_INVALID; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (to >= _list_->count) \
|
||||
{ \
|
||||
_list_->flag = CMC_FLAG_RANGE; \
|
||||
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; \
|
||||
_list_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
CMC_CALLBACKS_CALL(_list_, delete); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _seq_sublist)(struct SNAME * _list_, size_t from, size_t to) \
|
||||
{ \
|
||||
if (from > to) \
|
||||
{ \
|
||||
_list_->flag = CMC_FLAG_INVALID; \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
if (to >= _list_->count) \
|
||||
{ \
|
||||
_list_->flag = CMC_FLAG_RANGE; \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
size_t length = to - from + 1; \
|
||||
\
|
||||
struct SNAME *result = \
|
||||
CMC_(PFX, _new_custom)(length, _list_->f_val, _list_->alloc, CMC_CALLBACKS_GET(_list_)); \
|
||||
\
|
||||
if (!result) \
|
||||
{ \
|
||||
_list_->flag = CMC_FLAG_ALLOC; \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
memcpy(result->buffer, _list_->buffer, length * sizeof(V)); \
|
||||
\
|
||||
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; \
|
||||
result->count = length; \
|
||||
\
|
||||
_list_->flag = CMC_FLAG_OK; \
|
||||
\
|
||||
CMC_CALLBACKS_CALL(_list_, delete); \
|
||||
\
|
||||
return result; \
|
||||
}
|
||||
|
||||
/**
|
||||
* STR
|
||||
*/
|
||||
#define CMC_EXT_CMC_LIST_STR(PARAMS) \
|
||||
CMC_EXT_CMC_LIST_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_LIST_STR_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_LIST_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_LIST_STR_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_LIST_STR_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_LIST_STR_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_LIST_STR_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _list_, FILE * fptr); \
|
||||
bool CMC_(PFX, _print)(struct SNAME * _list_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end);
|
||||
|
||||
#define CMC_EXT_CMC_LIST_STR_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _list_, FILE * fptr) \
|
||||
{ \
|
||||
struct SNAME *l_ = _list_; \
|
||||
\
|
||||
return 0 <= fprintf(fptr, \
|
||||
"struct %s<%s> " \
|
||||
"at %p { " \
|
||||
"buffer:%p, " \
|
||||
"capacity:%" PRIuMAX ", " \
|
||||
"count:%" PRIuMAX ", " \
|
||||
"flag:%d, " \
|
||||
"f_val:%p, " \
|
||||
"alloc:%p, " \
|
||||
"callbacks:%p }", \
|
||||
CMC_TO_STRING(SNAME), CMC_TO_STRING(V), l_, l_->buffer, l_->capacity, l_->count, l_->flag, \
|
||||
l_->f_val, l_->alloc, CMC_CALLBACKS_GET(l_)); \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _print)(struct SNAME * _list_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end) \
|
||||
{ \
|
||||
fprintf(fptr, "%s", start); \
|
||||
\
|
||||
for (size_t i = 0; i < _list_->count; i++) \
|
||||
{ \
|
||||
if (!_list_->f_val->str(fptr, _list_->buffer[i])) \
|
||||
return false; \
|
||||
\
|
||||
if (i + 1 < _list_->count) \
|
||||
fprintf(fptr, "%s", separator); \
|
||||
} \
|
||||
\
|
||||
fprintf(fptr, "%s", end); \
|
||||
\
|
||||
return true; \
|
||||
}
|
||||
|
||||
#endif /* CMC_EXT_CMC_LIST_H */
|
||||
@@ -0,0 +1,348 @@
|
||||
/**
|
||||
* ext/cmc/queue.h
|
||||
*
|
||||
* Creation Date: 05/06/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CMC_EXT_CMC_QUEUE_H
|
||||
#define CMC_EXT_CMC_QUEUE_H
|
||||
|
||||
#include "../../cor/core.h"
|
||||
|
||||
/**
|
||||
* All the EXT parts of CMC Queue.
|
||||
*/
|
||||
#define CMC_EXT_CMC_QUEUE_PARTS ITER, STR
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*/
|
||||
#define CMC_EXT_CMC_QUEUE_ITER(PARAMS) \
|
||||
CMC_EXT_CMC_QUEUE_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_QUEUE_ITER_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_QUEUE_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_QUEUE_ITER_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_QUEUE_ITER_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_QUEUE_ITER_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_QUEUE_ITER_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
/* Queue Iterator */ \
|
||||
struct CMC_DEF_ITER(SNAME) \
|
||||
{ \
|
||||
/* Target queue */ \
|
||||
struct SNAME *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; \
|
||||
}; \
|
||||
\
|
||||
/* Iterator Initialization */ \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target); \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target); \
|
||||
/* Iterator State */ \
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
/* Iterator Movement */ \
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index); \
|
||||
/* Iterator Access */ \
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
|
||||
#define CMC_EXT_CMC_QUEUE_ITER_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = target->front; \
|
||||
iter.index = 0; \
|
||||
iter.start = true; \
|
||||
iter.end = CMC_(PFX, _empty)(target); \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
if (iter.target->back == 0) \
|
||||
iter.cursor = iter.target->capacity - 1; \
|
||||
else \
|
||||
iter.cursor = iter.target->back - 1; \
|
||||
\
|
||||
iter.index = iter.target->count - 1; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
iter.cursor = 0; \
|
||||
iter.index = 0; \
|
||||
} \
|
||||
\
|
||||
iter.start = CMC_(PFX, _empty)(target); \
|
||||
iter.end = true; \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->target->front; \
|
||||
iter->index = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = false; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
if (iter->target->back == 0) \
|
||||
iter->cursor = iter->target->capacity - 1; \
|
||||
else \
|
||||
iter->cursor = iter->target->back - 1; \
|
||||
\
|
||||
iter->index = iter->target->count - 1; \
|
||||
\
|
||||
iter->start = false; \
|
||||
iter->end = true; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor = (iter->cursor + 1) % (iter->target->capacity); \
|
||||
iter->index++; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; \
|
||||
iter->index--; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index + steps >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->index += steps; \
|
||||
iter->cursor = (iter->cursor + steps) % iter->target->capacity; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index < steps) \
|
||||
return false; \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->index -= steps; \
|
||||
\
|
||||
/* Prevent underflow */ \
|
||||
if (iter->cursor < steps) \
|
||||
iter->cursor += iter->target->capacity; \
|
||||
\
|
||||
iter->cursor -= steps; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator was able to be positioned at the */ \
|
||||
/* given index */ \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index) \
|
||||
{ \
|
||||
if (index >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index > index) \
|
||||
return CMC_(PFX, _iter_rewind)(iter, iter->index - index); \
|
||||
else if (iter->index < index) \
|
||||
return CMC_(PFX, _iter_advance)(iter, index - iter->index); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (V){ 0 }; \
|
||||
\
|
||||
return iter->target->buffer[iter->cursor]; \
|
||||
} \
|
||||
\
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return NULL; \
|
||||
\
|
||||
return &(iter->target->buffer[iter->cursor]); \
|
||||
} \
|
||||
\
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return iter->index; \
|
||||
}
|
||||
|
||||
/**
|
||||
* STR
|
||||
*/
|
||||
#define CMC_EXT_CMC_QUEUE_STR(PARAMS) \
|
||||
CMC_EXT_CMC_QUEUE_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_QUEUE_STR_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_QUEUE_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_QUEUE_STR_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_QUEUE_STR_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_QUEUE_STR_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_QUEUE_STR_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _queue_, FILE * fptr); \
|
||||
bool CMC_(PFX, _print)(struct SNAME * _queue_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end);
|
||||
|
||||
#define CMC_EXT_CMC_QUEUE_STR_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _queue_, FILE * fptr) \
|
||||
{ \
|
||||
struct SNAME *q_ = _queue_; \
|
||||
\
|
||||
return 0 <= fprintf(fptr, \
|
||||
"struct %s<%s> " \
|
||||
"at %p { " \
|
||||
"buffer:%p, " \
|
||||
"capacity:%" PRIuMAX ", " \
|
||||
"count:%" PRIuMAX ", " \
|
||||
"front:%" PRIuMAX ", " \
|
||||
"back:%" PRIuMAX ", " \
|
||||
"flag:%d, " \
|
||||
"f_val:%p, " \
|
||||
"alloc:%p, " \
|
||||
"callbacks:%p }", \
|
||||
CMC_TO_STRING(SNAME), CMC_TO_STRING(V), q_, q_->buffer, q_->capacity, q_->count, \
|
||||
q_->front, q_->back, q_->flag, q_->f_val, q_->alloc, CMC_CALLBACKS_GET(q_)); \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _print)(struct SNAME * _queue_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end) \
|
||||
{ \
|
||||
fprintf(fptr, "%s", start); \
|
||||
\
|
||||
for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) \
|
||||
{ \
|
||||
if (!_queue_->f_val->str(fptr, _queue_->buffer[i])) \
|
||||
return false; \
|
||||
\
|
||||
i = (i + 1) % _queue_->capacity; \
|
||||
\
|
||||
if (j + 1 < _queue_->count) \
|
||||
fprintf(fptr, "%s", separator); \
|
||||
} \
|
||||
\
|
||||
fprintf(fptr, "%s", end); \
|
||||
\
|
||||
return true; \
|
||||
}
|
||||
|
||||
#endif /* CMC_EXT_CMC_QUEUE_H */
|
||||
@@ -0,0 +1,310 @@
|
||||
/**
|
||||
* ext/cmc/sortedlist.h
|
||||
*
|
||||
* Creation Date: 06/06/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CMC_EXT_CMC_SORTEDLIST_H
|
||||
#define CMC_EXT_CMC_SORTEDLIST_H
|
||||
|
||||
#include "../../cor/core.h"
|
||||
|
||||
/**
|
||||
* All the EXT parts of CMC SortedList.
|
||||
*/
|
||||
#define CMC_EXT_CMC_SORTEDLIST_PARTS ITER, STR
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*/
|
||||
#define CMC_EXT_CMC_SORTEDLIST_ITER(PARAMS) \
|
||||
CMC_EXT_CMC_SORTEDLIST_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_SORTEDLIST_ITER_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_SORTEDLIST_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_SORTEDLIST_ITER_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_SORTEDLIST_ITER_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_SORTEDLIST_ITER_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_SORTEDLIST_ITER_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
/* List Iterator */ \
|
||||
struct CMC_DEF_ITER(SNAME) \
|
||||
{ \
|
||||
/* Target list */ \
|
||||
struct SNAME *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; \
|
||||
}; \
|
||||
\
|
||||
/* Iterator Initialization */ \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target); \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target); \
|
||||
/* Iterator State */ \
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
/* Iterator Movement */ \
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index); \
|
||||
/* Iterator Access */ \
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
|
||||
#define CMC_EXT_CMC_SORTEDLIST_ITER_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \
|
||||
{ \
|
||||
CMC_(PFX, _sort)(target); \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = 0; \
|
||||
iter.start = true; \
|
||||
iter.end = CMC_(PFX, _empty)(target); \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target) \
|
||||
{ \
|
||||
CMC_(PFX, _sort)(target); \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = 0; \
|
||||
iter.start = CMC_(PFX, _empty)(target); \
|
||||
iter.end = true; \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
iter.cursor = target->count - 1; \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
iter->cursor = iter->target->count - 1; \
|
||||
iter->end = true; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor++; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor--; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->cursor + steps >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor += steps; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor == 0) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->cursor < steps) \
|
||||
return false; \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor -= steps; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator was able to be positioned at the */ \
|
||||
/* given index */ \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index) \
|
||||
{ \
|
||||
if (index >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor > index) \
|
||||
return CMC_(PFX, _iter_rewind)(iter, iter->cursor - index); \
|
||||
else if (iter->cursor < index) \
|
||||
return CMC_(PFX, _iter_advance)(iter, index - iter->cursor); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (V){ 0 }; \
|
||||
\
|
||||
return iter->target->buffer[iter->cursor]; \
|
||||
} \
|
||||
\
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return iter->cursor; \
|
||||
}
|
||||
|
||||
/**
|
||||
* STR
|
||||
*/
|
||||
#define CMC_EXT_CMC_SORTEDLIST_STR(PARAMS) \
|
||||
CMC_EXT_CMC_SORTEDLIST_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_SORTEDLIST_STR_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_SORTEDLIST_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_SORTEDLIST_STR_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_SORTEDLIST_STR_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_SORTEDLIST_STR_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_SORTEDLIST_STR_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _list_, FILE * fptr); \
|
||||
bool CMC_(PFX, _print)(struct SNAME * _list_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end);
|
||||
|
||||
#define CMC_EXT_CMC_SORTEDLIST_STR_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _list_, FILE * fptr) \
|
||||
{ \
|
||||
struct SNAME *l_ = _list_; \
|
||||
\
|
||||
return 0 <= fprintf(fptr, \
|
||||
"struct %s<%s> " \
|
||||
"at %p { " \
|
||||
"buffer:%p, " \
|
||||
"capacity:%" PRIuMAX ", " \
|
||||
"count:%" PRIuMAX ", " \
|
||||
"is_sorted:%s, " \
|
||||
"flag:%d, " \
|
||||
"f_val:%p, " \
|
||||
"alloc:%p, " \
|
||||
"callbacks:%p }", \
|
||||
CMC_TO_STRING(SNAME), CMC_TO_STRING(V), l_, l_->buffer, l_->capacity, l_->count, \
|
||||
l_->is_sorted ? "true" : "false", l_->flag, l_->f_val, l_->alloc, CMC_CALLBACKS_GET(l_)); \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _print)(struct SNAME * _list_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end) \
|
||||
{ \
|
||||
CMC_(PFX, _sort)(_list_); \
|
||||
\
|
||||
fprintf(fptr, "%s", start); \
|
||||
\
|
||||
for (size_t i = 0; i < _list_->count; i++) \
|
||||
{ \
|
||||
if (!_list_->f_val->str(fptr, _list_->buffer[i])) \
|
||||
return false; \
|
||||
\
|
||||
if (i + 1 < _list_->count) \
|
||||
fprintf(fptr, "%s", separator); \
|
||||
} \
|
||||
\
|
||||
fprintf(fptr, "%s", end); \
|
||||
\
|
||||
return true; \
|
||||
}
|
||||
|
||||
#endif /* CMC_EXT_CMC_SORTEDLIST_H */
|
||||
@@ -0,0 +1,315 @@
|
||||
/**
|
||||
* ext/cmc/stack.h
|
||||
*
|
||||
* Creation Date: 07/06/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CMC_EXT_CMC_STACK_H
|
||||
#define CMC_EXT_CMC_STACK_H
|
||||
|
||||
#include "../../cor/core.h"
|
||||
|
||||
/**
|
||||
* All the EXT parts of CMC Stack.
|
||||
*/
|
||||
#define CMC_EXT_CMC_STACK_PARTS ITER, STR
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*/
|
||||
#define CMC_EXT_CMC_STACK_ITER(PARAMS) \
|
||||
CMC_EXT_CMC_STACK_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_STACK_ITER_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_STACK_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_STACK_ITER_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_STACK_ITER_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_STACK_ITER_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_STACK_ITER_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
/* Stack Iterator */ \
|
||||
struct CMC_DEF_ITER(SNAME) \
|
||||
{ \
|
||||
/* Target stack */ \
|
||||
struct SNAME *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; \
|
||||
}; \
|
||||
\
|
||||
/* Iterator Initialization */ \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target); \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target); \
|
||||
/* Iterator State */ \
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
/* Iterator Movement */ \
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index); \
|
||||
/* Iterator Access */ \
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
|
||||
#define CMC_EXT_CMC_STACK_ITER_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = 0; \
|
||||
iter.start = true; \
|
||||
iter.end = CMC_(PFX, _empty)(target); \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
iter.cursor = target->count - 1; \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = 0; \
|
||||
iter.start = CMC_(PFX, _empty)(target); \
|
||||
iter.end = true; \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = iter->target->count - 1; \
|
||||
iter->start = true; \
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->cursor = 0; \
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
iter->end = true; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor == 0) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor--; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor++; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor == 0) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->cursor < steps) \
|
||||
return false; \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor -= steps; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor + 1 == iter->target->count) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->cursor + steps >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
iter->cursor += steps; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator was able to be positioned at the */ \
|
||||
/* given index */ \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index) \
|
||||
{ \
|
||||
if (index >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor > index) \
|
||||
return CMC_(PFX, _iter_advance)(iter, iter->cursor - index); \
|
||||
else if (iter->cursor < index) \
|
||||
return CMC_(PFX, _iter_rewind)(iter, index - iter->cursor); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (V){ 0 }; \
|
||||
\
|
||||
return iter->target->buffer[iter->cursor]; \
|
||||
} \
|
||||
\
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return NULL; \
|
||||
\
|
||||
return &(iter->target->buffer[iter->cursor]); \
|
||||
} \
|
||||
\
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return 0; \
|
||||
\
|
||||
return iter->target->count - 1 - iter->cursor; \
|
||||
}
|
||||
|
||||
/**
|
||||
* STR
|
||||
*/
|
||||
#define CMC_EXT_CMC_STACK_STR(PARAMS) \
|
||||
CMC_EXT_CMC_STACK_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_STACK_STR_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_STACK_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_STACK_STR_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_STACK_STR_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_STACK_STR_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_STACK_STR_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _stack_, FILE * fptr); \
|
||||
bool CMC_(PFX, _print)(struct SNAME * _stack_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end);
|
||||
|
||||
#define CMC_EXT_CMC_STACK_STR_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _stack_, FILE * fptr) \
|
||||
{ \
|
||||
struct SNAME *s_ = _stack_; \
|
||||
\
|
||||
return 0 <= fprintf(fptr, \
|
||||
"struct %s<%s> " \
|
||||
"at %p { " \
|
||||
"buffer:%p, " \
|
||||
"capacity:%" PRIuMAX ", " \
|
||||
"count:%" PRIuMAX ", " \
|
||||
"flag:%d, " \
|
||||
"f_val:%p, " \
|
||||
"alloc:%p, " \
|
||||
"callbacks:%p }", \
|
||||
CMC_TO_STRING(SNAME), CMC_TO_STRING(V), s_, s_->buffer, s_->capacity, s_->count, s_->flag, \
|
||||
s_->f_val, s_->alloc, CMC_CALLBACKS_GET(s_)); \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _print)(struct SNAME * _stack_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end) \
|
||||
{ \
|
||||
fprintf(fptr, "%s", start); \
|
||||
\
|
||||
for (size_t i = _stack_->count; i > 0; i--) \
|
||||
{ \
|
||||
if (!_stack_->f_val->str(fptr, _stack_->buffer[i - 1])) \
|
||||
return false; \
|
||||
\
|
||||
if (i - 1 != 0) \
|
||||
fprintf(fptr, "%s", separator); \
|
||||
} \
|
||||
\
|
||||
fprintf(fptr, "%s", end); \
|
||||
\
|
||||
return true; \
|
||||
}
|
||||
|
||||
#endif /* CMC_EXT_CMC_STACK_H */
|
||||
@@ -0,0 +1,443 @@
|
||||
/**
|
||||
* ext/cmc/treemap.h
|
||||
*
|
||||
* Creation Date: 08/06/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CMC_EXT_CMC_TREEMAP_H
|
||||
#define CMC_EXT_CMC_TREEMAP_H
|
||||
|
||||
#include "../../cor/core.h"
|
||||
|
||||
/**
|
||||
* All the EXT parts of CMC TreeMap.
|
||||
*/
|
||||
#define CMC_EXT_CMC_TREEMAP_PARTS ITER, STR
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*/
|
||||
#define CMC_EXT_CMC_TREEMAP_ITER(PARAMS) \
|
||||
CMC_EXT_CMC_TREEMAP_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_TREEMAP_ITER_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_TREEMAP_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_TREEMAP_ITER_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_K(PARAMS), \
|
||||
CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_TREEMAP_ITER_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_TREEMAP_ITER_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_K(PARAMS), \
|
||||
CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_TREEMAP_ITER_HEADER_(PFX, SNAME, K, V) \
|
||||
\
|
||||
/* Treemap Iterator */ \
|
||||
struct CMC_DEF_ITER(SNAME) \
|
||||
{ \
|
||||
/* Target treemap */ \
|
||||
struct SNAME *target; \
|
||||
\
|
||||
/* Cursor's current node */ \
|
||||
struct CMC_DEF_NODE(SNAME) * cursor; \
|
||||
\
|
||||
/* The first node in the iteration */ \
|
||||
struct CMC_DEF_NODE(SNAME) * first; \
|
||||
\
|
||||
/* The last node in the iteration */ \
|
||||
struct CMC_DEF_NODE(SNAME) * last; \
|
||||
\
|
||||
/* 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; \
|
||||
}; \
|
||||
\
|
||||
/* Iterator Initialization */ \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target); \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target); \
|
||||
/* Iterator State */ \
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
/* Iterator Movement */ \
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index); \
|
||||
/* Iterator Access */ \
|
||||
K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
|
||||
#define CMC_EXT_CMC_TREEMAP_ITER_SOURCE_(PFX, SNAME, K, V) \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = target->root; \
|
||||
iter.first = NULL; \
|
||||
iter.last = NULL; \
|
||||
iter.index = 0; \
|
||||
iter.start = true; \
|
||||
iter.end = CMC_(PFX, _empty)(target); \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
while (iter.cursor->left != NULL) \
|
||||
iter.cursor = iter.cursor->left; \
|
||||
\
|
||||
iter.first = iter.cursor; \
|
||||
\
|
||||
iter.last = target->root; \
|
||||
while (iter.last->right != NULL) \
|
||||
iter.last = iter.last->right; \
|
||||
} \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = target->root; \
|
||||
iter.first = NULL; \
|
||||
iter.last = NULL; \
|
||||
iter.index = 0; \
|
||||
iter.start = CMC_(PFX, _empty)(target); \
|
||||
iter.end = true; \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
while (iter.cursor->right != NULL) \
|
||||
iter.cursor = iter.cursor->right; \
|
||||
\
|
||||
iter.last = iter.cursor; \
|
||||
\
|
||||
iter.first = target->root; \
|
||||
while (iter.first->left != NULL) \
|
||||
iter.first = iter.first->left; \
|
||||
\
|
||||
iter.index = target->count - 1; \
|
||||
} \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->index = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
iter->cursor = iter->first; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->index = iter->target->count - 1; \
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
iter->end = true; \
|
||||
iter->cursor = iter->last; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor == iter->last) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
if (iter->cursor->right != NULL) \
|
||||
{ \
|
||||
iter->cursor = iter->cursor->right; \
|
||||
\
|
||||
while (iter->cursor->left != NULL) \
|
||||
iter->cursor = iter->cursor->left; \
|
||||
\
|
||||
iter->index++; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
while (true) \
|
||||
{ \
|
||||
if (iter->cursor->parent->left == iter->cursor) \
|
||||
{ \
|
||||
iter->cursor = iter->cursor->parent; \
|
||||
\
|
||||
iter->index++; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
iter->cursor = iter->cursor->parent; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor == iter->first) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
if (iter->cursor->left != NULL) \
|
||||
{ \
|
||||
iter->cursor = iter->cursor->left; \
|
||||
\
|
||||
while (iter->cursor->right != NULL) \
|
||||
iter->cursor = iter->cursor->right; \
|
||||
\
|
||||
iter->index--; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
while (true) \
|
||||
{ \
|
||||
if (iter->cursor->parent->right == iter->cursor) \
|
||||
{ \
|
||||
iter->cursor = iter->cursor->parent; \
|
||||
\
|
||||
iter->index--; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
iter->cursor = iter->cursor->parent; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor == iter->last) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index + steps >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
CMC_(PFX, _iter_next)(iter); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor == iter->first) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index < steps) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
CMC_(PFX, _iter_prev)(iter); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator was able to be positioned at the */ \
|
||||
/* given index */ \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index) \
|
||||
{ \
|
||||
if (index >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index > index) \
|
||||
return CMC_(PFX, _iter_rewind)(iter, iter->index - index); \
|
||||
else if (iter->index < index) \
|
||||
return CMC_(PFX, _iter_advance)(iter, index - iter->index); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (K){ 0 }; \
|
||||
\
|
||||
return iter->cursor->key; \
|
||||
} \
|
||||
\
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (V){ 0 }; \
|
||||
\
|
||||
return iter->cursor->value; \
|
||||
} \
|
||||
\
|
||||
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return NULL; \
|
||||
\
|
||||
return &(iter->cursor->value); \
|
||||
} \
|
||||
\
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return iter->index; \
|
||||
}
|
||||
|
||||
/**
|
||||
* STR
|
||||
*/
|
||||
#define CMC_EXT_CMC_TREEMAP_STR(PARAMS) \
|
||||
CMC_EXT_CMC_TREEMAP_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_TREEMAP_STR_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_TREEMAP_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_TREEMAP_STR_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_K(PARAMS), \
|
||||
CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_TREEMAP_STR_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_TREEMAP_STR_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_K(PARAMS), \
|
||||
CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_TREEMAP_STR_HEADER_(PFX, SNAME, K, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _map_, FILE * fptr); \
|
||||
bool CMC_(PFX, _print)(struct SNAME * _map_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end, const char *key_val_sep);
|
||||
|
||||
#define CMC_EXT_CMC_TREEMAP_STR_SOURCE_(PFX, SNAME, K, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _map_, FILE * fptr) \
|
||||
{ \
|
||||
struct SNAME *m_ = _map_; \
|
||||
\
|
||||
return 0 <= fprintf(fptr, \
|
||||
"struct %s<%s, %s> " \
|
||||
"at %p { " \
|
||||
"root:%p, " \
|
||||
"count:%" PRIuMAX ", " \
|
||||
"flag:%d, " \
|
||||
"f_val:%p, " \
|
||||
"f_key:%p, " \
|
||||
"alloc:%p, " \
|
||||
"callbacks:%p }", \
|
||||
CMC_TO_STRING(SNAME), CMC_TO_STRING(K), CMC_TO_STRING(V), m_, m_->root, m_->count, \
|
||||
m_->flag, m_->f_key, m_->f_val, m_->alloc, CMC_CALLBACKS_GET(m_)); \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _print)(struct SNAME * _map_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end, const char *key_val_sep) \
|
||||
{ \
|
||||
fprintf(fptr, "%s", start); \
|
||||
\
|
||||
struct CMC_DEF_NODE(SNAME) *root = _map_->root; \
|
||||
\
|
||||
bool left_done = false; \
|
||||
\
|
||||
size_t i = 0; \
|
||||
while (root) \
|
||||
{ \
|
||||
if (!left_done) \
|
||||
{ \
|
||||
while (root->left) \
|
||||
root = root->left; \
|
||||
} \
|
||||
\
|
||||
if (!_map_->f_key->str(fptr, root->key)) \
|
||||
return false; \
|
||||
\
|
||||
fprintf(fptr, "%s", key_val_sep); \
|
||||
\
|
||||
if (!_map_->f_val->str(fptr, root->value)) \
|
||||
return false; \
|
||||
\
|
||||
if (++i < _map_->count) \
|
||||
fprintf(fptr, "%s", separator); \
|
||||
\
|
||||
left_done = true; \
|
||||
\
|
||||
if (root->right) \
|
||||
{ \
|
||||
left_done = false; \
|
||||
root = root->right; \
|
||||
} \
|
||||
else if (root->parent) \
|
||||
{ \
|
||||
while (root->parent && root == root->parent->right) \
|
||||
root = root->parent; \
|
||||
\
|
||||
if (!root->parent) \
|
||||
break; \
|
||||
\
|
||||
root = root->parent; \
|
||||
} \
|
||||
else \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
fprintf(fptr, "%s", end); \
|
||||
\
|
||||
return true; \
|
||||
}
|
||||
|
||||
#endif /* CMC_EXT_CMC_TREEMAP_H */
|
||||
@@ -0,0 +1,649 @@
|
||||
/**
|
||||
* ext/cmc/treeset.h
|
||||
*
|
||||
* Creation Date: 08/06/2020
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CMC_EXT_CMC_TREESET_H
|
||||
#define CMC_EXT_CMC_TREESET_H
|
||||
|
||||
#include "../../cor/core.h"
|
||||
|
||||
/**
|
||||
* All the EXT parts of CMC TreeSet.
|
||||
*/
|
||||
#define CMC_EXT_CMC_TREESET_PARTS ITER, SETF, STR
|
||||
|
||||
/**
|
||||
* ITER
|
||||
*/
|
||||
#define CMC_EXT_CMC_TREESET_ITER(PARAMS) \
|
||||
CMC_EXT_CMC_TREESET_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_TREESET_ITER_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_TREESET_ITER_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_TREESET_ITER_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_TREESET_ITER_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_TREESET_ITER_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_TREESET_ITER_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
/* Treeset Iterator */ \
|
||||
struct CMC_DEF_ITER(SNAME) \
|
||||
{ \
|
||||
/* Target treeset */ \
|
||||
struct SNAME *target; \
|
||||
\
|
||||
/* Cursor's current node */ \
|
||||
struct CMC_DEF_NODE(SNAME) * cursor; \
|
||||
\
|
||||
/* The first node in the iteration */ \
|
||||
struct CMC_DEF_NODE(SNAME) * first; \
|
||||
\
|
||||
/* The last node in the iteration */ \
|
||||
struct CMC_DEF_NODE(SNAME) * last; \
|
||||
\
|
||||
/* 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; \
|
||||
}; \
|
||||
\
|
||||
/* Iterator Initialization */ \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target); \
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target); \
|
||||
/* Iterator State */ \
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
/* Iterator Movement */ \
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps); \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index); \
|
||||
/* Iterator Access */ \
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter); \
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
|
||||
|
||||
#define CMC_EXT_CMC_TREESET_ITER_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = target->root; \
|
||||
iter.first = NULL; \
|
||||
iter.last = NULL; \
|
||||
iter.index = 0; \
|
||||
iter.start = true; \
|
||||
iter.end = CMC_(PFX, _empty)(target); \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
while (iter.cursor->left != NULL) \
|
||||
iter.cursor = iter.cursor->left; \
|
||||
\
|
||||
iter.first = iter.cursor; \
|
||||
\
|
||||
iter.last = target->root; \
|
||||
while (iter.last->right != NULL) \
|
||||
iter.last = iter.last->right; \
|
||||
} \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME * target) \
|
||||
{ \
|
||||
struct CMC_DEF_ITER(SNAME) iter; \
|
||||
\
|
||||
iter.target = target; \
|
||||
iter.cursor = target->root; \
|
||||
iter.first = NULL; \
|
||||
iter.last = NULL; \
|
||||
iter.index = 0; \
|
||||
iter.start = CMC_(PFX, _empty)(target); \
|
||||
iter.end = true; \
|
||||
\
|
||||
if (!CMC_(PFX, _empty)(target)) \
|
||||
{ \
|
||||
while (iter.cursor->right != NULL) \
|
||||
iter.cursor = iter.cursor->right; \
|
||||
\
|
||||
iter.last = iter.cursor; \
|
||||
\
|
||||
iter.first = target->root; \
|
||||
while (iter.first->left != NULL) \
|
||||
iter.first = iter.first->left; \
|
||||
\
|
||||
iter.index = target->count - 1; \
|
||||
} \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return CMC_(PFX, _empty)(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->index = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
iter->cursor = iter->first; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (!CMC_(PFX, _empty)(iter->target)) \
|
||||
{ \
|
||||
iter->index = iter->target->count - 1; \
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
iter->end = true; \
|
||||
iter->cursor = iter->last; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor == iter->last) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->start = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
if (iter->cursor->right != NULL) \
|
||||
{ \
|
||||
iter->cursor = iter->cursor->right; \
|
||||
\
|
||||
while (iter->cursor->left != NULL) \
|
||||
iter->cursor = iter->cursor->left; \
|
||||
\
|
||||
iter->index++; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
while (true) \
|
||||
{ \
|
||||
if (iter->cursor->parent->left == iter->cursor) \
|
||||
{ \
|
||||
iter->cursor = iter->cursor->parent; \
|
||||
\
|
||||
iter->index++; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
iter->cursor = iter->cursor->parent; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor == iter->first) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
iter->end = CMC_(PFX, _empty)(iter->target); \
|
||||
\
|
||||
if (iter->cursor->left != NULL) \
|
||||
{ \
|
||||
iter->cursor = iter->cursor->left; \
|
||||
\
|
||||
while (iter->cursor->right != NULL) \
|
||||
iter->cursor = iter->cursor->right; \
|
||||
\
|
||||
iter->index--; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
while (true) \
|
||||
{ \
|
||||
if (iter->cursor->parent->right == iter->cursor) \
|
||||
{ \
|
||||
iter->cursor = iter->cursor->parent; \
|
||||
\
|
||||
iter->index--; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
iter->cursor = iter->cursor->parent; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor == iter->last) \
|
||||
{ \
|
||||
iter->end = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index + steps >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
CMC_(PFX, _iter_next)(iter); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator moved */ \
|
||||
bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->cursor == iter->first) \
|
||||
{ \
|
||||
iter->start = true; \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
if (steps == 0 || iter->index < steps) \
|
||||
return false; \
|
||||
\
|
||||
for (size_t i = 0; i < steps; i++) \
|
||||
CMC_(PFX, _iter_prev)(iter); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Returns true only if the iterator was able to be positioned at the */ \
|
||||
/* given index */ \
|
||||
bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index) \
|
||||
{ \
|
||||
if (index >= iter->target->count) \
|
||||
return false; \
|
||||
\
|
||||
if (iter->index > index) \
|
||||
return CMC_(PFX, _iter_rewind)(iter, iter->index - index); \
|
||||
else if (iter->index < index) \
|
||||
return CMC_(PFX, _iter_advance)(iter, index - iter->index); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
if (CMC_(PFX, _empty)(iter->target)) \
|
||||
return (V){ 0 }; \
|
||||
\
|
||||
return iter->cursor->value; \
|
||||
} \
|
||||
\
|
||||
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter) \
|
||||
{ \
|
||||
return iter->index; \
|
||||
}
|
||||
|
||||
/**
|
||||
* SETF
|
||||
*/
|
||||
#define CMC_EXT_CMC_TREESET_SETF(PARAMS) \
|
||||
CMC_EXT_CMC_TREESET_SETF_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_TREESET_SETF_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_TREESET_SETF_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_TREESET_SETF_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_TREESET_SETF_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_TREESET_SETF_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_TREESET_SETF_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
/* Set Operations */ \
|
||||
struct SNAME *CMC_(PFX, _union)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
struct SNAME *CMC_(PFX, _intersection)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
struct SNAME *CMC_(PFX, _difference)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
struct SNAME *CMC_(PFX, _symmetric_difference)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_subset)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_superset)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_proper_subset)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_proper_superset)(struct SNAME * _set1_, struct SNAME * _set2_); \
|
||||
bool CMC_(PFX, _is_disjointset)(struct SNAME * _set1_, struct SNAME * _set2_);
|
||||
|
||||
#define CMC_EXT_CMC_TREESET_SETF_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _union)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
struct SNAME *_set_r_ = CMC_(PFX, _new_custom)(_set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
return NULL; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter1 = CMC_(PFX, _iter_start)(_set1_); \
|
||||
struct CMC_DEF_ITER(SNAME) iter2 = CMC_(PFX, _iter_start)(_set2_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter1); CMC_(PFX, _iter_next)(&iter1)) \
|
||||
{ \
|
||||
CMC_(PFX, _insert)(_set_r_, CMC_(PFX, _iter_value)(&iter1)); \
|
||||
} \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter2); CMC_(PFX, _iter_next)(&iter2)) \
|
||||
{ \
|
||||
CMC_(PFX, _insert)(_set_r_, CMC_(PFX, _iter_value)(&iter2)); \
|
||||
} \
|
||||
\
|
||||
CMC_CALLBACKS_ASSIGN(_set_r_, _set1_->callbacks); \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _intersection)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
struct SNAME *_set_r_ = CMC_(PFX, _new_custom)(_set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
return NULL; \
|
||||
\
|
||||
/** TODO Should this compare count or capacity? */ \
|
||||
struct SNAME *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; \
|
||||
struct SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set_A_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_node)(_set_B_, value) != NULL) \
|
||||
CMC_(PFX, _insert)(_set_r_, value); \
|
||||
} \
|
||||
\
|
||||
CMC_CALLBACKS_ASSIGN(_set_r_, _set1_->callbacks); \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _difference)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
struct SNAME *_set_r_ = CMC_(PFX, _new_custom)(_set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
return NULL; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_node)(_set2_, value) == NULL) \
|
||||
CMC_(PFX, _insert)(_set_r_, value); \
|
||||
} \
|
||||
\
|
||||
CMC_CALLBACKS_ASSIGN(_set_r_, _set1_->callbacks); \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *CMC_(PFX, _symmetric_difference)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
struct SNAME *_set_r_ = CMC_(PFX, _new_custom)(_set1_->f_val, _set1_->alloc, NULL); \
|
||||
\
|
||||
if (!_set_r_) \
|
||||
return NULL; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter1 = CMC_(PFX, _iter_start)(_set1_); \
|
||||
struct CMC_DEF_ITER(SNAME) iter2 = CMC_(PFX, _iter_start)(_set2_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter1); CMC_(PFX, _iter_next)(&iter1)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter1); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_node)(_set2_, value) == NULL) \
|
||||
CMC_(PFX, _insert)(_set_r_, value); \
|
||||
} \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter2); CMC_(PFX, _iter_next)(&iter2)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter2); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_node)(_set1_, value) == NULL) \
|
||||
CMC_(PFX, _insert)(_set_r_, value); \
|
||||
} \
|
||||
\
|
||||
CMC_CALLBACKS_ASSIGN(_set_r_, _set1_->callbacks); \
|
||||
\
|
||||
return _set_r_; \
|
||||
} \
|
||||
\
|
||||
/* Is _set1_ a subset of _set2_ ? */ \
|
||||
/* A set X is a subset of a set Y when: X <= Y */ \
|
||||
/* If X is a subset of Y, then Y is a superset of X */ \
|
||||
bool CMC_(PFX, _is_subset)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* If the cardinality of _set1_ is greater than that of _set2_ */ \
|
||||
/* then it is safe to say that _set1_ can't be a subset of _set2_ */ \
|
||||
if (_set1_->count > _set2_->count) \
|
||||
return false; \
|
||||
\
|
||||
/* The empty set is a subset of all sets */ \
|
||||
if (CMC_(PFX, _empty)(_set1_)) \
|
||||
return true; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_node)(_set2_, value) == NULL) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Is _set1_ a superset of _set2_ ? */ \
|
||||
/* A set X is a superset of a set Y when: X >= Y */ \
|
||||
/* If X is a superset of Y, then Y is a subset of X */ \
|
||||
bool CMC_(PFX, _is_superset)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
return CMC_(PFX, _is_subset)(_set2_, _set1_); \
|
||||
} \
|
||||
\
|
||||
/* Is _set1_ a proper subset of _set2_ ? */ \
|
||||
/* A set X is a proper subset of a set Y when: X < Y */ \
|
||||
/* If X is a proper subset of Y, then Y is a proper superset of X */ \
|
||||
bool CMC_(PFX, _is_proper_subset)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* If the cardinality of _set1_ is greater than or equal to that */ \
|
||||
/* of _set2_, then it is safe to say that _set1_ can't be a proper */ \
|
||||
/* subset of _set2_ */ \
|
||||
if (_set1_->count >= _set2_->count) \
|
||||
return false; \
|
||||
\
|
||||
if (CMC_(PFX, _empty)(_set1_)) \
|
||||
{ \
|
||||
/* The empty set is a proper subset of all non-empty sets */ \
|
||||
if (!CMC_(PFX, _empty)(_set2_)) \
|
||||
return true; \
|
||||
/* The empty set is not a proper subset of itself (this is true */ \
|
||||
/* for any set) */ \
|
||||
else \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_node)(_set2_, value) == NULL) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
/* Is _set1_ a proper superset of _set2_ ? */ \
|
||||
/* A set X is a proper superset of a set Y when: X > Y */ \
|
||||
/* If X is a proper superset of Y, then Y is a proper subset of X */ \
|
||||
bool CMC_(PFX, _is_proper_superset)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
return CMC_(PFX, _is_proper_subset)(_set2_, _set1_); \
|
||||
} \
|
||||
\
|
||||
/* Is _set1_ a disjointset of _set2_ ? */ \
|
||||
/* A set X is a disjointset of a set Y if their intersection is empty, */ \
|
||||
/* that is, if there are no elements in common between the two */ \
|
||||
bool CMC_(PFX, _is_disjointset)(struct SNAME * _set1_, struct SNAME * _set2_) \
|
||||
{ \
|
||||
/* The intersection of an empty set with any other set will result */ \
|
||||
/* in an empty set */ \
|
||||
if (CMC_(PFX, _empty)(_set1_)) \
|
||||
return true; \
|
||||
\
|
||||
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_); \
|
||||
\
|
||||
for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter)) \
|
||||
{ \
|
||||
V value = CMC_(PFX, _iter_value)(&iter); \
|
||||
\
|
||||
if (CMC_(PFX, _impl_get_node)(_set2_, value) != NULL) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* STR
|
||||
*/
|
||||
#define CMC_EXT_CMC_TREESET_STR(PARAMS) \
|
||||
CMC_EXT_CMC_TREESET_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_TREESET_STR_SOURCE(PARAMS)
|
||||
|
||||
#define CMC_EXT_CMC_TREESET_STR_HEADER(PARAMS) \
|
||||
CMC_EXT_CMC_TREESET_STR_HEADER_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_TREESET_STR_SOURCE(PARAMS) \
|
||||
CMC_EXT_CMC_TREESET_STR_SOURCE_(CMC_PARAM_PFX(PARAMS), CMC_PARAM_SNAME(PARAMS), CMC_PARAM_V(PARAMS))
|
||||
|
||||
#define CMC_EXT_CMC_TREESET_STR_HEADER_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _set_, FILE * fptr); \
|
||||
bool CMC_(PFX, _print)(struct SNAME * _set_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end);
|
||||
|
||||
#define CMC_EXT_CMC_TREESET_STR_SOURCE_(PFX, SNAME, V) \
|
||||
\
|
||||
bool CMC_(PFX, _to_string)(struct SNAME * _set_, FILE * fptr) \
|
||||
{ \
|
||||
struct SNAME *s_ = _set_; \
|
||||
\
|
||||
return 0 <= fprintf(fptr, \
|
||||
"struct %s<%s> " \
|
||||
"at %p { " \
|
||||
"root:%p, " \
|
||||
"count:%" PRIuMAX ", " \
|
||||
"flag:%d, " \
|
||||
"f_val:%p, " \
|
||||
"alloc:%p, " \
|
||||
"callbacks:%p }", \
|
||||
CMC_TO_STRING(SNAME), CMC_TO_STRING(V), s_, s_->root, s_->count, s_->flag, s_->f_val, \
|
||||
s_->alloc, CMC_CALLBACKS_GET(s_)); \
|
||||
} \
|
||||
\
|
||||
bool CMC_(PFX, _print)(struct SNAME * _set_, FILE * fptr, const char *start, const char *separator, \
|
||||
const char *end) \
|
||||
{ \
|
||||
fprintf(fptr, "%s", start); \
|
||||
\
|
||||
struct CMC_DEF_NODE(SNAME) *root = _set_->root; \
|
||||
\
|
||||
bool left_done = false; \
|
||||
\
|
||||
size_t i = 0; \
|
||||
while (root) \
|
||||
{ \
|
||||
if (!left_done) \
|
||||
{ \
|
||||
while (root->left) \
|
||||
root = root->left; \
|
||||
} \
|
||||
\
|
||||
if (!_set_->f_val->str(fptr, root->value)) \
|
||||
return false; \
|
||||
\
|
||||
if (++i < _set_->count) \
|
||||
fprintf(fptr, "%s", separator); \
|
||||
\
|
||||
left_done = true; \
|
||||
\
|
||||
if (root->right) \
|
||||
{ \
|
||||
left_done = false; \
|
||||
root = root->right; \
|
||||
} \
|
||||
else if (root->parent) \
|
||||
{ \
|
||||
while (root->parent && root == root->parent->right) \
|
||||
root = root->parent; \
|
||||
\
|
||||
if (!root->parent) \
|
||||
break; \
|
||||
\
|
||||
root = root->parent; \
|
||||
} \
|
||||
else \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
fprintf(fptr, "%s", end); \
|
||||
\
|
||||
return true; \
|
||||
}
|
||||
|
||||
#endif /* CMC_EXT_CMC_TREESET_H */
|
||||
+225
-38
@@ -8,54 +8,241 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file provides everything from the C Macro Collections library.
|
||||
*
|
||||
* Every data structure and features are available through this header. There is
|
||||
* also three macros that can help you generate whichever Collection you need
|
||||
* from any given sub-library. They are:
|
||||
*
|
||||
* - C_MACRO_COLLECTIONS
|
||||
* - C_MACRO_COLLECTIONS_GEN
|
||||
* - C_MACRO_COLLECTIONS_GEN_HEADER
|
||||
* - C_MACRO_COLLECTIONS_GEN_SOURCE
|
||||
* - C_MACRO_COLLECTIONS_ALL
|
||||
* - C_MACRO_COLLECTIONS_ALL_HEADER
|
||||
* - C_MACRO_COLLECTIONS_ALL_SOURCE
|
||||
*/
|
||||
#ifndef CMC_MACRO_COLLECTIONS_H
|
||||
#define CMC_MACRO_COLLECTIONS_H
|
||||
|
||||
#define CMC_CONCAT_(C, T) CMC_WRAPGEN_##C##_##T
|
||||
// clang-format off
|
||||
#include "cmc/bitset.h" /* Added in 30/04/2020 */
|
||||
#include "cmc/deque.h" /* Added in 20/03/2019 */
|
||||
#include "cmc/hashbidimap.h" /* Added in 26/09/2019 */
|
||||
#include "cmc/hashmap.h" /* Added in 03/04/2019 */
|
||||
#include "cmc/hashmultimap.h" /* Added in 26/04/2019 */
|
||||
#include "cmc/hashmultiset.h" /* Added in 10/04/2019 */
|
||||
#include "cmc/hashset.h" /* Added in 01/04/2019 */
|
||||
#include "cmc/heap.h" /* Added in 25/03/2019 */
|
||||
#include "cmc/intervalheap.h" /* Added in 06/07/2019 */
|
||||
#include "cmc/linkedlist.h" /* Added in 22/03/2019 */
|
||||
#include "cmc/list.h" /* Added in 12/02/2019 */
|
||||
#include "cmc/queue.h" /* Added in 15/02/2019 */
|
||||
#include "cmc/sortedlist.h" /* Added in 17/09/2019 */
|
||||
#include "cmc/stack.h" /* Added in 14/02/2019 */
|
||||
#include "cmc/treemap.h" /* Added in 28/03/2019 */
|
||||
#include "cmc/treeset.h" /* Added in 27/03/2019 */
|
||||
|
||||
#define CMC_CONCAT(C, T) CMC_CONCAT_(C, T)
|
||||
#include "cor/alloc.h" /* Added in 24/05/2020 */
|
||||
#include "cor/bitset.h" /* Added in 20/05/2020 */
|
||||
#include "cor/callbacks.h" /* Added in 24/05/2020 */
|
||||
#include "cor/core.h" /* Added in 17/03/2020 */
|
||||
#include "cor/flags.h" /* Added in 14/05/2020 */
|
||||
#include "cor/ftable.h" /* Added in 27/05/2020 */
|
||||
#include "cor/hashtable.h" /* Added in 17/03/2020 */
|
||||
#include "cor/heap.h" /* Added in 01/06/2020 */
|
||||
|
||||
#define CMC_COLLECTION_GENERATE(C, PFX, SNAME, K, V) \
|
||||
CMC_COLLECTION_GENERATE_HEADER(C, PFX, SNAME, K, V) \
|
||||
CMC_COLLECTION_GENERATE_SOURCE(C, PFX, SNAME, K, V)
|
||||
#include "ext/cmc/bitset.h" /* Added in 08/06/2020 */
|
||||
#include "ext/cmc/deque.h" /* Added in 25/05/2020 */
|
||||
#include "ext/cmc/hashbidimap.h" /* Added in 26/05/2020 */
|
||||
#include "ext/cmc/hashmap.h" /* Added in 25/05/2020 */
|
||||
#include "ext/cmc/hashmultimap.h" /* Added in 29/05/2020 */
|
||||
#include "ext/cmc/hashmultiset.h" /* Added in 30/05/2020 */
|
||||
#include "ext/cmc/hashset.h" /* Added in 31/05/2020 */
|
||||
#include "ext/cmc/heap.h" /* Added in 01/06/2020 */
|
||||
#include "ext/cmc/intervalheap.h" /* Added in 02/06/2020 */
|
||||
#include "ext/cmc/linkedlist.h" /* Added in 03/06/2020 */
|
||||
#include "ext/cmc/list.h" /* Added in 04/06/2020 */
|
||||
#include "ext/cmc/queue.h" /* Added in 05/06/2020 */
|
||||
#include "ext/cmc/sortedlist.h" /* Added in 06/06/2020 */
|
||||
#include "ext/cmc/stack.h" /* Added in 07/06/2020 */
|
||||
#include "ext/cmc/treemap.h" /* Added in 08/06/2020 */
|
||||
#include "ext/cmc/treeset.h" /* Added in 08/06/2020 */
|
||||
|
||||
#define CMC_COLLECTION_GENERATE_HEADER(C, PFX, SNAME, K, V) \
|
||||
CMC_CONCAT(C, HEADER)(PFX, SNAME, K, V)
|
||||
#include "utl/assert.h" /* Added in 27/06/2019 */
|
||||
#include "utl/foreach.h" /* Added in 25/02/2019 */
|
||||
#include "utl/futils.h" /* Added in 15/04/2020 */
|
||||
#include "utl/log.h" /* Added in 21/06/2019 */
|
||||
#include "utl/mutex.h" /* Added in 14/05/2020 */
|
||||
#include "utl/test.h" /* Added in 26/06/2019 */
|
||||
#include "utl/thread.h" /* Added in 14/05/2020 */
|
||||
#include "utl/timer.h" /* Added in 12/04/2019 */
|
||||
// clang-format on
|
||||
|
||||
#define CMC_COLLECTION_GENERATE_SOURCE(C, PFX, SNAME, K, V) \
|
||||
CMC_CONCAT(C, SOURCE)(PFX, SNAME, K, V)
|
||||
/**
|
||||
* C_MACRO_COLLECTIONS
|
||||
*
|
||||
* Generate a specific part of a specific collection from a specific library.
|
||||
*
|
||||
* \param LIB The collection's sub-library
|
||||
* \param COLLECTION The name of the collection in all uppercase
|
||||
* \param PART The part of the collection (either CORE or one available at EXT)
|
||||
* \param FILE Either HEADER or SOURCE
|
||||
* \param PARAMS A tuple of form (PFX, SNAME, SIZE, K, V)
|
||||
*/
|
||||
#define C_MACRO_COLLECTIONS(LIB, COLLECTION, PART, FILE, PARAMS) \
|
||||
C_MACRO_COLLECTIONS_(LIB, COLLECTION, PART, FILE)(PARAMS)
|
||||
#define C_MACRO_COLLECTIONS_(LIB, COLLECTION, PART, FILE) CMC_##LIB##_##COLLECTION##_##PART##_##FILE
|
||||
|
||||
#include "cor/core.h" /* Added in 17/03/2020 */
|
||||
#include "cor/flags.h" /* Added in 14/05/2020 */
|
||||
#include "cor/hashtable.h" /* Added in 17/03/2020 */
|
||||
/**
|
||||
* C_MACRO_COLLECTIONS_GEN
|
||||
*
|
||||
* Generate the CORE of a collection along with one or more part from EXT. The
|
||||
* headers are generated first, then the source code.
|
||||
*
|
||||
* \param LIB The collection's sub-library
|
||||
* \param COLLECTION The name of the collection in all uppercase
|
||||
* \param PARAMS A tuple of form (PFX, SNAME, SIZE, K, V)
|
||||
* \param PARTS A non-empty tuple of all desired EXT parts
|
||||
*/
|
||||
#define C_MACRO_COLLECTIONS_GEN(LIB, COLLECTION, PARAMS, PARTS) \
|
||||
C_MACRO_COLLECTIONS_GEN_HEADER(LIB, COLLECTION, PARAMS, PARTS) \
|
||||
C_MACRO_COLLECTIONS_GEN_SOURCE(LIB, COLLECTION, PARAMS, PARTS)
|
||||
|
||||
#include "cmc/bitset.h" /* Added in 30/04/2020 */
|
||||
#include "cmc/deque.h" /* Added in 20/03/2019 */
|
||||
#include "cmc/hashbidimap.h" /* Added in 26/09/2019 */
|
||||
#include "cmc/hashmap.h" /* Added in 03/04/2019 */
|
||||
#include "cmc/hashmultimap.h" /* Added in 26/04/2019 */
|
||||
#include "cmc/hashmultiset.h" /* Added in 10/04/2019 */
|
||||
#include "cmc/hashset.h" /* Added in 01/04/2019 */
|
||||
#include "cmc/heap.h" /* Added in 25/03/2019 */
|
||||
#include "cmc/intervalheap.h" /* Added in 06/07/2019 */
|
||||
#include "cmc/linkedlist.h" /* Added in 22/03/2019 */
|
||||
#include "cmc/list.h" /* Added in 12/02/2019 */
|
||||
#include "cmc/queue.h" /* Added in 15/02/2019 */
|
||||
#include "cmc/sortedlist.h" /* Added in 17/09/2019 */
|
||||
#include "cmc/stack.h" /* Added in 14/02/2019 */
|
||||
#include "cmc/treemap.h" /* Added in 28/03/2019 */
|
||||
#include "cmc/treeset.h" /* Added in 27/03/2019 */
|
||||
/**
|
||||
* C_MACRO_COLLECTIONS_GEN_HEADER
|
||||
*
|
||||
* Generate all headers of CORE and the specified header parts of a collection.
|
||||
*
|
||||
* \param LIB The collection's sub-library
|
||||
* \param COLLECTION The name of the collection in all uppercase
|
||||
* \param PARAMS A tuple of form (PFX, SNAME, SIZE, K, V)
|
||||
* \param PARTS A non-empty tuple of all desired EXT parts
|
||||
*/
|
||||
#define C_MACRO_COLLECTIONS_GEN_HEADER(LIB, COLLECTION, PARAMS, PARTS) \
|
||||
C_MACRO_COLLECTIONS(LIB, COLLECTION, CORE_PUBLIC, HEADER, PARAMS) \
|
||||
CMC_MAP(CMC_(EXT_, LIB), COLLECTION, HEADER, PARAMS, CMC_EVAL PARTS)
|
||||
|
||||
#include "sac/queue.h"
|
||||
#include "sac/stack.h"
|
||||
/**
|
||||
* C_MACRO_COLLECTIONS_GEN_SOURCE
|
||||
*
|
||||
* Generate all sources of CORE and the specified source parts of a collection.
|
||||
*
|
||||
* \param LIB The collection's sub-library
|
||||
* \param COLLECTION The name of the collection in all uppercase
|
||||
* \param PARAMS A tuple of form (PFX, SNAME, SIZE, K, V)
|
||||
* \param PARTS A non-empty tuple of all desired EXT parts
|
||||
*/
|
||||
#define C_MACRO_COLLECTIONS_GEN_SOURCE(LIB, COLLECTION, PARAMS, PARTS) \
|
||||
C_MACRO_COLLECTIONS(LIB, COLLECTION, CORE_PUBLIC, SOURCE, PARAMS) \
|
||||
CMC_MAP(CMC_(EXT_, LIB), COLLECTION, SOURCE, PARAMS, CMC_EVAL PARTS)
|
||||
|
||||
#include "utl/assert.h" /* Added in 27/06/2019 */
|
||||
#include "utl/foreach.h" /* Added in 25/02/2019 */
|
||||
#include "utl/futils.h" /* Added in 15/04/2020 */
|
||||
#include "utl/log.h" /* Added in 21/06/2019 */
|
||||
#include "utl/mutex.h" /* Added in 14/05/2020 */
|
||||
#include "utl/test.h" /* Added in 26/06/2019 */
|
||||
#include "utl/thread.h" /* Added in 14/05/2020 */
|
||||
#include "utl/timer.h" /* Added in 12/04/2019 */
|
||||
/**
|
||||
* C_MACRO_COLLECTIONS_ALL
|
||||
*
|
||||
* Generate everything provided by a collection included in the EXT library. The
|
||||
* headers are generated first, then the source code.
|
||||
*
|
||||
* \param LIB The collection's library
|
||||
* \param COLLECTION The name of the collection in all uppercase
|
||||
* \param PARAMS A tuple of form (PFX, SNAME, SIZE, K, V
|
||||
*/
|
||||
#define C_MACRO_COLLECTIONS_ALL(LIB, COLLECTION, PARAMS) \
|
||||
C_MACRO_COLLECTIONS_ALL_HEADER(LIB, COLLECTION, PARAMS) \
|
||||
C_MACRO_COLLECTIONS_ALL_SOURCE(LIB, COLLECTION, PARAMS)
|
||||
|
||||
/**
|
||||
* C_MACRO_COLLECTIONS_ALL_HEADER
|
||||
*
|
||||
* Generates all headers (CORE and those at EXT) from a given collection.
|
||||
*
|
||||
* \param LIB The collection's library
|
||||
* \param COLLECTION The name of the collection in all uppercase
|
||||
* \param PARAMS A tuple of form (PFX, SNAME, SIZE, K, V
|
||||
*/
|
||||
#define C_MACRO_COLLECTIONS_ALL_HEADER(LIB, COLLECTION, PARAMS) \
|
||||
C_MACRO_COLLECTIONS(LIB, COLLECTION, CORE_PUBLIC, HEADER, PARAMS) \
|
||||
CMC_MAP(CMC_(EXT_, LIB), COLLECTION, HEADER, PARAMS, C_MACRO_COLLECTIONS_PARTS(LIB, COLLECTION))
|
||||
|
||||
/**
|
||||
* C_MACRO_COLLECTIONS_ALL_SOURCE
|
||||
*
|
||||
* Generates all sources (CORE and those at EXT) from a given collection.
|
||||
*
|
||||
* \param LIB The collection's library
|
||||
* \param COLLECTION The name of the collection in all uppercase
|
||||
* \param PARAMS A tuple of form (PFX, SNAME, SIZE, K, V
|
||||
*/
|
||||
#define C_MACRO_COLLECTIONS_ALL_SOURCE(LIB, COLLECTION, PARAMS) \
|
||||
C_MACRO_COLLECTIONS(LIB, COLLECTION, CORE_PUBLIC, SOURCE, PARAMS) \
|
||||
CMC_MAP(CMC_(EXT_, LIB), COLLECTION, SOURCE, PARAMS, C_MACRO_COLLECTIONS_PARTS(LIB, COLLECTION))
|
||||
|
||||
/**
|
||||
* C_MACRO_COLLECTIONS_PARTS
|
||||
*
|
||||
* Gets the macro with all EXT parts of a collection. Every collection has this
|
||||
* macro defined in the EXT libraries.
|
||||
*/
|
||||
#define C_MACRO_COLLECTIONS_PARTS(LIB, COLLECTION) CMC_EXT_##LIB##_##COLLECTION##_PARTS,
|
||||
|
||||
/* Evaluates a tuple so that (A, B) -> A, B, */
|
||||
#define CMC_EVAL(...) __VA_ARGS__,
|
||||
|
||||
/**
|
||||
* A __VA_ARGS__ argument counter. This argument counter is slightly shifted:
|
||||
*
|
||||
* CMC_NARG(HELLO) -> 0
|
||||
* CMC_NARG(HELLO,) -> 1
|
||||
* CMC_NARG(HELLO, WORLD,) -> 2
|
||||
*/
|
||||
#define CMC_NARG(...) CMC_NARG_(__VA_ARGS__, CMC_SEQ_N())
|
||||
#define CMC_NARG_(...) CMC_ARG_N(__VA_ARGS__)
|
||||
#define CMC_ARG_N(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, \
|
||||
_22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, \
|
||||
_42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, \
|
||||
_62, _63, N, ...) \
|
||||
N
|
||||
#define CMC_SEQ_N() \
|
||||
63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, \
|
||||
35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, \
|
||||
7, 6, 5, 4, 3, 2, 1, 0
|
||||
|
||||
/* Generates the FILE for each part (__VA_ARGS__) of a collection */
|
||||
#define CMC_MAP(LIB, COLLECTION, FILE, PARAMS, ...) \
|
||||
CMC_(CMC_MAP_, CMC_NARG(__VA_ARGS__)) \
|
||||
(LIB, COLLECTION, FILE, PARAMS, __VA_ARGS__)
|
||||
|
||||
#define CMC_MAP_0(LIB, COLLECTION, FILE, PARAMS, PART, ...)
|
||||
#define CMC_MAP_1(LIB, COLLECTION, FILE, PARAMS, PART, ...) \
|
||||
C_MACRO_COLLECTIONS(LIB, COLLECTION, PART, FILE, PARAMS) \
|
||||
CMC_MAP_0(LIB, COLLECTION, FILE, PARAMS, __VA_ARGS__)
|
||||
#define CMC_MAP_2(LIB, COLLECTION, FILE, PARAMS, PART, ...) \
|
||||
C_MACRO_COLLECTIONS(LIB, COLLECTION, PART, FILE, PARAMS) \
|
||||
CMC_MAP_1(LIB, COLLECTION, FILE, PARAMS, __VA_ARGS__)
|
||||
#define CMC_MAP_3(LIB, COLLECTION, FILE, PARAMS, PART, ...) \
|
||||
C_MACRO_COLLECTIONS(LIB, COLLECTION, PART, FILE, PARAMS) \
|
||||
CMC_MAP_2(LIB, COLLECTION, FILE, PARAMS, __VA_ARGS__)
|
||||
#define CMC_MAP_4(LIB, COLLECTION, FILE, PARAMS, PART, ...) \
|
||||
C_MACRO_COLLECTIONS(LIB, COLLECTION, PART, FILE, PARAMS) \
|
||||
CMC_MAP_3(LIB, COLLECTION, FILE, PARAMS, __VA_ARGS__)
|
||||
#define CMC_MAP_5(LIB, COLLECTION, FILE, PARAMS, PART, ...) \
|
||||
C_MACRO_COLLECTIONS(LIB, COLLECTION, PART, FILE, PARAMS) \
|
||||
CMC_MAP_4(LIB, COLLECTION, FILE, PARAMS, __VA_ARGS__)
|
||||
#define CMC_MAP_6(LIB, COLLECTION, FILE, PARAMS, PART, ...) \
|
||||
C_MACRO_COLLECTIONS(LIB, COLLECTION, PART, FILE, PARAMS) \
|
||||
CMC_MAP_5(LIB, COLLECTION, FILE, PARAMS, __VA_ARGS__)
|
||||
#define CMC_MAP_7(LIB, COLLECTION, FILE, PARAMS, PART, ...) \
|
||||
C_MACRO_COLLECTIONS(LIB, COLLECTION, PART, FILE, PARAMS) \
|
||||
CMC_MAP_6(LIB, COLLECTION, FILE, PARAMS, __VA_ARGS__)
|
||||
#define CMC_MAP_8(LIB, COLLECTION, FILE, PARAMS, PART, ...) \
|
||||
C_MACRO_COLLECTIONS(LIB, COLLECTION, PART, FILE, PARAMS) \
|
||||
CMC_MAP_7(LIB, COLLECTION, FILE, PARAMS, __VA_ARGS__)
|
||||
#define CMC_MAP_9(LIB, COLLECTION, FILE, PARAMS, PART, ...) \
|
||||
C_MACRO_COLLECTIONS(LIB, COLLECTION, PART, FILE, PARAMS) \
|
||||
CMC_MAP_8(LIB, COLLECTION, FILE, PARAMS, __VA_ARGS__)
|
||||
#define CMC_MAP_10(LIB, COLLECTION, FILE, PARAMS, PART, ...) \
|
||||
C_MACRO_COLLECTIONS(LIB, COLLECTION, PART, FILE, PARAMS) \
|
||||
CMC_MAP_9(LIB, COLLECTION, FILE, PARAMS, __VA_ARGS__)
|
||||
|
||||
#endif /* CMC_MACRO_COLLECTIONS_H */
|
||||
-357
@@ -1,357 +0,0 @@
|
||||
/**
|
||||
* queue.h
|
||||
*
|
||||
* Creation Date: 24/06/2019
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* A Purely Stack Allocated Queue
|
||||
*
|
||||
* This means that the Queue has a fixed size, but it also has the advantage of
|
||||
* not requiring for manually allocating and deallocating the struct.
|
||||
*
|
||||
* Generating a collection with too big of a storage can be dangerous and might
|
||||
* quickly cause a stack overflow.
|
||||
*
|
||||
* It is recommended to not generate any Stack Allocated Collection with less
|
||||
* than 1000 internal storage.
|
||||
*/
|
||||
|
||||
#ifndef CMC_SAC_QUEUE_H
|
||||
#define CMC_SAC_QUEUE_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#define SAC_QUEUE_GENERATE(PFX, SNAME, FMOD, V, SIZE) \
|
||||
SAC_QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V, SIZE) \
|
||||
SAC_QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V, SIZE)
|
||||
|
||||
#define SAC_QUEUE_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V, SIZE) \
|
||||
SAC_QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V, SIZE)
|
||||
|
||||
#define SAC_QUEUE_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V, SIZE) \
|
||||
SAC_QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V, SIZE)
|
||||
|
||||
/* HEADER ********************************************************************/
|
||||
#define SAC_QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V, SIZE) \
|
||||
\
|
||||
/* Queue Structure */ \
|
||||
typedef struct SNAME##_s \
|
||||
{ \
|
||||
/* Internal Storage */ \
|
||||
V buffer[SIZE]; \
|
||||
\
|
||||
/* Current amount of elements */ \
|
||||
size_t count; \
|
||||
\
|
||||
/* Index representing the front of the queue */ \
|
||||
size_t front; \
|
||||
\
|
||||
/* Index representing the back of the queue */ \
|
||||
size_t rear; \
|
||||
\
|
||||
/* Function that returns an iterator to the start of the queue */ \
|
||||
struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
|
||||
\
|
||||
/* Function that returns an iterator to the end of the queue */ \
|
||||
struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
|
||||
\
|
||||
} SNAME, *SNAME##_ptr; \
|
||||
\
|
||||
/* Queue Iterator */ \
|
||||
typedef struct SNAME##_iter_s \
|
||||
{ \
|
||||
/* Target queue */ \
|
||||
struct SNAME##_s *target; \
|
||||
\
|
||||
/* Cursor's position (index) */ \
|
||||
size_t cursor; \
|
||||
\
|
||||
/* Keeps track of relative index to the iteration of elements */ \
|
||||
size_t index; \
|
||||
\
|
||||
/* If the iterator has reached the start of the iteration */ \
|
||||
bool start; \
|
||||
\
|
||||
/* If the iterator has reached the end of the iteration */ \
|
||||
bool end; \
|
||||
\
|
||||
} SNAME##_iter, *SNAME##_iter_ptr; \
|
||||
\
|
||||
/* Collection Functions */ \
|
||||
/* Collection Allocation and Deallocation */ \
|
||||
FMOD SNAME PFX##_new(void); \
|
||||
FMOD void PFX##_clear(SNAME *_queue_); \
|
||||
/* Collection Input and Output */ \
|
||||
FMOD bool PFX##_enqueue(SNAME *_queue_, V element); \
|
||||
FMOD bool PFX##_dequeue(SNAME *_queue_); \
|
||||
/* Conditional Input and Output */ \
|
||||
FMOD bool PFX##_enqueue_if(SNAME *_queue_, V element, bool condition); \
|
||||
FMOD bool PFX##_dequeue_if(SNAME *_queue_, bool condition); \
|
||||
/* Element Access */ \
|
||||
FMOD V PFX##_peek(SNAME *_queue_); \
|
||||
/* Collection State */ \
|
||||
FMOD bool PFX##_contains(SNAME *_queue_, V element, int (*comparator)(V, V)); \
|
||||
FMOD bool PFX##_empty(SNAME *_queue_); \
|
||||
FMOD bool PFX##_full(SNAME *_queue_); \
|
||||
FMOD size_t PFX##_count(SNAME *_queue_); \
|
||||
FMOD size_t PFX##_capacity(void); \
|
||||
\
|
||||
/* Iterator Functions */ \
|
||||
/* Iterator Initialization */ \
|
||||
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \
|
||||
/* Iterator State */ \
|
||||
FMOD bool PFX##_iter_start(SNAME##_iter *iter); \
|
||||
FMOD bool PFX##_iter_end(SNAME##_iter *iter); \
|
||||
/* Iterator Movement */ \
|
||||
FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \
|
||||
FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \
|
||||
FMOD bool PFX##_iter_next(SNAME##_iter *iter); \
|
||||
FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \
|
||||
/* Iterator Access */ \
|
||||
FMOD V PFX##_iter_value(SNAME##_iter *iter); \
|
||||
FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \
|
||||
FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \
|
||||
\
|
||||
/* Default Value */ \
|
||||
static inline V PFX##_impl_default_value(void) \
|
||||
{ \
|
||||
V _empty_value_; \
|
||||
\
|
||||
memset(&_empty_value_, 0, sizeof(V)); \
|
||||
\
|
||||
return _empty_value_; \
|
||||
} \
|
||||
\
|
||||
/* SOURCE ********************************************************************/
|
||||
#define SAC_QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V, SIZE) \
|
||||
\
|
||||
/* Implementation Detail Functions */ \
|
||||
static SNAME##_iter PFX##_impl_it_start(SNAME *_queue_); \
|
||||
static SNAME##_iter PFX##_impl_it_end(SNAME *_queue_); \
|
||||
\
|
||||
FMOD SNAME PFX##_new(void) \
|
||||
{ \
|
||||
SNAME result; \
|
||||
\
|
||||
memset(&result, 0, sizeof(SNAME)); \
|
||||
\
|
||||
result.it_start = PFX##_impl_it_start; \
|
||||
result.it_end = PFX##_impl_it_end; \
|
||||
\
|
||||
return result; \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_clear(SNAME *_queue_) \
|
||||
{ \
|
||||
memset(_queue_->buffer, 0, sizeof(_queue_->buffer)); \
|
||||
\
|
||||
_queue_->count = 0; \
|
||||
_queue_->front = 0; \
|
||||
_queue_->rear = 0; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_enqueue(SNAME *_queue_, V element) \
|
||||
{ \
|
||||
if (PFX##_full(_queue_)) \
|
||||
return false; \
|
||||
\
|
||||
_queue_->buffer[_queue_->rear] = element; \
|
||||
\
|
||||
_queue_->rear = (_queue_->rear == SIZE - 1) ? 0 : _queue_->rear + 1; \
|
||||
_queue_->count++; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_dequeue(SNAME *_queue_) \
|
||||
{ \
|
||||
if (PFX##_empty(_queue_)) \
|
||||
return false; \
|
||||
\
|
||||
_queue_->buffer[_queue_->front] = PFX##_impl_default_value(); \
|
||||
\
|
||||
_queue_->front = (_queue_->front == SIZE - 1) ? 0 : _queue_->front + 1; \
|
||||
_queue_->count--; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_enqueue_if(SNAME *_queue_, V element, bool condition) \
|
||||
{ \
|
||||
if (condition) \
|
||||
return PFX##_enqueue(_queue_, element); \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_dequeue_if(SNAME *_queue_, bool condition) \
|
||||
{ \
|
||||
if (condition) \
|
||||
return PFX##_dequeue(_queue_); \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
FMOD V PFX##_peek(SNAME *_queue_) \
|
||||
{ \
|
||||
if (PFX##_empty(_queue_)) \
|
||||
return PFX##_impl_default_value(); \
|
||||
\
|
||||
return _queue_->buffer[_queue_->front]; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_contains(SNAME *_queue_, V element, int (*comparator)(V, V)) \
|
||||
{ \
|
||||
for (size_t i = _queue_->front, j = 0; j < _queue_->count; i = (i + 1) % _queue_->count, j++) \
|
||||
{ \
|
||||
if (comparator(_queue_->buffer[i], element) == 0) \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_empty(SNAME *_queue_) \
|
||||
{ \
|
||||
return _queue_->count == 0; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_full(SNAME *_queue_) \
|
||||
{ \
|
||||
return _queue_->count >= SIZE; \
|
||||
} \
|
||||
\
|
||||
FMOD size_t PFX##_count(SNAME *_queue_) \
|
||||
{ \
|
||||
return _queue_->count; \
|
||||
} \
|
||||
\
|
||||
FMOD size_t PFX##_capacity(void) \
|
||||
{ \
|
||||
return SIZE; \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \
|
||||
{ \
|
||||
iter->target = target; \
|
||||
iter->cursor = target->front; \
|
||||
iter->index = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = PFX##_empty(target); \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_iter_start(SNAME##_iter *iter) \
|
||||
{ \
|
||||
return PFX##_empty(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_iter_end(SNAME##_iter *iter) \
|
||||
{ \
|
||||
return PFX##_empty(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \
|
||||
{ \
|
||||
iter->cursor = iter->target->front; \
|
||||
iter->index = 0; \
|
||||
iter->start = true; \
|
||||
iter->end = PFX##_empty(iter->target); \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (PFX##_empty(iter->target)) \
|
||||
iter->cursor = 0; \
|
||||
else \
|
||||
iter->cursor = (iter->target->rear == 0) ? SIZE - 1 : iter->target->rear - 1; \
|
||||
\
|
||||
iter->index = iter->target->count - 1; \
|
||||
iter->start = PFX##_empty(iter->target); \
|
||||
iter->end = true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_iter_next(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
iter->start = PFX##_empty(iter->target); \
|
||||
\
|
||||
if (iter->index == iter->target->count - 1) \
|
||||
iter->end = true; \
|
||||
else \
|
||||
{ \
|
||||
iter->cursor = (iter->cursor + 1) % (SIZE); \
|
||||
iter->index++; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
iter->end = PFX##_empty(iter->target); \
|
||||
\
|
||||
if (iter->index == 0) \
|
||||
iter->start = true; \
|
||||
else \
|
||||
{ \
|
||||
iter->cursor = (iter->cursor == 0) ? SIZE - 1 : iter->cursor - 1; \
|
||||
iter->index--; \
|
||||
} \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (PFX##_empty(iter->target)) \
|
||||
return PFX##_impl_default_value(); \
|
||||
\
|
||||
return iter->target->buffer[iter->cursor]; \
|
||||
} \
|
||||
\
|
||||
FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (PFX##_empty(iter->target)) \
|
||||
return NULL; \
|
||||
\
|
||||
return &(iter->target->buffer[iter->cursor]); \
|
||||
} \
|
||||
\
|
||||
FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \
|
||||
{ \
|
||||
return iter->index; \
|
||||
} \
|
||||
\
|
||||
static SNAME##_iter PFX##_impl_it_start(SNAME *_queue_) \
|
||||
{ \
|
||||
SNAME##_iter iter; \
|
||||
\
|
||||
PFX##_iter_init(&iter, _queue_); \
|
||||
PFX##_iter_to_start(&iter); \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
static SNAME##_iter PFX##_impl_it_end(SNAME *_queue_) \
|
||||
{ \
|
||||
SNAME##_iter iter; \
|
||||
\
|
||||
PFX##_iter_init(&iter, _queue_); \
|
||||
PFX##_iter_to_end(&iter); \
|
||||
\
|
||||
return iter; \
|
||||
}
|
||||
|
||||
#endif /* CMC_SAC_QUEUE_H */
|
||||
-327
@@ -1,327 +0,0 @@
|
||||
/**
|
||||
* stack.h
|
||||
*
|
||||
* Creation Date: 21/06/2019
|
||||
*
|
||||
* Authors:
|
||||
* Leonardo Vencovsky (https://github.com/LeoVen)
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* A Purely Stack Allocated Stack
|
||||
*
|
||||
* This means that the Stack has a fixed size, but it also has the advantage of
|
||||
* not requiring for manually allocating and deallocating the struct.
|
||||
*
|
||||
* Generating a collection with too big of a storage can be dangerous and might
|
||||
* quickly cause a stack overflow.
|
||||
*
|
||||
* It is recommended to not generate any Stack Allocated Collection with less
|
||||
* than 1000 internal storage.
|
||||
*/
|
||||
|
||||
#ifndef CMC_SAC_STACK_H
|
||||
#define CMC_SAC_STACK_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#define SAC_STACK_GENERATE(PFX, SNAME, FMOD, V, SIZE) \
|
||||
SAC_STACK_GENERATE_HEADER(PFX, SNAME, FMOD, V, SIZE) \
|
||||
SAC_STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, V, SIZE)
|
||||
|
||||
#define SAC_STACK_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V, SIZE) \
|
||||
SAC_STACK_GENERATE_HEADER(PFX, SNAME, FMOD, V, SIZE)
|
||||
|
||||
#define SAC_STACK_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V, SIZE) \
|
||||
SAC_STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, V, SIZE)
|
||||
|
||||
/* HEADER ********************************************************************/
|
||||
#define SAC_STACK_GENERATE_HEADER(PFX, SNAME, FMOD, V, SIZE) \
|
||||
\
|
||||
/* Stack Structure */ \
|
||||
typedef struct SNAME##_s \
|
||||
{ \
|
||||
/* Internal Storage */ \
|
||||
V buffer[SIZE]; \
|
||||
\
|
||||
/* Current amount of elements */ \
|
||||
size_t count; \
|
||||
\
|
||||
/* Function that returns an iterator to the start of the stack */ \
|
||||
struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
|
||||
\
|
||||
/* Function that returns an iterator to the end of the stack */ \
|
||||
struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
|
||||
\
|
||||
} SNAME, *SNAME##_ptr; \
|
||||
\
|
||||
/* Stack Iterator */ \
|
||||
typedef struct SNAME##_iter_s \
|
||||
{ \
|
||||
/* Target stack */ \
|
||||
struct SNAME##_s *target; \
|
||||
\
|
||||
/* Cursor's position (index) */ \
|
||||
size_t cursor; \
|
||||
\
|
||||
/* If the iterator has reached the start of the iteration */ \
|
||||
bool start; \
|
||||
\
|
||||
/* If the iterator has reached the end of the iteration */ \
|
||||
bool end; \
|
||||
\
|
||||
} SNAME##_iter, *SNAME##_iter_ptr; \
|
||||
\
|
||||
/* Collection Functions */ \
|
||||
/* Collection Allocation and Deallocation */ \
|
||||
FMOD SNAME PFX##_new(void); \
|
||||
FMOD void PFX##_clear(SNAME *_stack_); \
|
||||
/* Collection Input and Output */ \
|
||||
FMOD bool PFX##_push(SNAME *_stack_, V element); \
|
||||
FMOD bool PFX##_pop(SNAME *_stack_); \
|
||||
/* Conditional Input and Output */ \
|
||||
FMOD bool PFX##_push_if(SNAME *_stack_, V element, bool condition); \
|
||||
FMOD bool PFX##_pop_if(SNAME *_stack_, bool condition); \
|
||||
/* Element Access */ \
|
||||
FMOD V PFX##_top(SNAME *_stack_); \
|
||||
/* Collection State */ \
|
||||
FMOD bool PFX##_contains(SNAME *_stack_, V element, int (*comparator)(V, V)); \
|
||||
FMOD bool PFX##_empty(SNAME *_stack_); \
|
||||
FMOD bool PFX##_full(SNAME *_stack_); \
|
||||
FMOD size_t PFX##_count(SNAME *_stack_); \
|
||||
FMOD size_t PFX##_capacity(void); \
|
||||
\
|
||||
/* Iterator Functions */ \
|
||||
/* Iterator Initialization */ \
|
||||
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \
|
||||
/* Iterator State */ \
|
||||
FMOD bool PFX##_iter_start(SNAME##_iter *iter); \
|
||||
FMOD bool PFX##_iter_end(SNAME##_iter *iter); \
|
||||
/* Iterator Movement */ \
|
||||
FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \
|
||||
FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \
|
||||
FMOD bool PFX##_iter_next(SNAME##_iter *iter); \
|
||||
FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \
|
||||
/* Iterator Access */ \
|
||||
FMOD V PFX##_iter_value(SNAME##_iter *iter); \
|
||||
FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \
|
||||
FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \
|
||||
\
|
||||
/* Default Value */ \
|
||||
static inline V PFX##_impl_default_value(void) \
|
||||
{ \
|
||||
V _empty_value_; \
|
||||
\
|
||||
memset(&_empty_value_, 0, sizeof(V)); \
|
||||
\
|
||||
return _empty_value_; \
|
||||
} \
|
||||
\
|
||||
/* SOURCE ********************************************************************/
|
||||
#define SAC_STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, V, SIZE) \
|
||||
\
|
||||
/* Implementation Detail Functions */ \
|
||||
static SNAME##_iter PFX##_impl_it_start(SNAME *_stack_); \
|
||||
static SNAME##_iter PFX##_impl_it_end(SNAME *_stack_); \
|
||||
\
|
||||
FMOD SNAME PFX##_new(void) \
|
||||
{ \
|
||||
SNAME result; \
|
||||
\
|
||||
memset(&result, 0, sizeof(SNAME)); \
|
||||
\
|
||||
result.it_start = PFX##_impl_it_start; \
|
||||
result.it_end = PFX##_impl_it_end; \
|
||||
\
|
||||
return result; \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_clear(SNAME *_stack_) \
|
||||
{ \
|
||||
memset(_stack_->buffer, 0, sizeof(_stack_->buffer)); \
|
||||
\
|
||||
_stack_->count = 0; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_push(SNAME *_stack_, V element) \
|
||||
{ \
|
||||
if (PFX##_full(_stack_)) \
|
||||
return false; \
|
||||
\
|
||||
_stack_->buffer[_stack_->count++] = element; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_pop(SNAME *_stack_) \
|
||||
{ \
|
||||
if (PFX##_empty(_stack_)) \
|
||||
return false; \
|
||||
\
|
||||
_stack_->buffer[--_stack_->count] = PFX##_impl_default_value(); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_push_if(SNAME *_stack_, V element, bool condition) \
|
||||
{ \
|
||||
if (condition) \
|
||||
return PFX##_push(_stack_, element); \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_pop_if(SNAME *_stack_, bool condition) \
|
||||
{ \
|
||||
if (condition) \
|
||||
return PFX##_pop(_stack_); \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
FMOD V PFX##_top(SNAME *_stack_) \
|
||||
{ \
|
||||
if (PFX##_empty(_stack_)) \
|
||||
return PFX##_impl_default_value(); \
|
||||
\
|
||||
return _stack_->buffer[_stack_->count - 1]; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_contains(SNAME *_stack_, V element, int (*comparator)(V, V)) \
|
||||
{ \
|
||||
for (size_t i = 0; i < _stack_->count; i++) \
|
||||
{ \
|
||||
if (comparator(_stack_->buffer[i], element) == 0) \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_empty(SNAME *_stack_) \
|
||||
{ \
|
||||
return _stack_->count == 0; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_full(SNAME *_stack_) \
|
||||
{ \
|
||||
return _stack_->count >= SIZE; \
|
||||
} \
|
||||
\
|
||||
FMOD size_t PFX##_count(SNAME *_stack_) \
|
||||
{ \
|
||||
return _stack_->count; \
|
||||
} \
|
||||
\
|
||||
FMOD size_t PFX##_capacity(void) \
|
||||
{ \
|
||||
return SIZE; \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \
|
||||
{ \
|
||||
iter->target = target; \
|
||||
iter->cursor = iter->target->count - 1; \
|
||||
iter->start = true; \
|
||||
iter->end = PFX##_empty(target); \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_iter_start(SNAME##_iter *iter) \
|
||||
{ \
|
||||
return PFX##_empty(iter->target) || iter->start; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_iter_end(SNAME##_iter *iter) \
|
||||
{ \
|
||||
return PFX##_empty(iter->target) || iter->end; \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \
|
||||
{ \
|
||||
iter->cursor = iter->target->count - 1; \
|
||||
iter->start = true; \
|
||||
iter->end = PFX##_empty(iter->target); \
|
||||
} \
|
||||
\
|
||||
FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \
|
||||
{ \
|
||||
iter->cursor = 0; \
|
||||
iter->start = PFX##_empty(iter->target); \
|
||||
iter->end = true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_iter_next(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter->end) \
|
||||
return false; \
|
||||
\
|
||||
iter->start = PFX##_empty(iter->target); \
|
||||
\
|
||||
if (iter->cursor == 0) \
|
||||
iter->end = true; \
|
||||
else \
|
||||
iter->cursor--; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (iter->start) \
|
||||
return false; \
|
||||
\
|
||||
iter->end = PFX##_empty(iter->target); \
|
||||
\
|
||||
if (iter->cursor == iter->target->count - 1) \
|
||||
iter->start = true; \
|
||||
else \
|
||||
iter->cursor++; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (PFX##_empty(iter->target)) \
|
||||
return PFX##_impl_default_value(); \
|
||||
\
|
||||
return iter->target->buffer[iter->cursor]; \
|
||||
} \
|
||||
\
|
||||
FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \
|
||||
{ \
|
||||
if (PFX##_empty(iter->target)) \
|
||||
return NULL; \
|
||||
\
|
||||
return &(iter->target->buffer[iter->cursor]); \
|
||||
} \
|
||||
\
|
||||
FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \
|
||||
{ \
|
||||
return iter->target->count - 1 - iter->cursor; \
|
||||
} \
|
||||
\
|
||||
static SNAME##_iter PFX##_impl_it_start(SNAME *_stack_) \
|
||||
{ \
|
||||
SNAME##_iter iter; \
|
||||
\
|
||||
PFX##_iter_init(&iter, _stack_); \
|
||||
PFX##_iter_to_start(&iter); \
|
||||
\
|
||||
return iter; \
|
||||
} \
|
||||
\
|
||||
static SNAME##_iter PFX##_impl_it_end(SNAME *_stack_) \
|
||||
{ \
|
||||
SNAME##_iter iter; \
|
||||
\
|
||||
PFX##_iter_init(&iter, _stack_); \
|
||||
PFX##_iter_to_end(&iter); \
|
||||
\
|
||||
return iter; \
|
||||
}
|
||||
|
||||
#endif /* CMC_SAC_STACK_H */
|
||||
+2123
-2342
File diff suppressed because it is too large.
Load diff
+12
-10
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* foreach.h
|
||||
* utl/foreach.h
|
||||
*
|
||||
* Creation Date: 25/02/2019
|
||||
*
|
||||
@@ -17,15 +17,17 @@
|
||||
* TARGET - Target variable
|
||||
*/
|
||||
|
||||
#ifndef CMC_FOREACH_H
|
||||
#define CMC_FOREACH_H
|
||||
#ifndef CMC_UTL_FOREACH_H
|
||||
#define CMC_UTL_FOREACH_H
|
||||
|
||||
#define CMC_FOREACH(PFX, SNAME, ITERNAME, TARGET) \
|
||||
for (struct SNAME##_iter ITERNAME = (TARGET)->it_start(TARGET); \
|
||||
!PFX##_iter_end(&ITERNAME); PFX##_iter_next(&ITERNAME))
|
||||
#include "../cor/core.h"
|
||||
|
||||
#define CMC_FOREACH_REV(PFX, SNAME, ITERNAME, TARGET) \
|
||||
for (struct SNAME##_iter ITERNAME = (TARGET)->it_end(TARGET); \
|
||||
!PFX##_iter_start(&ITERNAME); PFX##_iter_prev(&ITERNAME))
|
||||
#define CMC_FOREACH(PFX, SNAME, ITERNAME, TARGET) \
|
||||
for (struct CMC_DEF_ITER(SNAME) ITERNAME = CMC_(PFX, _iter_start)(TARGET); !CMC_(PFX, _iter_at_end)(&ITERNAME); \
|
||||
CMC_(PFX, _iter_next)(&ITERNAME))
|
||||
|
||||
#endif /* CMC_FOREACH_H */
|
||||
#define CMC_FOREACH_REV(PFX, SNAME, ITERNAME, TARGET) \
|
||||
for (struct CMC_DEF_ITER(SNAME) ITERNAME = CMC_(PFX, _iter_end)(TARGET); !CMC_(PFX, _iter_at_start)(&ITERNAME); \
|
||||
CMC_(PFX, _iter_prev)(&ITERNAME))
|
||||
|
||||
#endif /* CMC_UTL_FOREACH_H */
|
||||
+8
-6
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* futils.h
|
||||
* utl/futils.h
|
||||
*
|
||||
* Creation Date: 15/04/2020
|
||||
*
|
||||
@@ -13,8 +13,8 @@
|
||||
* another one every time.
|
||||
*/
|
||||
|
||||
#ifndef CMC_FUTILS_H
|
||||
#define CMC_FUTILS_H
|
||||
#ifndef CMC_UTL_FUTILS_H
|
||||
#define CMC_UTL_FUTILS_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
@@ -323,7 +323,8 @@ static inline size_t cmc_float_hash(float e)
|
||||
if (e == 0.0)
|
||||
e = 0.0; // if e == -0.0, now it is 0.0
|
||||
|
||||
union {
|
||||
union
|
||||
{
|
||||
float a;
|
||||
size_t b;
|
||||
} x;
|
||||
@@ -342,7 +343,8 @@ static inline size_t cmc_double_hash(double e)
|
||||
if (e == 0.0)
|
||||
e = 0.0; // if e == -0.0, now it is 0.0
|
||||
|
||||
union {
|
||||
union
|
||||
{
|
||||
double a;
|
||||
size_t b;
|
||||
} x;
|
||||
@@ -461,4 +463,4 @@ static inline size_t cmc_u64_hash_mix(uint64_t element)
|
||||
|
||||
/* Can simply use cmp for basic data types */
|
||||
|
||||
#endif /* CMC_FUTILS_H */
|
||||
#endif /* CMC_UTL_FUTILS_H */
|
||||
+20
-28
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* log.h
|
||||
* utl/log.h
|
||||
*
|
||||
* Creation Date: 21/06/2019
|
||||
*
|
||||
@@ -56,20 +56,20 @@
|
||||
* - If X is less than the level of FATAL, all logs are enabled
|
||||
*/
|
||||
|
||||
#ifndef CMC_LOG_H
|
||||
#define CMC_LOG_H
|
||||
#ifndef CMC_UTL_LOG_H
|
||||
#define CMC_UTL_LOG_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
static const char *cmc_log_names[] = { "TRACE", "DEBUG", "INFO",
|
||||
"WARN", "ERROR", "FATAL" };
|
||||
#include "../cor/core.h"
|
||||
|
||||
static const char *cmc_log_names[] = { "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL" };
|
||||
|
||||
#ifdef CMC_LOG_COLOR
|
||||
static const char *cmc_log_color[] = { "\x1b[94m", "\x1b[36m", "\x1b[32m",
|
||||
"\x1b[33m", "\x1b[31m", "\x1b[35m" };
|
||||
static const char *cmc_log_color[] = { "\x1b[94m", "\x1b[36m", "\x1b[32m", "\x1b[33m", "\x1b[31m", "\x1b[35m" };
|
||||
#endif
|
||||
|
||||
enum cmc_log_type
|
||||
@@ -93,21 +93,15 @@ static struct
|
||||
|
||||
} cmc_log_config = { 0, 0, true, true, true, NULL };
|
||||
|
||||
#define cmc_log_trace(fmt, ...) \
|
||||
cmc_log(CMC_LOG_TRACE, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__)
|
||||
#define cmc_log_debug(fmt, ...) \
|
||||
cmc_log(CMC_LOG_DEBUG, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__)
|
||||
#define cmc_log_info(fmt, ...) \
|
||||
cmc_log(CMC_LOG_INFO, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__)
|
||||
#define cmc_log_warn(fmt, ...) \
|
||||
cmc_log(CMC_LOG_WARN, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__)
|
||||
#define cmc_log_error(fmt, ...) \
|
||||
cmc_log(CMC_LOG_ERROR, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__)
|
||||
#define cmc_log_fatal(fmt, ...) \
|
||||
cmc_log(CMC_LOG_FATAL, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__)
|
||||
#define cmc_log_trace(fmt, ...) cmc_log(CMC_LOG_TRACE, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__)
|
||||
#define cmc_log_debug(fmt, ...) cmc_log(CMC_LOG_DEBUG, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__)
|
||||
#define cmc_log_info(fmt, ...) cmc_log(CMC_LOG_INFO, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__)
|
||||
#define cmc_log_warn(fmt, ...) cmc_log(CMC_LOG_WARN, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__)
|
||||
#define cmc_log_error(fmt, ...) cmc_log(CMC_LOG_ERROR, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__)
|
||||
#define cmc_log_fatal(fmt, ...) cmc_log(CMC_LOG_FATAL, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__)
|
||||
|
||||
static void cmc_log(enum cmc_log_type log, const char *filename,
|
||||
const char *funcname, unsigned line, const char *fmt, ...)
|
||||
CMC_UNUSED static void cmc_log(enum cmc_log_type log, const char *filename, const char *funcname, unsigned line,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
if (!cmc_log_config.enabled)
|
||||
return;
|
||||
@@ -130,11 +124,10 @@ static void cmc_log(enum cmc_log_type log, const char *filename,
|
||||
time[strftime(time, sizeof(time), "%Y-%m-%d %H:%M:%S", lt)] = '\0';
|
||||
|
||||
#ifdef CMC_LOG_COLOR
|
||||
fprintf(stderr, "%s %s%5s\x1b[0m at\x1b[90m %s:%s:%u\x1b[0m | ", time,
|
||||
cmc_log_color[i], cmc_log_names[i], filename, funcname, line);
|
||||
#else
|
||||
fprintf(stderr, "%s %5s at %s:%s:%u | ", time, cmc_log_names[i],
|
||||
fprintf(stderr, "%s %s%5s\x1b[0m at\x1b[90m %s:%s:%u\x1b[0m | ", time, cmc_log_color[i], cmc_log_names[i],
|
||||
filename, funcname, line);
|
||||
#else
|
||||
fprintf(stderr, "%s %5s at %s:%s:%u | ", time, cmc_log_names[i], filename, funcname, line);
|
||||
#endif
|
||||
|
||||
va_list args;
|
||||
@@ -165,8 +158,7 @@ skip:
|
||||
char time[32];
|
||||
time[strftime(time, sizeof(time), "%Y-%m-%d %H:%M:%S", lt)] = '\0';
|
||||
|
||||
fprintf(cmc_log_config.file, "%s %5s at %s:%s:%u | ", time,
|
||||
cmc_log_names[i], filename, funcname, line);
|
||||
fprintf(cmc_log_config.file, "%s %5s at %s:%s:%u | ", time, cmc_log_names[i], filename, funcname, line);
|
||||
|
||||
va_list file_args;
|
||||
va_start(file_args, fmt);
|
||||
@@ -178,4 +170,4 @@ skip:
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CMC_LOG_H */
|
||||
#endif /* CMC_UTL_LOG_H */
|
||||
+26
-26
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* mutex.h
|
||||
* utl/mutex.h
|
||||
*
|
||||
* Creation Date: 14/05/2020
|
||||
*
|
||||
@@ -22,8 +22,8 @@
|
||||
* - cmc_mtx_trylock
|
||||
*/
|
||||
|
||||
#ifndef CMC_MUTEX_H
|
||||
#define CMC_MUTEX_H
|
||||
#ifndef CMC_UTL_MUTEX_H
|
||||
#define CMC_UTL_MUTEX_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
@@ -72,9 +72,9 @@ static inline bool cmc_mtx_init(struct cmc_mutex *mtx)
|
||||
mtx->mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
|
||||
if (mtx->mutex == NULL)
|
||||
mtx->flag = cmc_flags.MUTEX;
|
||||
mtx->flag = CMC_FLAG_MUTEX;
|
||||
else
|
||||
mtx->flag = cmc_flags.OK;
|
||||
mtx->flag = CMC_FLAG_OK;
|
||||
|
||||
return mtx->mutex != NULL;
|
||||
|
||||
@@ -82,9 +82,9 @@ static inline bool cmc_mtx_init(struct cmc_mutex *mtx)
|
||||
int err = pthread_mutex_init(&(mtx->mutex), NULL);
|
||||
|
||||
if (err != 0)
|
||||
mtx->flag = cmc_flags.MUTEX;
|
||||
mtx->flag = CMC_FLAG_MUTEX;
|
||||
else
|
||||
mtx->flag = cmc_flags.OK;
|
||||
mtx->flag = CMC_FLAG_OK;
|
||||
|
||||
return err == 0;
|
||||
#endif
|
||||
@@ -102,21 +102,21 @@ static inline bool cmc_mtx_destroy(struct cmc_mutex *mtx)
|
||||
#if defined(CMC_MUTEX_WINDOWS)
|
||||
if (!CloseHandle(mtx->mutex))
|
||||
{
|
||||
mtx->flag = cmc_flags.MUTEX;
|
||||
mtx->flag = CMC_FLAG_MUTEX;
|
||||
return false;
|
||||
}
|
||||
|
||||
mtx->flag = cmc_flags.OK;
|
||||
mtx->flag = CMC_FLAG_OK;
|
||||
return true;
|
||||
|
||||
#elif defined(CMC_MUTEX_UNIX)
|
||||
if (pthread_mutex_destroy(&(mtx->mutex)) != 0)
|
||||
{
|
||||
mtx->flag = cmc_flags.MUTEX;
|
||||
mtx->flag = CMC_FLAG_MUTEX;
|
||||
return false;
|
||||
}
|
||||
|
||||
mtx->flag = cmc_flags.OK;
|
||||
mtx->flag = CMC_FLAG_OK;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
@@ -135,21 +135,21 @@ static inline bool cmc_mtx_lock(struct cmc_mutex *mtx)
|
||||
|
||||
if (result == WAIT_FAILED || result == WAIT_ABANDONED)
|
||||
{
|
||||
mtx->flag = cmc_flags.MUTEX;
|
||||
mtx->flag = CMC_FLAG_MUTEX;
|
||||
return false;
|
||||
}
|
||||
|
||||
mtx->flag = cmc_flags.OK;
|
||||
mtx->flag = CMC_FLAG_OK;
|
||||
return true;
|
||||
|
||||
#elif defined(CMC_MUTEX_UNIX)
|
||||
if (pthread_mutex_lock(&mtx->mutex) != 0)
|
||||
{
|
||||
mtx->flag = cmc_flags.MUTEX;
|
||||
mtx->flag = CMC_FLAG_MUTEX;
|
||||
return false;
|
||||
}
|
||||
|
||||
mtx->flag = cmc_flags.OK;
|
||||
mtx->flag = CMC_FLAG_OK;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
@@ -165,19 +165,19 @@ static inline bool cmc_mtx_unlock(struct cmc_mutex *mtx)
|
||||
{
|
||||
#if defined(CMC_MUTEX_WINDOWS)
|
||||
if (!ReleaseMutex(mtx->mutex))
|
||||
mtx->flag = cmc_flags.MUTEX;
|
||||
mtx->flag = CMC_FLAG_MUTEX;
|
||||
else
|
||||
mtx->flag = cmc_flags.OK;
|
||||
mtx->flag = CMC_FLAG_OK;
|
||||
|
||||
return mtx->flag == cmc_flags.OK;
|
||||
return mtx->flag == CMC_FLAG_OK;
|
||||
|
||||
#elif defined(CMC_MUTEX_UNIX)
|
||||
if (pthread_mutex_unlock(&mtx->mutex) != 0)
|
||||
mtx->flag = cmc_flags.MUTEX;
|
||||
mtx->flag = CMC_FLAG_MUTEX;
|
||||
else
|
||||
mtx->flag = cmc_flags.OK;
|
||||
mtx->flag = CMC_FLAG_OK;
|
||||
|
||||
return mtx->flag == cmc_flags.OK;
|
||||
return mtx->flag == CMC_FLAG_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -195,23 +195,23 @@ static inline bool cmc_mtx_trylock(struct cmc_mutex *mtx)
|
||||
|
||||
if (result == WAIT_FAILED || result == WAIT_ABANDONED)
|
||||
{
|
||||
mtx->flag = cmc_flags.MUTEX;
|
||||
mtx->flag = CMC_FLAG_MUTEX;
|
||||
return false;
|
||||
}
|
||||
|
||||
mtx->flag = cmc_flags.OK;
|
||||
mtx->flag = CMC_FLAG_OK;
|
||||
return result != WAIT_TIMEOUT;
|
||||
|
||||
#elif defined(CMC_MUTEX_UNIX)
|
||||
int err = pthread_mutex_trylock(&mtx->mutex);
|
||||
|
||||
if (err == EINVAL || err == EFAULT)
|
||||
mtx->flag = cmc_flags.MUTEX;
|
||||
mtx->flag = CMC_FLAG_MUTEX;
|
||||
else
|
||||
mtx->flag = cmc_flags.OK;
|
||||
mtx->flag = CMC_FLAG_OK;
|
||||
|
||||
return err == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* CMC_MUTEX_H */
|
||||
#endif /* CMC_UTL_MUTEX_H */
|
||||
+119
-140
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* test.h
|
||||
* utl/test.h
|
||||
*
|
||||
* Creation Date: 26/06/2019
|
||||
*
|
||||
@@ -34,14 +34,15 @@
|
||||
* Define this macro to allow colored output.
|
||||
*/
|
||||
|
||||
#ifndef CMC_TEST_H
|
||||
#define CMC_TEST_H
|
||||
#ifndef CMC_UTL_TEST_H
|
||||
#define CMC_UTL_TEST_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../cor/core.h"
|
||||
#include "assert.h"
|
||||
#include "timer.h"
|
||||
|
||||
@@ -56,27 +57,27 @@ struct cmc_test_info
|
||||
bool verbose;
|
||||
};
|
||||
|
||||
#ifdef CMC_TEST_COLOR
|
||||
static inline const char *cmc_test_color(int i)
|
||||
{
|
||||
#ifdef CMC_TEST_COLOR
|
||||
// 0 - Default, all off
|
||||
// 1 - Failed (red)
|
||||
// 2 - Passed (green)
|
||||
// 3 - Box (gray)
|
||||
// 4 - Name (cyan)
|
||||
// 5 - Total (yellow)
|
||||
static const char *cmc_test_colors[] = {
|
||||
"\x1b[0m", "\x1b[31m", "\x1b[32m", "\x1b[90m", "\x1b[36m", "\x1b[33m"
|
||||
};
|
||||
static const char *cmc_test_colors[] = { "\x1b[0m", "\x1b[31m", "\x1b[32m", "\x1b[90m", "\x1b[36m", "\x1b[33m" };
|
||||
return cmc_test_colors[i];
|
||||
#else
|
||||
static inline const char *cmc_test_color(int i)
|
||||
{
|
||||
(void)i;
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Logging function */
|
||||
static void cmc_test_log(const char *unit_name, const char *current_test,
|
||||
bool aborted, bool passed)
|
||||
CMC_UNUSED static void cmc_test_log(const char *unit_name, const char *current_test, bool aborted, bool passed)
|
||||
{
|
||||
if (aborted)
|
||||
{
|
||||
@@ -105,139 +106,117 @@ static void cmc_test_log(const char *unit_name, const char *current_test,
|
||||
}
|
||||
}
|
||||
|
||||
#define CMC_CREATE_UNIT(UNAME, VERBOSE, BODY) \
|
||||
uintmax_t UNAME(void) \
|
||||
{ \
|
||||
const char *unit_name = #UNAME; \
|
||||
const char *current_test = NULL; \
|
||||
\
|
||||
struct cmc_test_info tinfo = { 0 }; \
|
||||
struct cmc_timer timer = { 0 }; \
|
||||
\
|
||||
tinfo.verbose = VERBOSE; \
|
||||
tinfo.assert_total = cmc_assert_total; \
|
||||
tinfo.assert_failed = cmc_assert_failed; \
|
||||
\
|
||||
printf("%s", cmc_test_color(3)); \
|
||||
printf( \
|
||||
" +---------------------------------------------------------------+\n"); \
|
||||
printf(" | "); \
|
||||
printf("%s", cmc_test_color(0)); \
|
||||
printf("Unit "); \
|
||||
printf("%s", cmc_test_color(4)); \
|
||||
printf("%-56s", unit_name); \
|
||||
printf("%s", cmc_test_color(3)); \
|
||||
printf( \
|
||||
" |\n +---------------------------------------------------------------+"); \
|
||||
printf("%s\n", cmc_test_color(0)); \
|
||||
\
|
||||
/* Tests */ \
|
||||
cmc_timer_start(timer); \
|
||||
\
|
||||
BODY; \
|
||||
\
|
||||
cmc_timer_stop(timer); \
|
||||
\
|
||||
unittest_abort: \
|
||||
if (tinfo.aborted) \
|
||||
{ \
|
||||
cmc_test_log(unit_name, current_test, true, false); \
|
||||
} \
|
||||
\
|
||||
tinfo.assert_total = cmc_assert_total - tinfo.assert_total; \
|
||||
tinfo.assert_failed = cmc_assert_failed - tinfo.assert_failed; \
|
||||
\
|
||||
printf("%s", cmc_test_color(3)); \
|
||||
printf( \
|
||||
" +---------------------------------------------------------------+\n | "); \
|
||||
printf("%s", cmc_test_color(0)); \
|
||||
printf("Summary : "); \
|
||||
printf("%s", cmc_test_color(4)); \
|
||||
printf("%-52s", unit_name); \
|
||||
printf("%s|\n", cmc_test_color(3)); \
|
||||
printf( \
|
||||
" +---------++----------------+-----------------+-----------------+\n | "); \
|
||||
printf("%s", cmc_test_color(0)); \
|
||||
printf("Tests "); \
|
||||
printf("%s", cmc_test_color(3)); \
|
||||
printf("||"); \
|
||||
printf("%s", cmc_test_color(5)); \
|
||||
printf(" Total %8" PRIuMAX "", tinfo.total); \
|
||||
printf("%s", cmc_test_color(3)); \
|
||||
printf(" | "); \
|
||||
printf("%s", cmc_test_color(2)); \
|
||||
printf("Passed %8" PRIuMAX "", tinfo.passed); \
|
||||
printf("%s", cmc_test_color(3)); \
|
||||
printf(" | "); \
|
||||
printf("%s", cmc_test_color(1)); \
|
||||
printf("Failed %8" PRIuMAX "", tinfo.failed); \
|
||||
printf("%s", cmc_test_color(3)); \
|
||||
printf(" |\n | "); \
|
||||
printf("%s", cmc_test_color(0)); \
|
||||
printf("Asserts "); \
|
||||
printf("%s", cmc_test_color(3)); \
|
||||
printf("||"); \
|
||||
printf("%s", cmc_test_color(5)); \
|
||||
printf(" Total %8" PRIuMAX "", tinfo.assert_total); \
|
||||
printf("%s", cmc_test_color(3)); \
|
||||
printf(" | "); \
|
||||
printf("%s", cmc_test_color(2)); \
|
||||
printf("Passed %8" PRIuMAX "", \
|
||||
tinfo.assert_total - tinfo.assert_failed); \
|
||||
printf("%s", cmc_test_color(3)); \
|
||||
printf(" | "); \
|
||||
printf("%s", cmc_test_color(1)); \
|
||||
printf("Failed %8" PRIuMAX "", tinfo.assert_failed); \
|
||||
printf("%s", cmc_test_color(3)); \
|
||||
printf(" |\n"); \
|
||||
printf( \
|
||||
" +---------++----------------+-----------------+-----------------+\n | "); \
|
||||
printf("%s", cmc_test_color(0)); \
|
||||
printf("Total Runtime : %32.0f milliseconds", timer.result); \
|
||||
printf(" %s|\n", cmc_test_color(3)); \
|
||||
printf( \
|
||||
" +---------------------------------------------------------------+\n"); \
|
||||
printf("%s", cmc_test_color(0)); \
|
||||
printf("\n"); \
|
||||
\
|
||||
return tinfo.failed; \
|
||||
#define CMC_CREATE_UNIT(UNAME, VERBOSE, BODY) \
|
||||
uintmax_t UNAME(void) \
|
||||
{ \
|
||||
const char *unit_name = #UNAME; \
|
||||
const char *current_test = NULL; \
|
||||
\
|
||||
struct cmc_test_info tinfo = { 0 }; \
|
||||
struct cmc_timer timer = { 0 }; \
|
||||
\
|
||||
tinfo.verbose = VERBOSE; \
|
||||
tinfo.assert_total = cmc_assert_total; \
|
||||
tinfo.assert_failed = cmc_assert_failed; \
|
||||
\
|
||||
printf("%s", cmc_test_color(3)); \
|
||||
printf(" +---------------------------------------------------------------+\n"); \
|
||||
printf(" | "); \
|
||||
printf("%s", cmc_test_color(0)); \
|
||||
printf("Unit "); \
|
||||
printf("%s", cmc_test_color(4)); \
|
||||
printf("%-56s", unit_name); \
|
||||
printf("%s", cmc_test_color(3)); \
|
||||
printf(" |\n +---------------------------------------------------------------+"); \
|
||||
printf("%s\n", cmc_test_color(0)); \
|
||||
\
|
||||
/* Tests */ \
|
||||
cmc_timer_start(timer); \
|
||||
\
|
||||
BODY; \
|
||||
\
|
||||
cmc_timer_stop(timer); \
|
||||
\
|
||||
tinfo.assert_total = cmc_assert_total - tinfo.assert_total; \
|
||||
tinfo.assert_failed = cmc_assert_failed - tinfo.assert_failed; \
|
||||
\
|
||||
printf("%s", cmc_test_color(3)); \
|
||||
printf(" +---------------------------------------------------------------+\n | "); \
|
||||
printf("%s", cmc_test_color(0)); \
|
||||
printf("Summary : "); \
|
||||
printf("%s", cmc_test_color(4)); \
|
||||
printf("%-52s", unit_name); \
|
||||
printf("%s|\n", cmc_test_color(3)); \
|
||||
printf(" +---------++----------------+-----------------+-----------------+\n | "); \
|
||||
printf("%s", cmc_test_color(0)); \
|
||||
printf("Tests "); \
|
||||
printf("%s", cmc_test_color(3)); \
|
||||
printf("||"); \
|
||||
printf("%s", cmc_test_color(5)); \
|
||||
printf(" Total %8" PRIuMAX "", tinfo.total); \
|
||||
printf("%s", cmc_test_color(3)); \
|
||||
printf(" | "); \
|
||||
printf("%s", cmc_test_color(2)); \
|
||||
printf("Passed %8" PRIuMAX "", tinfo.passed); \
|
||||
printf("%s", cmc_test_color(3)); \
|
||||
printf(" | "); \
|
||||
printf("%s", cmc_test_color(1)); \
|
||||
printf("Failed %8" PRIuMAX "", tinfo.failed); \
|
||||
printf("%s", cmc_test_color(3)); \
|
||||
printf(" |\n | "); \
|
||||
printf("%s", cmc_test_color(0)); \
|
||||
printf("Asserts "); \
|
||||
printf("%s", cmc_test_color(3)); \
|
||||
printf("||"); \
|
||||
printf("%s", cmc_test_color(5)); \
|
||||
printf(" Total %8" PRIuMAX "", tinfo.assert_total); \
|
||||
printf("%s", cmc_test_color(3)); \
|
||||
printf(" | "); \
|
||||
printf("%s", cmc_test_color(2)); \
|
||||
printf("Passed %8" PRIuMAX "", tinfo.assert_total - tinfo.assert_failed); \
|
||||
printf("%s", cmc_test_color(3)); \
|
||||
printf(" | "); \
|
||||
printf("%s", cmc_test_color(1)); \
|
||||
printf("Failed %8" PRIuMAX "", tinfo.assert_failed); \
|
||||
printf("%s", cmc_test_color(3)); \
|
||||
printf(" |\n"); \
|
||||
printf(" +---------++----------------+-----------------+-----------------+\n | "); \
|
||||
printf("%s", cmc_test_color(0)); \
|
||||
printf("Total Runtime : %32.0f milliseconds", timer.result); \
|
||||
printf(" %s|\n", cmc_test_color(3)); \
|
||||
printf(" +---------------------------------------------------------------+\n"); \
|
||||
printf("%s", cmc_test_color(0)); \
|
||||
printf("\n"); \
|
||||
\
|
||||
return tinfo.failed; \
|
||||
}
|
||||
|
||||
#define CMC_CREATE_TEST(TNAME, BODY) \
|
||||
do \
|
||||
{ \
|
||||
current_test = #TNAME; \
|
||||
\
|
||||
tinfo.total += 1; \
|
||||
\
|
||||
/* Provided by assert.h */ \
|
||||
cmc_assert_state = true; \
|
||||
\
|
||||
BODY; \
|
||||
\
|
||||
if (tinfo.verbose) \
|
||||
{ \
|
||||
if (!cmc_assert_state) \
|
||||
{ \
|
||||
tinfo.failed += 1; \
|
||||
#define CMC_CREATE_TEST(TNAME, BODY) \
|
||||
do \
|
||||
{ \
|
||||
current_test = #TNAME; \
|
||||
\
|
||||
tinfo.total += 1; \
|
||||
\
|
||||
/* Provided by assert.h */ \
|
||||
cmc_assert_state = true; \
|
||||
\
|
||||
BODY; \
|
||||
\
|
||||
if (tinfo.verbose) \
|
||||
{ \
|
||||
if (!cmc_assert_state) \
|
||||
{ \
|
||||
tinfo.failed += 1; \
|
||||
cmc_test_log(unit_name, current_test, false, false); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
tinfo.passed += 1; \
|
||||
cmc_test_log(unit_name, current_test, false, true); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
tinfo.passed += 1; \
|
||||
cmc_test_log(unit_name, current_test, false, true); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#define CMC_TEST_ABORT() \
|
||||
do \
|
||||
{ \
|
||||
tinfo.aborted = true; \
|
||||
tinfo.total -= 1; \
|
||||
goto unittest_abort; \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#endif /* CMC_TEST_H */
|
||||
#endif /* CMC_UTL_TEST_H */
|
||||
+18
-19
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* thread.h
|
||||
* utl/thread.h
|
||||
*
|
||||
* Creation Date: 14/05/2020
|
||||
*
|
||||
@@ -20,8 +20,8 @@
|
||||
* - cmc_thrd_join
|
||||
*/
|
||||
|
||||
#ifndef CMC_THREAD_H
|
||||
#define CMC_THREAD_H
|
||||
#ifndef CMC_UTL_THREAD_H
|
||||
#define CMC_UTL_THREAD_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
@@ -88,8 +88,7 @@ static void *cmc_thread_wrapper(void *arg)
|
||||
* \param args The arguments passed to the proc function.
|
||||
* \return True or false if the thread creation was successfull.
|
||||
*/
|
||||
static inline bool cmc_thrd_create(struct cmc_thread *thr, cmc_thread_proc proc,
|
||||
void *args)
|
||||
static inline bool cmc_thrd_create(struct cmc_thread *thr, cmc_thread_proc proc, void *args)
|
||||
{
|
||||
#if defined(CMC_THREAD_WINDOWS)
|
||||
thr->args = args;
|
||||
@@ -97,21 +96,21 @@ static inline bool cmc_thrd_create(struct cmc_thread *thr, cmc_thread_proc proc,
|
||||
thr->thread = CreateThread(NULL, 0, cmc_thread_wrapper, thr, 0, NULL);
|
||||
|
||||
if (!thr->thread)
|
||||
thr->flag = cmc_flags.THREAD;
|
||||
thr->flag = CMC_FLAG_THREAD;
|
||||
else
|
||||
thr->flag = cmc_flags.OK;
|
||||
thr->flag = CMC_FLAG_OK;
|
||||
|
||||
return thr->flag == cmc_flags.OK;
|
||||
return thr->flag == CMC_FLAG_OK;
|
||||
|
||||
#elif defined(CMC_THREAD_UNIX)
|
||||
thr->args = args;
|
||||
thr->process = proc;
|
||||
if (pthread_create(&(thr->thread), NULL, cmc_thread_wrapper, thr) != 0)
|
||||
thr->flag = cmc_flags.THREAD;
|
||||
thr->flag = CMC_FLAG_THREAD;
|
||||
else
|
||||
thr->flag = cmc_flags.OK;
|
||||
thr->flag = CMC_FLAG_OK;
|
||||
|
||||
return thr->flag == cmc_flags.OK;
|
||||
return thr->flag == CMC_FLAG_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -127,7 +126,7 @@ static inline bool cmc_thrd_join(struct cmc_thread *thr, int *result)
|
||||
#if defined(CMC_THREAD_WINDOWS)
|
||||
if (WaitForSingleObject(thr->thread, INFINITE) == WAIT_FAILED)
|
||||
{
|
||||
thr->flag = cmc_flags.THREAD;
|
||||
thr->flag = CMC_FLAG_THREAD;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -137,22 +136,22 @@ static inline bool cmc_thrd_join(struct cmc_thread *thr, int *result)
|
||||
{
|
||||
if (GetExitCodeThread(thr->thread, &exit_code) == 0)
|
||||
{
|
||||
thr->flag = cmc_flags.THREAD;
|
||||
thr->flag = CMC_FLAG_THREAD;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
*result = (int)exit_code;
|
||||
}
|
||||
|
||||
thr->flag = cmc_flags.OK;
|
||||
thr->flag = CMC_FLAG_OK;
|
||||
|
||||
if (CloseHandle(thr->thread) == 0)
|
||||
{
|
||||
thr->flag = cmc_flags.THREAD;
|
||||
thr->flag = CMC_FLAG_THREAD;
|
||||
return false;
|
||||
}
|
||||
|
||||
thr->flag = cmc_flags.OK;
|
||||
thr->flag = CMC_FLAG_OK;
|
||||
return true;
|
||||
|
||||
#elif defined(CMC_THREAD_UNIX)
|
||||
@@ -160,7 +159,7 @@ static inline bool cmc_thrd_join(struct cmc_thread *thr, int *result)
|
||||
|
||||
if (pthread_join(thr->thread, &exit_value) != 0)
|
||||
{
|
||||
thr->flag = cmc_flags.THREAD;
|
||||
thr->flag = CMC_FLAG_THREAD;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -169,10 +168,10 @@ static inline bool cmc_thrd_join(struct cmc_thread *thr, int *result)
|
||||
*result = (int)(intptr_t)exit_value;
|
||||
}
|
||||
|
||||
thr->flag = cmc_flags.OK;
|
||||
thr->flag = CMC_FLAG_OK;
|
||||
return true;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* CMC_THREAD_H */
|
||||
#endif /* CMC_UTL_THREAD_H */
|
||||
+14
-15
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* timer.h
|
||||
* utl/timer.h
|
||||
*
|
||||
* Creation Date: 12/04/2019
|
||||
*
|
||||
@@ -12,8 +12,8 @@
|
||||
* Simple timer macros utility for timing code execution.
|
||||
*/
|
||||
|
||||
#ifndef CMC_TIMER_H
|
||||
#define CMC_TIMER_H
|
||||
#ifndef CMC_UTL_TIMER_H
|
||||
#define CMC_UTL_TIMER_H
|
||||
|
||||
#include <time.h>
|
||||
|
||||
@@ -24,20 +24,19 @@ struct cmc_timer
|
||||
double result; /* The result is given in milliseconds */
|
||||
};
|
||||
|
||||
#define cmc_timer_start(timer) \
|
||||
do \
|
||||
{ \
|
||||
#define cmc_timer_start(timer) \
|
||||
do \
|
||||
{ \
|
||||
struct cmc_timer *t__ = &(timer); \
|
||||
t__->start = clock(); \
|
||||
t__->start = clock(); \
|
||||
} while (0)
|
||||
|
||||
#define cmc_timer_stop(timer) \
|
||||
do \
|
||||
{ \
|
||||
struct cmc_timer *t__ = &(timer); \
|
||||
t__->stop = clock(); \
|
||||
t__->result = \
|
||||
(double)(t__->stop - t__->start) * 1000.0 / CLOCKS_PER_SEC; \
|
||||
#define cmc_timer_stop(timer) \
|
||||
do \
|
||||
{ \
|
||||
struct cmc_timer *t__ = &(timer); \
|
||||
t__->stop = clock(); \
|
||||
t__->result = (double)(t__->stop - t__->start) * 1000.0 / CLOCKS_PER_SEC; \
|
||||
} while (0)
|
||||
|
||||
#endif /* CMC_TIMER_H */
|
||||
#endif /* CMC_UTL_TIMER_H */
|
||||
@@ -1,22 +0,0 @@
|
||||
CC = gcc
|
||||
CFLAGS = -std=c11 -Wall -Wextra
|
||||
CFLAGS += -Wno-unused -Wno-missing-braces
|
||||
|
||||
main: FORCE
|
||||
$(CC) foreach.c -o foreach.exe $(CFLAGS)
|
||||
./foreach.exe
|
||||
$(CC) iterators.c -o iterators.exe $(CFLAGS)
|
||||
./iterators.exe
|
||||
$(CC) contains.c -o contains.exe $(CFLAGS)
|
||||
./contains.exe
|
||||
$(CC) types.c -o types.exe $(CFLAGS)
|
||||
./types.exe
|
||||
make -C ./sep
|
||||
|
||||
dev: main
|
||||
rm *.exe ./sep/*.o ./sep/*.exe
|
||||
|
||||
windev: main
|
||||
del *.exe .\\sep\\*.o .\\sep\\*.exe
|
||||
|
||||
FORCE:
|
||||
@@ -1,9 +0,0 @@
|
||||
# Tests
|
||||
|
||||
* `codecov` - A stalled version for codecov;
|
||||
* `main` - Unit tests for the main C Macro Collections library;
|
||||
* `sep/main.c`, `sep/sep.c` and `sep/sep.h` - Tests separate header and source compilation;
|
||||
* `contains.c` - Tests the `contains` function for all collections;
|
||||
* `foreach.c` - Tests the ForEach macros for all collections;
|
||||
* `iterators.c` - Tests all collection's iterators;
|
||||
* `types.c` - Tests if all containers accept all possible C data types (struct, union, enum, pointers, function pointers)
|
||||
@@ -1,260 +0,0 @@
|
||||
#include "../src/macro_collections.h"
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int intcmp(int a, int b)
|
||||
{
|
||||
return (a > b) - (a < b);
|
||||
}
|
||||
|
||||
size_t inthash(int t)
|
||||
{
|
||||
size_t a = t;
|
||||
a += ~(a << 15);
|
||||
a ^= (a >> 10);
|
||||
a += (a << 3);
|
||||
a ^= (a >> 6);
|
||||
a += ~(a << 11);
|
||||
a ^= (a >> 16);
|
||||
return a;
|
||||
}
|
||||
|
||||
CMC_COLLECTION_GENERATE(LIST, l, list, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(STACK, s, stack, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(QUEUE, q, queue, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(DEQUE, d, deque, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(LINKEDLIST, ll, linked, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(HEAP, h, heap, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(TREESET, ts, tset, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(TREEMAP, tm, tmap, int, int)
|
||||
CMC_COLLECTION_GENERATE(HASHSET, hs, hset, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(HASHMAP, hm, hmap, int, int)
|
||||
|
||||
CMC_COLLECTION_GENERATE(INTERVALHEAP, ih, iheap, , int)
|
||||
CMC_COLLECTION_GENERATE(MULTIMAP, mm, mmap, int, int)
|
||||
CMC_COLLECTION_GENERATE(MULTISET, ms, mset, , int)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
struct list *l = l_new(1000);
|
||||
struct stack *s = s_new(1000);
|
||||
struct queue *q = q_new(1000);
|
||||
struct deque *d = d_new(1000);
|
||||
struct linked *ll = ll_new();
|
||||
struct heap *h = h_new(1000, cmc_max_heap, intcmp);
|
||||
struct tset *ts = ts_new(intcmp);
|
||||
struct tmap *tm = tm_new(intcmp);
|
||||
struct hset *hs = hs_new(1000, 0.6, intcmp, inthash);
|
||||
struct hmap *hm = hm_new(1000, 0.6, intcmp, inthash);
|
||||
struct iheap *ih = ih_new(1000, intcmp);
|
||||
struct mmap *mm = mm_new(1000, 0.8, intcmp, inthash);
|
||||
struct mset *ms = ms_new(1000, 0.6, intcmp, inthash);
|
||||
|
||||
bool a[13] = { false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false },
|
||||
b[13] = { false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false },
|
||||
c[13] = { true, true, true, 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);
|
||||
|
||||
b[10] = ih_contains(ih, 1);
|
||||
b[11] = mm_contains(mm, 1);
|
||||
b[12] = ms_contains(ms, 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);
|
||||
|
||||
ih_insert(ih, i);
|
||||
mm_insert(mm, i, i);
|
||||
ms_insert(ms, 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);
|
||||
|
||||
c[10] = c[10] && ih_contains(ih, i);
|
||||
c[11] = c[11] && mm_contains(mm, i);
|
||||
c[12] = c[12] && ms_contains(ms, 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);
|
||||
|
||||
a[10] = a[10] || ih_contains(ih, i);
|
||||
a[11] = a[11] || mm_contains(mm, i);
|
||||
a[12] = a[12] || ms_contains(ms, 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);
|
||||
|
||||
a[10] = a[10] || ih_contains(ih, i);
|
||||
a[11] = a[11] || mm_contains(mm, i);
|
||||
a[12] = a[12] || ms_contains(ms, i);
|
||||
}
|
||||
|
||||
d_clear(d, NULL);
|
||||
hm_clear(hm, NULL);
|
||||
hs_clear(hs, NULL);
|
||||
h_clear(h, NULL);
|
||||
ll_clear(ll, NULL);
|
||||
l_clear(l, NULL);
|
||||
q_clear(q, NULL);
|
||||
s_clear(s, NULL);
|
||||
tm_clear(tm, NULL);
|
||||
ts_clear(ts, NULL);
|
||||
|
||||
ih_clear(ih, NULL);
|
||||
mm_clear(mm, NULL);
|
||||
ms_clear(ms, NULL);
|
||||
|
||||
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);
|
||||
|
||||
b[10] = b[10] || ih_contains(ih, 1);
|
||||
b[11] = b[11] || mm_contains(mm, 1);
|
||||
b[12] = b[12] || ms_contains(ms, 1);
|
||||
|
||||
printf("-------------------- CONTAINS --------------------\n");
|
||||
if (c[0] && !a[0] && !b[0])
|
||||
printf("%12s PASSED\n", "DEQUE");
|
||||
else
|
||||
printf("%12s FAILED\n", "DEQUE");
|
||||
if (c[1] && !a[1] && !b[1])
|
||||
printf("%12s PASSED\n", "HASHMAP");
|
||||
else
|
||||
printf("%12s FAILED\n", "HASHMAP");
|
||||
if (c[2] && !a[2] && !b[2])
|
||||
printf("%12s PASSED\n", "HASHSET");
|
||||
else
|
||||
printf("%12s FAILED\n", "HASHSET");
|
||||
if (c[3] && !a[3] && !b[3])
|
||||
printf("%12s PASSED\n", "HEAP");
|
||||
else
|
||||
printf("%12s FAILED\n", "HEAP");
|
||||
if (c[4] && !a[4] && !b[4])
|
||||
printf("%12s PASSED\n", "LINKEDLIST");
|
||||
else
|
||||
printf("%12s FAILED\n", "LINKEDLIST");
|
||||
if (c[5] && !a[5] && !b[5])
|
||||
printf("%12s PASSED\n", "LIST");
|
||||
else
|
||||
printf("%12s FAILED\n", "LIST");
|
||||
if (c[6] && !a[6] && !b[6])
|
||||
printf("%12s PASSED\n", "QUEUE");
|
||||
else
|
||||
printf("%12s FAILED\n", "QUEUE");
|
||||
if (c[7] && !a[7] && !b[7])
|
||||
printf("%12s PASSED\n", "STACK");
|
||||
else
|
||||
printf("%12s FAILED\n", "STACK");
|
||||
if (c[8] && !a[8] && !b[8])
|
||||
printf("%12s PASSED\n", "TREEMAP");
|
||||
else
|
||||
printf("%12s FAILED\n", "TREEMAP");
|
||||
if (c[9] && !a[9] && !b[9])
|
||||
printf("%12s PASSED\n", "TREESET");
|
||||
else
|
||||
printf("%12s FAILED\n", "TREESET");
|
||||
if (c[10] && !a[10] && !b[10])
|
||||
printf("%12s PASSED\n", "INTERVALHEAP");
|
||||
else
|
||||
printf("%12s FAILED\n", "INTERVALHEAP");
|
||||
if (c[11] && !a[11] && !b[11])
|
||||
printf("%12s PASSED\n", "MULTIMAP");
|
||||
else
|
||||
printf("%12s FAILED\n", "MULTIMAP");
|
||||
if (c[12] && !a[12] && !b[12])
|
||||
printf("%12s PASSED\n", "MULTISET");
|
||||
else
|
||||
printf("%12s FAILED\n", "MULTISET");
|
||||
|
||||
printf("\n\n");
|
||||
|
||||
l_free(l, NULL);
|
||||
ll_free(ll, NULL);
|
||||
s_free(s, NULL);
|
||||
q_free(q, NULL);
|
||||
d_free(d, NULL);
|
||||
h_free(h, NULL);
|
||||
ts_free(ts, NULL);
|
||||
tm_free(tm, NULL);
|
||||
hs_free(hs, NULL);
|
||||
hm_free(hm, NULL);
|
||||
|
||||
ih_free(ih, NULL);
|
||||
mm_free(mm, NULL);
|
||||
ms_free(ms, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
-286
@@ -1,286 +0,0 @@
|
||||
#include "../src/macro_collections.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.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;
|
||||
}
|
||||
|
||||
CMC_COLLECTION_GENERATE(LIST, l, list, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(STACK, s, stack, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(QUEUE, q, queue, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(DEQUE, d, deque, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(LINKEDLIST, ll, linked, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(HEAP, h, heap, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(TREESET, ts, tset, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(TREEMAP, tm, tmap, int, int)
|
||||
CMC_COLLECTION_GENERATE(HASHSET, hs, hset, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(HASHMAP, hm, hmap, int, int)
|
||||
|
||||
CMC_COLLECTION_GENERATE(INTERVALHEAP, ih, iheap, , int)
|
||||
CMC_COLLECTION_GENERATE(MULTIMAP, mm, mmap, int, int)
|
||||
CMC_COLLECTION_GENERATE(MULTISET, ms, mset, , int)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
struct list *l = l_new(1000);
|
||||
struct stack *s = s_new(1000);
|
||||
struct queue *q = q_new(1000);
|
||||
struct deque *d = d_new(1000);
|
||||
struct linked *ll = ll_new();
|
||||
struct heap *h = h_new(1000, cmc_max_heap, intcmp);
|
||||
struct tset *ts = ts_new(intcmp);
|
||||
struct tmap *tm = tm_new(intcmp);
|
||||
struct hset *hs = hs_new(1000, 0.6, intcmp, inthash);
|
||||
struct hmap *hm = hm_new(1000, 0.6, intcmp, inthash);
|
||||
struct iheap *ih = ih_new(1000, intcmp);
|
||||
struct mmap *mm = mm_new(1000, 0.8, intcmp, inthash);
|
||||
struct mset *ms = ms_new(1000, 0.6, intcmp, inthash);
|
||||
|
||||
bool p = true;
|
||||
|
||||
for (int i = 1; i < 10001; i++)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
assert(d_push_front(d, i));
|
||||
assert(l_push_front(l, i));
|
||||
assert(ll_push_front(ll, i));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(d_push_back(d, i));
|
||||
assert(l_push_back(l, i));
|
||||
assert(ll_push_back(ll, i));
|
||||
}
|
||||
|
||||
assert(s_push(s, i));
|
||||
assert(q_enqueue(q, i));
|
||||
assert(h_insert(h, i));
|
||||
assert(ts_insert(ts, i));
|
||||
assert(tm_insert(tm, i, i));
|
||||
assert(hs_insert(hs, i));
|
||||
assert(hm_insert(hm, i, i));
|
||||
|
||||
assert(ih_insert(ih, i));
|
||||
assert(mm_insert(mm, i, i));
|
||||
assert(ms_insert(ms, i));
|
||||
}
|
||||
|
||||
int sums[16] = { 0 };
|
||||
|
||||
CMC_FOR_EACH(d, deque, d, { sums[0] += d_iter_value(&iter); });
|
||||
|
||||
CMC_FOR_EACH(hm, hmap, hm, {
|
||||
sums[1] += hm_iter_key(&iter);
|
||||
sums[2] += hm_iter_value(&iter);
|
||||
});
|
||||
|
||||
CMC_FOR_EACH(hs, hset, hs, { sums[3] += hs_iter_value(&iter); });
|
||||
|
||||
CMC_FOR_EACH(h, heap, h, { sums[4] += h_iter_value(&iter); });
|
||||
|
||||
CMC_FOR_EACH(ll, linked, ll, { sums[5] += ll_iter_value(&iter); });
|
||||
|
||||
CMC_FOR_EACH(l, list, l, { sums[6] += l_iter_value(&iter); });
|
||||
|
||||
CMC_FOR_EACH(q, queue, q, { sums[7] += q_iter_value(&iter); });
|
||||
|
||||
CMC_FOR_EACH(s, stack, s, { sums[8] += s_iter_value(&iter); });
|
||||
|
||||
CMC_FOR_EACH(tm, tmap, tm, {
|
||||
sums[9] += tm_iter_key(&iter);
|
||||
sums[10] += tm_iter_value(&iter);
|
||||
});
|
||||
|
||||
CMC_FOR_EACH(ts, tset, ts, { sums[11] += ts_iter_value(&iter); });
|
||||
|
||||
CMC_FOR_EACH(ih, iheap, ih, { sums[12] += ih_iter_value(&iter); });
|
||||
|
||||
CMC_FOR_EACH(mm, mmap, mm, {
|
||||
sums[13] += mm_iter_key(&iter);
|
||||
sums[14] += mm_iter_value(&iter);
|
||||
});
|
||||
|
||||
CMC_FOR_EACH(ms, mset, ms, { sums[15] += ms_iter_value(&iter); });
|
||||
|
||||
printf("\n-------------------- CMC_FOR_EACH --------------------\n");
|
||||
if (sums[0] == 50005000)
|
||||
printf("%12s PASSED\n", "DEQUE");
|
||||
else
|
||||
printf("%12s FAILED\n", "DEQUE");
|
||||
if (sums[1] == 50005000 && sums[2] == 50005000)
|
||||
printf("%12s PASSED\n", "HASHMAP");
|
||||
else
|
||||
printf("%12s FAILED\n", "HASHMAP");
|
||||
if (sums[3] == 50005000)
|
||||
printf("%12s PASSED\n", "HASHSET");
|
||||
else
|
||||
printf("%12s FAILED\n", "HASHSET");
|
||||
if (sums[4] == 50005000)
|
||||
printf("%12s PASSED\n", "HEAP");
|
||||
else
|
||||
printf("%12s FAILED\n", "HEAP");
|
||||
if (sums[5] == 50005000)
|
||||
printf("%12s PASSED\n", "LINKEDLIST");
|
||||
else
|
||||
printf("%12s FAILED\n", "LINKEDLIST");
|
||||
if (sums[6] == 50005000)
|
||||
printf("%12s PASSED\n", "LIST");
|
||||
else
|
||||
printf("%12s FAILED\n", "LIST");
|
||||
if (sums[7] == 50005000)
|
||||
printf("%12s PASSED\n", "QUEUE");
|
||||
else
|
||||
printf("%12s FAILED\n", "QUEUE");
|
||||
if (sums[8] == 50005000)
|
||||
printf("%12s PASSED\n", "STACK");
|
||||
else
|
||||
printf("%12s FAILED\n", "STACK");
|
||||
if (sums[9] == 50005000 && sums[10] == 50005000)
|
||||
printf("%12s PASSED\n", "TREEMAP");
|
||||
else
|
||||
printf("%12s FAILED\n", "TREEMAP");
|
||||
if (sums[11] == 50005000)
|
||||
printf("%12s PASSED\n", "TREESET");
|
||||
else
|
||||
printf("%12s FAILED\n", "TREESET");
|
||||
if (sums[12] == 50005000)
|
||||
printf("%12s PASSED\n", "INTERVALHEAP");
|
||||
else
|
||||
printf("%12s FAILED\n", "INTERVALHEAP");
|
||||
if (sums[13] == 50005000 && sums[14] == 50005000)
|
||||
printf("%12s PASSED\n", "MULTIMAP");
|
||||
else
|
||||
printf("%12s FAILED\n", "MULTIMAP");
|
||||
if (sums[15] == 50005000)
|
||||
printf("%12s PASSED\n", "MULTISET");
|
||||
else
|
||||
printf("%12s FAILED\n", "MULTISET");
|
||||
|
||||
printf("\n\n");
|
||||
|
||||
memset(sums, 0, sizeof sums);
|
||||
|
||||
CMC_FOR_EACH_REV(d, deque, d, { sums[0] += d_iter_value(&iter); });
|
||||
|
||||
CMC_FOR_EACH_REV(hm, hmap, hm, {
|
||||
sums[1] += hm_iter_key(&iter);
|
||||
sums[2] += hm_iter_value(&iter);
|
||||
});
|
||||
|
||||
CMC_FOR_EACH_REV(hs, hset, hs, { sums[3] += hs_iter_value(&iter); });
|
||||
|
||||
CMC_FOR_EACH_REV(h, heap, h, { sums[4] += h_iter_value(&iter); });
|
||||
|
||||
CMC_FOR_EACH_REV(ll, linked, ll, { sums[5] += ll_iter_value(&iter); });
|
||||
|
||||
CMC_FOR_EACH_REV(l, list, l, { sums[6] += l_iter_value(&iter); });
|
||||
|
||||
CMC_FOR_EACH_REV(q, queue, q, { sums[7] += q_iter_value(&iter); });
|
||||
|
||||
CMC_FOR_EACH_REV(s, stack, s, { sums[8] += s_iter_value(&iter); });
|
||||
|
||||
CMC_FOR_EACH_REV(tm, tmap, tm, {
|
||||
sums[9] += tm_iter_key(&iter);
|
||||
sums[10] += tm_iter_value(&iter);
|
||||
});
|
||||
|
||||
CMC_FOR_EACH_REV(ts, tset, ts, { sums[11] += ts_iter_value(&iter); });
|
||||
|
||||
CMC_FOR_EACH_REV(ih, iheap, ih, { sums[12] += ih_iter_value(&iter); });
|
||||
|
||||
CMC_FOR_EACH_REV(mm, mmap, mm, {
|
||||
sums[13] += mm_iter_key(&iter);
|
||||
sums[14] += mm_iter_value(&iter);
|
||||
});
|
||||
|
||||
CMC_FOR_EACH_REV(ms, mset, ms, { sums[15] += ms_iter_value(&iter); });
|
||||
|
||||
printf("-------------------- CMC_FOR_EACH_REV --------------------\n");
|
||||
if (sums[0] == 50005000)
|
||||
printf("%12s PASSED\n", "DEQUE");
|
||||
else
|
||||
printf("%12s FAILED\n", "DEQUE");
|
||||
if (sums[1] == 50005000 && sums[2] == 50005000)
|
||||
printf("%12s PASSED\n", "HASHMAP");
|
||||
else
|
||||
printf("%12s FAILED\n", "HASHMAP");
|
||||
if (sums[3] == 50005000)
|
||||
printf("%12s PASSED\n", "HASHSET");
|
||||
else
|
||||
printf("%12s FAILED\n", "HASHSET");
|
||||
if (sums[4] == 50005000)
|
||||
printf("%12s PASSED\n", "HEAP");
|
||||
else
|
||||
printf("%12s FAILED\n", "HEAP");
|
||||
if (sums[5] == 50005000)
|
||||
printf("%12s PASSED\n", "LINKEDLIST");
|
||||
else
|
||||
printf("%12s FAILED\n", "LINKEDLIST");
|
||||
if (sums[6] == 50005000)
|
||||
printf("%12s PASSED\n", "LIST");
|
||||
else
|
||||
printf("%12s FAILED\n", "LIST");
|
||||
if (sums[7] == 50005000)
|
||||
printf("%12s PASSED\n", "QUEUE");
|
||||
else
|
||||
printf("%12s FAILED\n", "QUEUE");
|
||||
if (sums[8] == 50005000)
|
||||
printf("%12s PASSED\n", "STACK");
|
||||
else
|
||||
printf("%12s FAILED\n", "STACK");
|
||||
if (sums[9] == 50005000 && sums[10] == 50005000)
|
||||
printf("%12s PASSED\n", "TREEMAP");
|
||||
else
|
||||
printf("%12s FAILED\n", "TREEMAP");
|
||||
if (sums[11] == 50005000)
|
||||
printf("%12s PASSED\n", "TREESET");
|
||||
else
|
||||
printf("%12s FAILED\n", "TREESET");
|
||||
if (sums[12] == 50005000)
|
||||
printf("%12s PASSED\n", "INTERVALHEAP");
|
||||
else
|
||||
printf("%12s FAILED\n", "INTERVALHEAP");
|
||||
if (sums[13] == 50005000 && sums[14] == 50005000)
|
||||
printf("%12s PASSED\n", "MULTIMAP");
|
||||
else
|
||||
printf("%12s FAILED\n", "MULTIMAP");
|
||||
if (sums[15] == 50005000)
|
||||
printf("%12s PASSED\n", "MULTISET");
|
||||
else
|
||||
printf("%12s FAILED\n", "MULTISET");
|
||||
|
||||
printf("\n\n");
|
||||
|
||||
l_free(l, NULL);
|
||||
ll_free(ll, NULL);
|
||||
s_free(s, NULL);
|
||||
q_free(q, NULL);
|
||||
d_free(d, NULL);
|
||||
h_free(h, NULL);
|
||||
ts_free(ts, NULL);
|
||||
tm_free(tm, NULL);
|
||||
hs_free(hs, NULL);
|
||||
hm_free(hm, NULL);
|
||||
|
||||
ih_free(ih, NULL);
|
||||
mm_free(mm, NULL);
|
||||
ms_free(ms, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
|
||||
#ifndef CMC_CMC_BITSET_TEST_H
|
||||
#define CMC_CMC_BITSET_TEST_H
|
||||
|
||||
#include "macro_collections.h"
|
||||
|
||||
struct bitset
|
||||
{
|
||||
cmc_bitset_word *buffer;
|
||||
size_t capacity;
|
||||
size_t count;
|
||||
int flag;
|
||||
struct cmc_alloc_node *alloc;
|
||||
struct cmc_callbacks *callbacks;
|
||||
};
|
||||
struct bitset_iter
|
||||
{
|
||||
struct bitset *target;
|
||||
size_t cursor;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
};
|
||||
struct bitset *bs_new(size_t n_bits);
|
||||
struct bitset *bs_new_custom(size_t n_bits, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks);
|
||||
struct bitset bs_init(size_t n_bits);
|
||||
struct bitset bs_init_custom(size_t n_bits, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks);
|
||||
void bs_free(struct bitset *_bitset_);
|
||||
void bs_release(struct bitset _bitset_);
|
||||
void bs_customize(struct bitset *_bitset_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks);
|
||||
_Bool bs_set(struct bitset *_bitset_, size_t bit_index);
|
||||
_Bool bs_set_range(struct bitset *_bitset_, size_t from, size_t to);
|
||||
_Bool bs_clear(struct bitset *_bitset_, size_t bit_index);
|
||||
_Bool bs_clear_range(struct bitset *_bitset_, size_t from, size_t to);
|
||||
_Bool bs_flip(struct bitset *_bitset_, size_t bit_index);
|
||||
_Bool bs_flip_range(struct bitset *_bitset_, size_t from, size_t to);
|
||||
_Bool bs_put(struct bitset *_bitset_, size_t bit_index, _Bool state);
|
||||
_Bool bs_put_range(struct bitset *_bitset_, size_t from, size_t to, _Bool state);
|
||||
_Bool bs_set_all(struct bitset *_bitset_);
|
||||
_Bool bs_clear_all(struct bitset *_bitset_);
|
||||
_Bool bs_flip_all(struct bitset *_bitset_);
|
||||
_Bool bs_get(struct bitset *_bitset_, size_t bit_index);
|
||||
_Bool bs_resize(struct bitset *_bitset_, size_t n_bits);
|
||||
|
||||
#endif /* CMC_CMC_BITSET_TEST_H */
|
||||
@@ -0,0 +1,78 @@
|
||||
|
||||
#ifndef CMC_CMC_DEQUE_TEST_H
|
||||
#define CMC_CMC_DEQUE_TEST_H
|
||||
|
||||
#include "macro_collections.h"
|
||||
|
||||
struct deque
|
||||
{
|
||||
size_t *buffer;
|
||||
size_t capacity;
|
||||
size_t count;
|
||||
size_t front;
|
||||
size_t back;
|
||||
int flag;
|
||||
struct deque_fval *f_val;
|
||||
struct cmc_alloc_node *alloc;
|
||||
struct cmc_callbacks *callbacks;
|
||||
};
|
||||
struct deque_fval
|
||||
{
|
||||
int (*cmp)(size_t, size_t);
|
||||
size_t (*cpy)(size_t);
|
||||
_Bool (*str)(FILE *, size_t);
|
||||
void (*free)(size_t);
|
||||
size_t (*hash)(size_t);
|
||||
int (*pri)(size_t, size_t);
|
||||
};
|
||||
struct deque *d_new(size_t capacity, struct deque_fval *f_val);
|
||||
struct deque *d_new_custom(size_t capacity, struct deque_fval *f_val, struct cmc_alloc_node *alloc,
|
||||
struct cmc_callbacks *callbacks);
|
||||
void d_clear(struct deque *_deque_);
|
||||
void d_free(struct deque *_deque_);
|
||||
void d_customize(struct deque *_deque_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks);
|
||||
_Bool d_push_front(struct deque *_deque_, size_t value);
|
||||
_Bool d_push_back(struct deque *_deque_, size_t value);
|
||||
_Bool d_pop_front(struct deque *_deque_);
|
||||
_Bool d_pop_back(struct deque *_deque_);
|
||||
size_t d_front(struct deque *_deque_);
|
||||
size_t d_back(struct deque *_deque_);
|
||||
_Bool d_contains(struct deque *_deque_, size_t value);
|
||||
_Bool d_empty(struct deque *_deque_);
|
||||
_Bool d_full(struct deque *_deque_);
|
||||
size_t d_count(struct deque *_deque_);
|
||||
size_t d_capacity(struct deque *_deque_);
|
||||
int d_flag(struct deque *_deque_);
|
||||
_Bool d_resize(struct deque *_deque_, size_t capacity);
|
||||
struct deque *d_copy_of(struct deque *_deque_);
|
||||
_Bool d_equals(struct deque *_deque1_, struct deque *_deque2_);
|
||||
struct deque d_init(size_t capacity, struct deque_fval *f_val);
|
||||
struct deque d_init_custom(size_t capacity, struct deque_fval *f_val, struct cmc_alloc_node *alloc,
|
||||
struct cmc_callbacks *callbacks);
|
||||
void d_release(struct deque _deque_);
|
||||
struct deque_iter
|
||||
{
|
||||
struct deque *target;
|
||||
size_t cursor;
|
||||
size_t index;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
};
|
||||
struct deque_iter d_iter_start(struct deque *target);
|
||||
struct deque_iter d_iter_end(struct deque *target);
|
||||
_Bool d_iter_at_start(struct deque_iter *iter);
|
||||
_Bool d_iter_at_end(struct deque_iter *iter);
|
||||
_Bool d_iter_to_start(struct deque_iter *iter);
|
||||
_Bool d_iter_to_end(struct deque_iter *iter);
|
||||
_Bool d_iter_next(struct deque_iter *iter);
|
||||
_Bool d_iter_prev(struct deque_iter *iter);
|
||||
_Bool d_iter_advance(struct deque_iter *iter, size_t steps);
|
||||
_Bool d_iter_rewind(struct deque_iter *iter, size_t steps);
|
||||
_Bool d_iter_go_to(struct deque_iter *iter, size_t index);
|
||||
size_t d_iter_value(struct deque_iter *iter);
|
||||
size_t *d_iter_rvalue(struct deque_iter *iter);
|
||||
size_t d_iter_index(struct deque_iter *iter);
|
||||
_Bool d_to_string(struct deque *_deque_, FILE *fptr);
|
||||
_Bool d_print(struct deque *_deque_, FILE *fptr, const char *start, const char *separator, const char *end);
|
||||
|
||||
#endif /* CMC_CMC_DEQUE_TEST_H */
|
||||
@@ -0,0 +1,101 @@
|
||||
|
||||
#ifndef CMC_CMC_HASHBIDIMAP_TEST_H
|
||||
#define CMC_CMC_HASHBIDIMAP_TEST_H
|
||||
|
||||
#include "macro_collections.h"
|
||||
|
||||
struct hashbidimap
|
||||
{
|
||||
struct hashbidimap_entry *(*buffer)[2];
|
||||
size_t capacity;
|
||||
size_t count;
|
||||
double load;
|
||||
int flag;
|
||||
struct hashbidimap_fkey *f_key;
|
||||
struct hashbidimap_fval *f_val;
|
||||
struct cmc_alloc_node *alloc;
|
||||
struct cmc_callbacks *callbacks;
|
||||
struct hashbidimap_iter (*it_start)(struct hashbidimap *);
|
||||
struct hashbidimap_iter (*it_end)(struct hashbidimap *);
|
||||
};
|
||||
struct hashbidimap_entry
|
||||
{
|
||||
size_t key;
|
||||
size_t value;
|
||||
size_t dist[2];
|
||||
struct hashbidimap_entry **ref[2];
|
||||
};
|
||||
struct hashbidimap_fkey
|
||||
{
|
||||
int (*cmp)(size_t, size_t);
|
||||
size_t (*cpy)(size_t);
|
||||
_Bool (*str)(FILE *, size_t);
|
||||
void (*free)(size_t);
|
||||
size_t (*hash)(size_t);
|
||||
int (*pri)(size_t, size_t);
|
||||
};
|
||||
struct hashbidimap_fval
|
||||
{
|
||||
int (*cmp)(size_t, size_t);
|
||||
size_t (*cpy)(size_t);
|
||||
_Bool (*str)(FILE *, size_t);
|
||||
void (*free)(size_t);
|
||||
size_t (*hash)(size_t);
|
||||
int (*pri)(size_t, size_t);
|
||||
};
|
||||
struct hashbidimap_iter
|
||||
{
|
||||
struct hashbidimap *target;
|
||||
size_t cursor;
|
||||
size_t index;
|
||||
size_t first;
|
||||
size_t last;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
};
|
||||
struct hashbidimap *hbm_new(size_t capacity, double load, struct hashbidimap_fkey *f_key,
|
||||
struct hashbidimap_fval *f_val);
|
||||
struct hashbidimap *hbm_new_custom(size_t capacity, double load, struct hashbidimap_fkey *f_key,
|
||||
struct hashbidimap_fval *f_val, struct cmc_alloc_node *alloc,
|
||||
struct cmc_callbacks *callbacks);
|
||||
void hbm_clear(struct hashbidimap *_map_);
|
||||
void hbm_free(struct hashbidimap *_map_);
|
||||
void hbm_customize(struct hashbidimap *_map_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks);
|
||||
_Bool hbm_insert(struct hashbidimap *_map_, size_t key, size_t value);
|
||||
_Bool hbm_update_key(struct hashbidimap *_map_, size_t val, size_t new_key);
|
||||
_Bool hbm_update_val(struct hashbidimap *_map_, size_t key, size_t new_val);
|
||||
_Bool hbm_remove_by_key(struct hashbidimap *_map_, size_t key, size_t *out_key, size_t *out_val);
|
||||
_Bool hbm_remove_by_val(struct hashbidimap *_map_, size_t val, size_t *out_key, size_t *out_val);
|
||||
size_t hbm_get_key(struct hashbidimap *_map_, size_t val);
|
||||
size_t hbm_get_val(struct hashbidimap *_map_, size_t key);
|
||||
_Bool hbm_contains_key(struct hashbidimap *_map_, size_t key);
|
||||
_Bool hbm_contains_val(struct hashbidimap *_map_, size_t val);
|
||||
_Bool hbm_empty(struct hashbidimap *_map_);
|
||||
_Bool hbm_full(struct hashbidimap *_map_);
|
||||
size_t hbm_count(struct hashbidimap *_map_);
|
||||
size_t hbm_capacity(struct hashbidimap *_map_);
|
||||
double hbm_load(struct hashbidimap *_map_);
|
||||
int hbm_flag(struct hashbidimap *_map_);
|
||||
_Bool hbm_resize(struct hashbidimap *_map_, size_t capacity);
|
||||
struct hashbidimap *hbm_copy_of(struct hashbidimap *_map_);
|
||||
_Bool hbm_equals(struct hashbidimap *_map1_, struct hashbidimap *_map2_);
|
||||
struct hashbidimap_iter *hbm_iter_new(struct hashbidimap *target);
|
||||
void hbm_iter_free(struct hashbidimap_iter *iter);
|
||||
void hbm_iter_init(struct hashbidimap_iter *iter, struct hashbidimap *target);
|
||||
_Bool hbm_iter_start(struct hashbidimap_iter *iter);
|
||||
_Bool hbm_iter_end(struct hashbidimap_iter *iter);
|
||||
void hbm_iter_to_start(struct hashbidimap_iter *iter);
|
||||
void hbm_iter_to_end(struct hashbidimap_iter *iter);
|
||||
_Bool hbm_iter_next(struct hashbidimap_iter *iter);
|
||||
_Bool hbm_iter_prev(struct hashbidimap_iter *iter);
|
||||
_Bool hbm_iter_advance(struct hashbidimap_iter *iter, size_t steps);
|
||||
_Bool hbm_iter_rewind(struct hashbidimap_iter *iter, size_t steps);
|
||||
_Bool hbm_iter_go_to(struct hashbidimap_iter *iter, size_t index);
|
||||
size_t hbm_iter_key(struct hashbidimap_iter *iter);
|
||||
size_t hbm_iter_value(struct hashbidimap_iter *iter);
|
||||
size_t hbm_iter_index(struct hashbidimap_iter *iter);
|
||||
_Bool hbm_to_string(struct hashbidimap *_map_, FILE *fptr);
|
||||
_Bool hbm_print(struct hashbidimap *_map_, FILE *fptr, const char *start, const char *separator, const char *end,
|
||||
const char *key_val_sep);
|
||||
|
||||
#endif /* CMC_CMC_HASHBIDIMAP_TEST_H */
|
||||
@@ -0,0 +1,100 @@
|
||||
|
||||
#ifndef CMC_CMC_HASHMAP_TEST_H
|
||||
#define CMC_CMC_HASHMAP_TEST_H
|
||||
|
||||
#include "macro_collections.h"
|
||||
|
||||
struct hashmap
|
||||
{
|
||||
struct hashmap_entry *buffer;
|
||||
size_t capacity;
|
||||
size_t count;
|
||||
double load;
|
||||
int flag;
|
||||
struct hashmap_fkey *f_key;
|
||||
struct hashmap_fval *f_val;
|
||||
struct cmc_alloc_node *alloc;
|
||||
struct cmc_callbacks *callbacks;
|
||||
};
|
||||
struct hashmap_entry
|
||||
{
|
||||
size_t key;
|
||||
size_t value;
|
||||
size_t dist;
|
||||
enum cmc_entry_state state;
|
||||
};
|
||||
struct hashmap_fkey
|
||||
{
|
||||
int (*cmp)(size_t, size_t);
|
||||
size_t (*cpy)(size_t);
|
||||
_Bool (*str)(FILE *, size_t);
|
||||
void (*free)(size_t);
|
||||
size_t (*hash)(size_t);
|
||||
int (*pri)(size_t, size_t);
|
||||
};
|
||||
struct hashmap_fval
|
||||
{
|
||||
int (*cmp)(size_t, size_t);
|
||||
size_t (*cpy)(size_t);
|
||||
_Bool (*str)(FILE *, size_t);
|
||||
void (*free)(size_t);
|
||||
size_t (*hash)(size_t);
|
||||
int (*pri)(size_t, size_t);
|
||||
};
|
||||
struct hashmap *hm_new(size_t capacity, double load, struct hashmap_fkey *f_key, struct hashmap_fval *f_val);
|
||||
struct hashmap *hm_new_custom(size_t capacity, double load, struct hashmap_fkey *f_key, struct hashmap_fval *f_val,
|
||||
struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks);
|
||||
void hm_clear(struct hashmap *_map_);
|
||||
void hm_free(struct hashmap *_map_);
|
||||
void hm_customize(struct hashmap *_map_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks);
|
||||
_Bool hm_insert(struct hashmap *_map_, size_t key, size_t value);
|
||||
_Bool hm_update(struct hashmap *_map_, size_t key, size_t new_value, size_t *old_value);
|
||||
_Bool hm_remove(struct hashmap *_map_, size_t key, size_t *out_value);
|
||||
_Bool hm_max(struct hashmap *_map_, size_t *key, size_t *value);
|
||||
_Bool hm_min(struct hashmap *_map_, size_t *key, size_t *value);
|
||||
size_t hm_get(struct hashmap *_map_, size_t key);
|
||||
size_t *hm_get_ref(struct hashmap *_map_, size_t key);
|
||||
_Bool hm_contains(struct hashmap *_map_, size_t key);
|
||||
_Bool hm_empty(struct hashmap *_map_);
|
||||
_Bool hm_full(struct hashmap *_map_);
|
||||
size_t hm_count(struct hashmap *_map_);
|
||||
size_t hm_capacity(struct hashmap *_map_);
|
||||
double hm_load(struct hashmap *_map_);
|
||||
int hm_flag(struct hashmap *_map_);
|
||||
_Bool hm_resize(struct hashmap *_map_, size_t capacity);
|
||||
struct hashmap *hm_copy_of(struct hashmap *_map_);
|
||||
_Bool hm_equals(struct hashmap *_map1_, struct hashmap *_map2_);
|
||||
struct hashmap hm_init(size_t capacity, double load, struct hashmap_fkey *f_key, struct hashmap_fval *f_val);
|
||||
struct hashmap hm_init_custom(size_t capacity, double load, struct hashmap_fkey *f_key, struct hashmap_fval *f_val,
|
||||
struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks);
|
||||
void hm_release(struct hashmap _map_);
|
||||
struct hashmap_iter
|
||||
{
|
||||
struct hashmap *target;
|
||||
size_t cursor;
|
||||
size_t index;
|
||||
size_t first;
|
||||
size_t last;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
};
|
||||
struct hashmap_iter hm_iter_start(struct hashmap *target);
|
||||
struct hashmap_iter hm_iter_end(struct hashmap *target);
|
||||
_Bool hm_iter_at_start(struct hashmap_iter *iter);
|
||||
_Bool hm_iter_at_end(struct hashmap_iter *iter);
|
||||
_Bool hm_iter_to_start(struct hashmap_iter *iter);
|
||||
_Bool hm_iter_to_end(struct hashmap_iter *iter);
|
||||
_Bool hm_iter_next(struct hashmap_iter *iter);
|
||||
_Bool hm_iter_prev(struct hashmap_iter *iter);
|
||||
_Bool hm_iter_advance(struct hashmap_iter *iter, size_t steps);
|
||||
_Bool hm_iter_rewind(struct hashmap_iter *iter, size_t steps);
|
||||
_Bool hm_iter_go_to(struct hashmap_iter *iter, size_t index);
|
||||
size_t hm_iter_key(struct hashmap_iter *iter);
|
||||
size_t hm_iter_value(struct hashmap_iter *iter);
|
||||
size_t *hm_iter_rvalue(struct hashmap_iter *iter);
|
||||
size_t hm_iter_index(struct hashmap_iter *iter);
|
||||
_Bool hm_to_string(struct hashmap *_map_, FILE *fptr);
|
||||
_Bool hm_print(struct hashmap *_map_, FILE *fptr, const char *start, const char *separator, const char *end,
|
||||
const char *key_val_sep);
|
||||
|
||||
#endif /* CMC_CMC_HASHMAP_TEST_H */
|
||||
@@ -0,0 +1,102 @@
|
||||
|
||||
#ifndef CMC_CMC_HASHMULTIMAP_TEST_H
|
||||
#define CMC_CMC_HASHMULTIMAP_TEST_H
|
||||
|
||||
#include "macro_collections.h"
|
||||
|
||||
struct hashmultimap
|
||||
{
|
||||
struct hashmultimap_entry *(*buffer)[2];
|
||||
size_t capacity;
|
||||
size_t count;
|
||||
double load;
|
||||
int flag;
|
||||
struct hashmultimap_fkey *f_key;
|
||||
struct hashmultimap_fval *f_val;
|
||||
struct cmc_alloc_node *alloc;
|
||||
struct cmc_callbacks *callbacks;
|
||||
};
|
||||
struct hashmultimap_entry
|
||||
{
|
||||
size_t key;
|
||||
size_t value;
|
||||
struct hashmultimap_entry *next;
|
||||
struct hashmultimap_entry *prev;
|
||||
};
|
||||
struct hashmultimap_fkey
|
||||
{
|
||||
int (*cmp)(size_t, size_t);
|
||||
size_t (*cpy)(size_t);
|
||||
_Bool (*str)(FILE *, size_t);
|
||||
void (*free)(size_t);
|
||||
size_t (*hash)(size_t);
|
||||
int (*pri)(size_t, size_t);
|
||||
};
|
||||
struct hashmultimap_fval
|
||||
{
|
||||
int (*cmp)(size_t, size_t);
|
||||
size_t (*cpy)(size_t);
|
||||
_Bool (*str)(FILE *, size_t);
|
||||
void (*free)(size_t);
|
||||
size_t (*hash)(size_t);
|
||||
int (*pri)(size_t, size_t);
|
||||
};
|
||||
struct hashmultimap *hmm_new(size_t capacity, double load, struct hashmultimap_fkey *f_key,
|
||||
struct hashmultimap_fval *f_val);
|
||||
struct hashmultimap *hmm_new_custom(size_t capacity, double load, struct hashmultimap_fkey *f_key,
|
||||
struct hashmultimap_fval *f_val, struct cmc_alloc_node *alloc,
|
||||
struct cmc_callbacks *callbacks);
|
||||
void hmm_clear(struct hashmultimap *_map_);
|
||||
void hmm_free(struct hashmultimap *_map_);
|
||||
void hmm_customize(struct hashmultimap *_map_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks);
|
||||
_Bool hmm_insert(struct hashmultimap *_map_, size_t key, size_t value);
|
||||
_Bool hmm_update(struct hashmultimap *_map_, size_t key, size_t new_value, size_t *old_value);
|
||||
size_t hmm_update_all(struct hashmultimap *_map_, size_t key, size_t new_value, size_t **old_values);
|
||||
_Bool hmm_remove(struct hashmultimap *_map_, size_t key, size_t *out_value);
|
||||
size_t hmm_remove_all(struct hashmultimap *_map_, size_t key, size_t **out_values);
|
||||
_Bool hmm_max(struct hashmultimap *_map_, size_t *key, size_t *value);
|
||||
_Bool hmm_min(struct hashmultimap *_map_, size_t *key, size_t *value);
|
||||
size_t hmm_get(struct hashmultimap *_map_, size_t key);
|
||||
size_t *hmm_get_ref(struct hashmultimap *_map_, size_t key);
|
||||
_Bool hmm_contains(struct hashmultimap *_map_, size_t key);
|
||||
_Bool hmm_empty(struct hashmultimap *_map_);
|
||||
_Bool hmm_full(struct hashmultimap *_map_);
|
||||
size_t hmm_count(struct hashmultimap *_map_);
|
||||
size_t hmm_key_count(struct hashmultimap *_map_, size_t key);
|
||||
size_t hmm_capacity(struct hashmultimap *_map_);
|
||||
double hmm_load(struct hashmultimap *_map_);
|
||||
int hmm_flag(struct hashmultimap *_map_);
|
||||
_Bool hmm_resize(struct hashmultimap *_map_, size_t capacity);
|
||||
struct hashmultimap *hmm_copy_of(struct hashmultimap *_map_);
|
||||
_Bool hmm_equals(struct hashmultimap *_map1_, struct hashmultimap *_map2_);
|
||||
struct hashmultimap_iter
|
||||
{
|
||||
struct hashmultimap *target;
|
||||
struct hashmultimap_entry *curr_entry;
|
||||
size_t cursor;
|
||||
size_t index;
|
||||
size_t first;
|
||||
size_t last;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
};
|
||||
struct hashmultimap_iter hmm_iter_start(struct hashmultimap *target);
|
||||
struct hashmultimap_iter hmm_iter_end(struct hashmultimap *target);
|
||||
_Bool hmm_iter_at_start(struct hashmultimap_iter *iter);
|
||||
_Bool hmm_iter_at_end(struct hashmultimap_iter *iter);
|
||||
_Bool hmm_iter_to_start(struct hashmultimap_iter *iter);
|
||||
_Bool hmm_iter_to_end(struct hashmultimap_iter *iter);
|
||||
_Bool hmm_iter_next(struct hashmultimap_iter *iter);
|
||||
_Bool hmm_iter_prev(struct hashmultimap_iter *iter);
|
||||
_Bool hmm_iter_advance(struct hashmultimap_iter *iter, size_t steps);
|
||||
_Bool hmm_iter_rewind(struct hashmultimap_iter *iter, size_t steps);
|
||||
_Bool hmm_iter_go_to(struct hashmultimap_iter *iter, size_t index);
|
||||
size_t hmm_iter_key(struct hashmultimap_iter *iter);
|
||||
size_t hmm_iter_value(struct hashmultimap_iter *iter);
|
||||
size_t *hmm_iter_rvalue(struct hashmultimap_iter *iter);
|
||||
size_t hmm_iter_index(struct hashmultimap_iter *iter);
|
||||
_Bool hmm_to_string(struct hashmultimap *_map_, FILE *fptr);
|
||||
_Bool hmm_print(struct hashmultimap *_map_, FILE *fptr, const char *start, const char *separator, const char *end,
|
||||
const char *key_val_sep);
|
||||
|
||||
#endif /* CMC_CMC_HASHMULTIMAP_TEST_H */
|
||||
@@ -0,0 +1,98 @@
|
||||
|
||||
#ifndef CMC_CMC_HASHMULTISET_TEST_H
|
||||
#define CMC_CMC_HASHMULTISET_TEST_H
|
||||
|
||||
#include "macro_collections.h"
|
||||
|
||||
struct hashmultiset
|
||||
{
|
||||
struct hashmultiset_entry *buffer;
|
||||
size_t capacity;
|
||||
size_t count;
|
||||
size_t cardinality;
|
||||
double load;
|
||||
int flag;
|
||||
struct hashmultiset_fval *f_val;
|
||||
struct cmc_alloc_node *alloc;
|
||||
struct cmc_callbacks *callbacks;
|
||||
};
|
||||
struct hashmultiset_entry
|
||||
{
|
||||
size_t value;
|
||||
size_t multiplicity;
|
||||
size_t dist;
|
||||
enum cmc_entry_state state;
|
||||
};
|
||||
struct hashmultiset_fval
|
||||
{
|
||||
int (*cmp)(size_t, size_t);
|
||||
size_t (*cpy)(size_t);
|
||||
_Bool (*str)(FILE *, size_t);
|
||||
void (*free)(size_t);
|
||||
size_t (*hash)(size_t);
|
||||
int (*pri)(size_t, size_t);
|
||||
};
|
||||
struct hashmultiset *hms_new(size_t capacity, double load, struct hashmultiset_fval *f_val);
|
||||
struct hashmultiset *hms_new_custom(size_t capacity, double load, struct hashmultiset_fval *f_val,
|
||||
struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks);
|
||||
void hms_clear(struct hashmultiset *_set_);
|
||||
void hms_free(struct hashmultiset *_set_);
|
||||
void hms_customize(struct hashmultiset *_set_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks);
|
||||
_Bool hms_insert(struct hashmultiset *_set_, size_t value);
|
||||
_Bool hms_insert_many(struct hashmultiset *_set_, size_t value, size_t count);
|
||||
_Bool hms_update(struct hashmultiset *_set_, size_t value, size_t multiplicity);
|
||||
_Bool hms_remove(struct hashmultiset *_set_, size_t value);
|
||||
size_t hms_remove_all(struct hashmultiset *_set_, size_t value);
|
||||
_Bool hms_max(struct hashmultiset *_set_, size_t *value);
|
||||
_Bool hms_min(struct hashmultiset *_set_, size_t *value);
|
||||
size_t hms_multiplicity_of(struct hashmultiset *_set_, size_t value);
|
||||
_Bool hms_contains(struct hashmultiset *_set_, size_t value);
|
||||
_Bool hms_empty(struct hashmultiset *_set_);
|
||||
_Bool hms_full(struct hashmultiset *_set_);
|
||||
size_t hms_count(struct hashmultiset *_set_);
|
||||
size_t hms_cardinality(struct hashmultiset *_set_);
|
||||
size_t hms_capacity(struct hashmultiset *_set_);
|
||||
double hms_load(struct hashmultiset *_set_);
|
||||
int hms_flag(struct hashmultiset *_set_);
|
||||
_Bool hms_resize(struct hashmultiset *_set_, size_t capacity);
|
||||
struct hashmultiset *hms_copy_of(struct hashmultiset *_set_);
|
||||
_Bool hms_equals(struct hashmultiset *_set1_, struct hashmultiset *_set2_);
|
||||
struct hashmultiset_iter
|
||||
{
|
||||
struct hashmultiset *target;
|
||||
size_t cursor;
|
||||
size_t index;
|
||||
size_t first;
|
||||
size_t last;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
};
|
||||
struct hashmultiset_iter hms_iter_start(struct hashmultiset *target);
|
||||
struct hashmultiset_iter hms_iter_end(struct hashmultiset *target);
|
||||
_Bool hms_iter_at_start(struct hashmultiset_iter *iter);
|
||||
_Bool hms_iter_at_end(struct hashmultiset_iter *iter);
|
||||
_Bool hms_iter_to_start(struct hashmultiset_iter *iter);
|
||||
_Bool hms_iter_to_end(struct hashmultiset_iter *iter);
|
||||
_Bool hms_iter_next(struct hashmultiset_iter *iter);
|
||||
_Bool hms_iter_prev(struct hashmultiset_iter *iter);
|
||||
_Bool hms_iter_advance(struct hashmultiset_iter *iter, size_t steps);
|
||||
_Bool hms_iter_rewind(struct hashmultiset_iter *iter, size_t steps);
|
||||
_Bool hms_iter_go_to(struct hashmultiset_iter *iter, size_t index);
|
||||
size_t hms_iter_value(struct hashmultiset_iter *iter);
|
||||
size_t hms_iter_multiplicity(struct hashmultiset_iter *iter);
|
||||
size_t hms_iter_index(struct hashmultiset_iter *iter);
|
||||
struct hashmultiset *hms_union(struct hashmultiset *_set1_, struct hashmultiset *_set2_);
|
||||
struct hashmultiset *hms_intersection(struct hashmultiset *_set1_, struct hashmultiset *_set2_);
|
||||
struct hashmultiset *hms_difference(struct hashmultiset *_set1_, struct hashmultiset *_set2_);
|
||||
struct hashmultiset *hms_summation(struct hashmultiset *_set1_, struct hashmultiset *_set2_);
|
||||
struct hashmultiset *hms_symmetric_difference(struct hashmultiset *_set1_, struct hashmultiset *_set2_);
|
||||
_Bool hms_is_subset(struct hashmultiset *_set1_, struct hashmultiset *_set2_);
|
||||
_Bool hms_is_superset(struct hashmultiset *_set1_, struct hashmultiset *_set2_);
|
||||
_Bool hms_is_proper_subset(struct hashmultiset *_set1_, struct hashmultiset *_set2_);
|
||||
_Bool hms_is_proper_superset(struct hashmultiset *_set1_, struct hashmultiset *_set2_);
|
||||
_Bool hms_is_disjointset(struct hashmultiset *_set1_, struct hashmultiset *_set2_);
|
||||
_Bool hms_to_string(struct hashmultiset *_set_, FILE *fptr);
|
||||
_Bool hms_print(struct hashmultiset *_set_, FILE *fptr, const char *start, const char *separator, const char *end,
|
||||
const char *key_val_sep);
|
||||
|
||||
#endif /* CMC_CMC_HASHMULTISET_TEST_H */
|
||||
@@ -0,0 +1,88 @@
|
||||
|
||||
#ifndef CMC_CMC_HASHSET_TEST_H
|
||||
#define CMC_CMC_HASHSET_TEST_H
|
||||
|
||||
#include "macro_collections.h"
|
||||
|
||||
struct hashset
|
||||
{
|
||||
struct hashset_entry *buffer;
|
||||
size_t capacity;
|
||||
size_t count;
|
||||
double load;
|
||||
int flag;
|
||||
struct hashset_fval *f_val;
|
||||
struct cmc_alloc_node *alloc;
|
||||
struct cmc_callbacks *callbacks;
|
||||
};
|
||||
struct hashset_entry
|
||||
{
|
||||
size_t value;
|
||||
size_t dist;
|
||||
enum cmc_entry_state state;
|
||||
};
|
||||
struct hashset_fval
|
||||
{
|
||||
int (*cmp)(size_t, size_t);
|
||||
size_t (*cpy)(size_t);
|
||||
_Bool (*str)(FILE *, size_t);
|
||||
void (*free)(size_t);
|
||||
size_t (*hash)(size_t);
|
||||
int (*pri)(size_t, size_t);
|
||||
};
|
||||
struct hashset *hs_new(size_t capacity, double load, struct hashset_fval *f_val);
|
||||
struct hashset *hs_new_custom(size_t capacity, double load, struct hashset_fval *f_val, struct cmc_alloc_node *alloc,
|
||||
struct cmc_callbacks *callbacks);
|
||||
void hs_clear(struct hashset *_set_);
|
||||
void hs_free(struct hashset *_set_);
|
||||
void hs_customize(struct hashset *_set_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks);
|
||||
_Bool hs_insert(struct hashset *_set_, size_t value);
|
||||
_Bool hs_remove(struct hashset *_set_, size_t value);
|
||||
_Bool hs_max(struct hashset *_set_, size_t *value);
|
||||
_Bool hs_min(struct hashset *_set_, size_t *value);
|
||||
_Bool hs_contains(struct hashset *_set_, size_t value);
|
||||
_Bool hs_empty(struct hashset *_set_);
|
||||
_Bool hs_full(struct hashset *_set_);
|
||||
size_t hs_count(struct hashset *_set_);
|
||||
size_t hs_capacity(struct hashset *_set_);
|
||||
double hs_load(struct hashset *_set_);
|
||||
int hs_flag(struct hashset *_set_);
|
||||
_Bool hs_resize(struct hashset *_set_, size_t capacity);
|
||||
struct hashset *hs_copy_of(struct hashset *_set_);
|
||||
_Bool hs_equals(struct hashset *_set1_, struct hashset *_set2_);
|
||||
struct hashset_iter
|
||||
{
|
||||
struct hashset *target;
|
||||
size_t cursor;
|
||||
size_t index;
|
||||
size_t first;
|
||||
size_t last;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
};
|
||||
struct hashset_iter hs_iter_start(struct hashset *target);
|
||||
struct hashset_iter hs_iter_end(struct hashset *target);
|
||||
_Bool hs_iter_at_start(struct hashset_iter *iter);
|
||||
_Bool hs_iter_at_end(struct hashset_iter *iter);
|
||||
_Bool hs_iter_to_start(struct hashset_iter *iter);
|
||||
_Bool hs_iter_to_end(struct hashset_iter *iter);
|
||||
_Bool hs_iter_next(struct hashset_iter *iter);
|
||||
_Bool hs_iter_prev(struct hashset_iter *iter);
|
||||
_Bool hs_iter_advance(struct hashset_iter *iter, size_t steps);
|
||||
_Bool hs_iter_rewind(struct hashset_iter *iter, size_t steps);
|
||||
_Bool hs_iter_go_to(struct hashset_iter *iter, size_t index);
|
||||
size_t hs_iter_value(struct hashset_iter *iter);
|
||||
size_t hs_iter_index(struct hashset_iter *iter);
|
||||
struct hashset *hs_union(struct hashset *_set1_, struct hashset *_set2_);
|
||||
struct hashset *hs_intersection(struct hashset *_set1_, struct hashset *_set2_);
|
||||
struct hashset *hs_difference(struct hashset *_set1_, struct hashset *_set2_);
|
||||
struct hashset *hs_symmetric_difference(struct hashset *_set1_, struct hashset *_set2_);
|
||||
_Bool hs_is_subset(struct hashset *_set1_, struct hashset *_set2_);
|
||||
_Bool hs_is_superset(struct hashset *_set1_, struct hashset *_set2_);
|
||||
_Bool hs_is_proper_subset(struct hashset *_set1_, struct hashset *_set2_);
|
||||
_Bool hs_is_proper_superset(struct hashset *_set1_, struct hashset *_set2_);
|
||||
_Bool hs_is_disjointset(struct hashset *_set1_, struct hashset *_set2_);
|
||||
_Bool hs_to_string(struct hashset *_set_, FILE *fptr);
|
||||
_Bool hs_print(struct hashset *_set_, FILE *fptr, const char *start, const char *separator, const char *end);
|
||||
|
||||
#endif /* CMC_CMC_HASHSET_TEST_H */
|
||||
@@ -0,0 +1,68 @@
|
||||
|
||||
#ifndef CMC_CMC_HEAP_TEST_H
|
||||
#define CMC_CMC_HEAP_TEST_H
|
||||
|
||||
#include "macro_collections.h"
|
||||
|
||||
struct heap
|
||||
{
|
||||
size_t *buffer;
|
||||
size_t capacity;
|
||||
size_t count;
|
||||
enum cmc_heap_order HO;
|
||||
int flag;
|
||||
struct heap_fval *f_val;
|
||||
struct cmc_alloc_node *alloc;
|
||||
struct cmc_callbacks *callbacks;
|
||||
};
|
||||
struct heap_fval
|
||||
{
|
||||
int (*cmp)(size_t, size_t);
|
||||
size_t (*cpy)(size_t);
|
||||
_Bool (*str)(FILE *, size_t);
|
||||
void (*free)(size_t);
|
||||
size_t (*hash)(size_t);
|
||||
int (*pri)(size_t, size_t);
|
||||
};
|
||||
struct heap *h_new(size_t capacity, enum cmc_heap_order HO, struct heap_fval *f_val);
|
||||
struct heap *h_new_custom(size_t capacity, enum cmc_heap_order HO, struct heap_fval *f_val,
|
||||
struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks);
|
||||
void h_clear(struct heap *_heap_);
|
||||
void h_free(struct heap *_heap_);
|
||||
void h_customize(struct heap *_heap_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks);
|
||||
_Bool h_insert(struct heap *_heap_, size_t value);
|
||||
_Bool h_remove(struct heap *_heap_);
|
||||
size_t h_peek(struct heap *_heap_);
|
||||
_Bool h_contains(struct heap *_heap_, size_t value);
|
||||
_Bool h_empty(struct heap *_heap_);
|
||||
_Bool h_full(struct heap *_heap_);
|
||||
size_t h_count(struct heap *_heap_);
|
||||
size_t h_capacity(struct heap *_heap_);
|
||||
int h_flag(struct heap *_heap_);
|
||||
_Bool h_resize(struct heap *_heap_, size_t capacity);
|
||||
struct heap *h_copy_of(struct heap *_heap_);
|
||||
_Bool h_equals(struct heap *_heap1_, struct heap *_heap2_);
|
||||
struct heap_iter
|
||||
{
|
||||
struct heap *target;
|
||||
size_t cursor;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
};
|
||||
struct heap_iter h_iter_start(struct heap *target);
|
||||
struct heap_iter h_iter_end(struct heap *target);
|
||||
_Bool h_iter_at_start(struct heap_iter *iter);
|
||||
_Bool h_iter_at_end(struct heap_iter *iter);
|
||||
_Bool h_iter_to_start(struct heap_iter *iter);
|
||||
_Bool h_iter_to_end(struct heap_iter *iter);
|
||||
_Bool h_iter_next(struct heap_iter *iter);
|
||||
_Bool h_iter_prev(struct heap_iter *iter);
|
||||
_Bool h_iter_advance(struct heap_iter *iter, size_t steps);
|
||||
_Bool h_iter_rewind(struct heap_iter *iter, size_t steps);
|
||||
_Bool h_iter_go_to(struct heap_iter *iter, size_t index);
|
||||
size_t h_iter_value(struct heap_iter *iter);
|
||||
size_t h_iter_index(struct heap_iter *iter);
|
||||
_Bool h_to_string(struct heap *_heap_, FILE *fptr);
|
||||
_Bool h_print(struct heap *_heap_, FILE *fptr, const char *start, const char *separator, const char *end);
|
||||
|
||||
#endif /* CMC_CMC_HEAP_TEST_H */
|
||||
@@ -0,0 +1,72 @@
|
||||
|
||||
#ifndef CMC_CMC_INTERVALHEAP_TEST_H
|
||||
#define CMC_CMC_INTERVALHEAP_TEST_H
|
||||
|
||||
#include "macro_collections.h"
|
||||
|
||||
struct intervalheap
|
||||
{
|
||||
size_t (*buffer)[2];
|
||||
size_t capacity;
|
||||
size_t size;
|
||||
size_t count;
|
||||
int flag;
|
||||
struct intervalheap_fval *f_val;
|
||||
struct cmc_alloc_node *alloc;
|
||||
struct cmc_callbacks *callbacks;
|
||||
};
|
||||
struct intervalheap_fval
|
||||
{
|
||||
int (*cmp)(size_t, size_t);
|
||||
size_t (*cpy)(size_t);
|
||||
_Bool (*str)(FILE *, size_t);
|
||||
void (*free)(size_t);
|
||||
size_t (*hash)(size_t);
|
||||
int (*pri)(size_t, size_t);
|
||||
};
|
||||
struct intervalheap *ih_new(size_t capacity, struct intervalheap_fval *f_val);
|
||||
struct intervalheap *ih_new_custom(size_t capacity, struct intervalheap_fval *f_val, struct cmc_alloc_node *alloc,
|
||||
struct cmc_callbacks *callbacks);
|
||||
void ih_clear(struct intervalheap *_heap_);
|
||||
void ih_free(struct intervalheap *_heap_);
|
||||
void ih_customize(struct intervalheap *_heap_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks);
|
||||
_Bool ih_insert(struct intervalheap *_heap_, size_t value);
|
||||
_Bool ih_remove_max(struct intervalheap *_heap_);
|
||||
_Bool ih_remove_min(struct intervalheap *_heap_);
|
||||
_Bool ih_update_max(struct intervalheap *_heap_, size_t value);
|
||||
_Bool ih_update_min(struct intervalheap *_heap_, size_t value);
|
||||
size_t ih_max(struct intervalheap *_heap_);
|
||||
size_t ih_min(struct intervalheap *_heap_);
|
||||
_Bool ih_contains(struct intervalheap *_heap_, size_t value);
|
||||
_Bool ih_empty(struct intervalheap *_heap_);
|
||||
_Bool ih_full(struct intervalheap *_heap_);
|
||||
size_t ih_count(struct intervalheap *_heap_);
|
||||
size_t ih_capacity(struct intervalheap *_heap_);
|
||||
int ih_flag(struct intervalheap *_heap_);
|
||||
_Bool ih_resize(struct intervalheap *_heap_, size_t capacity);
|
||||
struct intervalheap *ih_copy_of(struct intervalheap *_heap_);
|
||||
_Bool ih_equals(struct intervalheap *_heap1_, struct intervalheap *_heap2_);
|
||||
struct intervalheap_iter
|
||||
{
|
||||
struct intervalheap *target;
|
||||
size_t cursor;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
};
|
||||
struct intervalheap_iter ih_iter_start(struct intervalheap *target);
|
||||
struct intervalheap_iter ih_iter_end(struct intervalheap *target);
|
||||
_Bool ih_iter_at_start(struct intervalheap_iter *iter);
|
||||
_Bool ih_iter_at_end(struct intervalheap_iter *iter);
|
||||
_Bool ih_iter_to_start(struct intervalheap_iter *iter);
|
||||
_Bool ih_iter_to_end(struct intervalheap_iter *iter);
|
||||
_Bool ih_iter_next(struct intervalheap_iter *iter);
|
||||
_Bool ih_iter_prev(struct intervalheap_iter *iter);
|
||||
_Bool ih_iter_advance(struct intervalheap_iter *iter, size_t steps);
|
||||
_Bool ih_iter_rewind(struct intervalheap_iter *iter, size_t steps);
|
||||
_Bool ih_iter_go_to(struct intervalheap_iter *iter, size_t index);
|
||||
size_t ih_iter_value(struct intervalheap_iter *iter);
|
||||
size_t ih_iter_index(struct intervalheap_iter *iter);
|
||||
_Bool ih_to_string(struct intervalheap *_heap_, FILE *fptr);
|
||||
_Bool ih_print(struct intervalheap *_heap_, FILE *fptr, const char *start, const char *separator, const char *end);
|
||||
|
||||
#endif /* CMC_CMC_INTERVALHEAP_TEST_H */
|
||||
@@ -0,0 +1,92 @@
|
||||
|
||||
#ifndef CMC_CMC_LINKEDLIST_TEST_H
|
||||
#define CMC_CMC_LINKEDLIST_TEST_H
|
||||
|
||||
#include "macro_collections.h"
|
||||
|
||||
struct linkedlist
|
||||
{
|
||||
struct linkedlist_node *head;
|
||||
struct linkedlist_node *tail;
|
||||
size_t count;
|
||||
int flag;
|
||||
struct linkedlist_fval *f_val;
|
||||
struct cmc_alloc_node *alloc;
|
||||
struct cmc_callbacks *callbacks;
|
||||
};
|
||||
struct linkedlist_node
|
||||
{
|
||||
size_t value;
|
||||
struct linkedlist_node *next;
|
||||
struct linkedlist_node *prev;
|
||||
};
|
||||
struct linkedlist_fval
|
||||
{
|
||||
int (*cmp)(size_t, size_t);
|
||||
size_t (*cpy)(size_t);
|
||||
_Bool (*str)(FILE *, size_t);
|
||||
void (*free)(size_t);
|
||||
size_t (*hash)(size_t);
|
||||
int (*pri)(size_t, size_t);
|
||||
};
|
||||
struct linkedlist *ll_new(struct linkedlist_fval *f_val);
|
||||
struct linkedlist *ll_new_custom(struct linkedlist_fval *f_val, struct cmc_alloc_node *alloc,
|
||||
struct cmc_callbacks *callbacks);
|
||||
void ll_clear(struct linkedlist *_list_);
|
||||
void ll_free(struct linkedlist *_list_);
|
||||
void ll_customize(struct linkedlist *_list_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks);
|
||||
_Bool ll_push_front(struct linkedlist *_list_, size_t value);
|
||||
_Bool ll_push_at(struct linkedlist *_list_, size_t value, size_t index);
|
||||
_Bool ll_push_back(struct linkedlist *_list_, size_t value);
|
||||
_Bool ll_pop_front(struct linkedlist *_list_);
|
||||
_Bool ll_pop_at(struct linkedlist *_list_, size_t index);
|
||||
_Bool ll_pop_back(struct linkedlist *_list_);
|
||||
size_t ll_front(struct linkedlist *_list_);
|
||||
size_t ll_get(struct linkedlist *_list_, size_t index);
|
||||
size_t *ll_get_ref(struct linkedlist *_list_, size_t index);
|
||||
size_t ll_back(struct linkedlist *_list_);
|
||||
_Bool ll_contains(struct linkedlist *_list_, size_t value);
|
||||
_Bool ll_empty(struct linkedlist *_list_);
|
||||
size_t ll_count(struct linkedlist *_list_);
|
||||
int ll_flag(struct linkedlist *_list_);
|
||||
struct linkedlist *ll_copy_of(struct linkedlist *_list_);
|
||||
_Bool ll_equals(struct linkedlist *_list1_, struct linkedlist *_list2_);
|
||||
struct linkedlist_iter
|
||||
{
|
||||
struct linkedlist *target;
|
||||
struct linkedlist_node *cursor;
|
||||
size_t index;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
};
|
||||
struct linkedlist_iter ll_iter_start(struct linkedlist *target);
|
||||
struct linkedlist_iter ll_iter_end(struct linkedlist *target);
|
||||
_Bool ll_iter_at_start(struct linkedlist_iter *iter);
|
||||
_Bool ll_iter_at_end(struct linkedlist_iter *iter);
|
||||
_Bool ll_iter_to_start(struct linkedlist_iter *iter);
|
||||
_Bool ll_iter_to_end(struct linkedlist_iter *iter);
|
||||
_Bool ll_iter_next(struct linkedlist_iter *iter);
|
||||
_Bool ll_iter_prev(struct linkedlist_iter *iter);
|
||||
_Bool ll_iter_advance(struct linkedlist_iter *iter, size_t steps);
|
||||
_Bool ll_iter_rewind(struct linkedlist_iter *iter, size_t steps);
|
||||
_Bool ll_iter_go_to(struct linkedlist_iter *iter, size_t index);
|
||||
size_t ll_iter_value(struct linkedlist_iter *iter);
|
||||
size_t *ll_iter_rvalue(struct linkedlist_iter *iter);
|
||||
size_t ll_iter_index(struct linkedlist_iter *iter);
|
||||
struct linkedlist_node *ll_iter_node(struct linkedlist_iter *iter);
|
||||
struct linkedlist_node *ll_new_node(struct linkedlist *_list_, size_t value);
|
||||
void ll_free_node(struct linkedlist *_list_, struct linkedlist_node *_node_);
|
||||
struct linkedlist_node *ll_head(struct linkedlist *_list_);
|
||||
struct linkedlist_node *ll_get_node(struct linkedlist *_list_, size_t index);
|
||||
struct linkedlist_node *ll_tail(struct linkedlist *_list_);
|
||||
_Bool ll_add_next(struct linkedlist *_owner_, struct linkedlist_node *_node_, size_t value);
|
||||
_Bool ll_add_prev(struct linkedlist *_owner_, struct linkedlist_node *_node_, size_t value);
|
||||
_Bool ll_del_next(struct linkedlist *_owner_, struct linkedlist_node *_node_);
|
||||
_Bool ll_del_curr(struct linkedlist *_owner_, struct linkedlist_node *_node_);
|
||||
_Bool ll_del_prev(struct linkedlist *_owner_, struct linkedlist_node *_node_);
|
||||
struct linkedlist_node *ll_next_node(struct linkedlist_node *_node_);
|
||||
struct linkedlist_node *ll_prev_node(struct linkedlist_node *_node_);
|
||||
_Bool ll_to_string(struct linkedlist *_list_, FILE *fptr);
|
||||
_Bool ll_print(struct linkedlist *_list_, FILE *fptr, const char *start, const char *separator, const char *end);
|
||||
|
||||
#endif /* CMC_CMC_LINKEDLIST_TEST_H */
|
||||
@@ -0,0 +1,82 @@
|
||||
|
||||
#ifndef CMC_CMC_LIST_TEST_H
|
||||
#define CMC_CMC_LIST_TEST_H
|
||||
|
||||
#include "macro_collections.h"
|
||||
|
||||
struct list
|
||||
{
|
||||
size_t *buffer;
|
||||
size_t capacity;
|
||||
size_t count;
|
||||
int flag;
|
||||
struct list_fval *f_val;
|
||||
struct cmc_alloc_node *alloc;
|
||||
struct cmc_callbacks *callbacks;
|
||||
};
|
||||
struct list_fval
|
||||
{
|
||||
int (*cmp)(size_t, size_t);
|
||||
size_t (*cpy)(size_t);
|
||||
_Bool (*str)(FILE *, size_t);
|
||||
void (*free)(size_t);
|
||||
size_t (*hash)(size_t);
|
||||
int (*pri)(size_t, size_t);
|
||||
};
|
||||
struct list *l_new(size_t capacity, struct list_fval *f_val);
|
||||
struct list *l_new_custom(size_t capacity, struct list_fval *f_val, struct cmc_alloc_node *alloc,
|
||||
struct cmc_callbacks *callbacks);
|
||||
void l_clear(struct list *_list_);
|
||||
void l_free(struct list *_list_);
|
||||
void l_customize(struct list *_list_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks);
|
||||
_Bool l_push_front(struct list *_list_, size_t value);
|
||||
_Bool l_push_at(struct list *_list_, size_t value, size_t index);
|
||||
_Bool l_push_back(struct list *_list_, size_t value);
|
||||
_Bool l_pop_front(struct list *_list_);
|
||||
_Bool l_pop_at(struct list *_list_, size_t index);
|
||||
_Bool l_pop_back(struct list *_list_);
|
||||
size_t l_front(struct list *_list_);
|
||||
size_t l_get(struct list *_list_, size_t index);
|
||||
size_t *l_get_ref(struct list *_list_, size_t index);
|
||||
size_t l_back(struct list *_list_);
|
||||
size_t l_index_of(struct list *_list_, size_t value, _Bool from_start);
|
||||
_Bool l_contains(struct list *_list_, size_t value);
|
||||
_Bool l_empty(struct list *_list_);
|
||||
_Bool l_full(struct list *_list_);
|
||||
size_t l_count(struct list *_list_);
|
||||
_Bool l_fits(struct list *_list_, size_t size);
|
||||
size_t l_capacity(struct list *_list_);
|
||||
int l_flag(struct list *_list_);
|
||||
_Bool l_resize(struct list *_list_, size_t capacity);
|
||||
struct list *l_copy_of(struct list *_list_);
|
||||
_Bool l_equals(struct list *_list1_, struct list *_list2_);
|
||||
struct list_iter
|
||||
{
|
||||
struct list *target;
|
||||
size_t cursor;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
};
|
||||
struct list_iter l_iter_start(struct list *target);
|
||||
struct list_iter l_iter_end(struct list *target);
|
||||
_Bool l_iter_at_start(struct list_iter *iter);
|
||||
_Bool l_iter_at_end(struct list_iter *iter);
|
||||
_Bool l_iter_to_start(struct list_iter *iter);
|
||||
_Bool l_iter_to_end(struct list_iter *iter);
|
||||
_Bool l_iter_next(struct list_iter *iter);
|
||||
_Bool l_iter_prev(struct list_iter *iter);
|
||||
_Bool l_iter_advance(struct list_iter *iter, size_t steps);
|
||||
_Bool l_iter_rewind(struct list_iter *iter, size_t steps);
|
||||
_Bool l_iter_go_to(struct list_iter *iter, size_t index);
|
||||
size_t l_iter_value(struct list_iter *iter);
|
||||
size_t *l_iter_rvalue(struct list_iter *iter);
|
||||
size_t l_iter_index(struct list_iter *iter);
|
||||
_Bool l_seq_push_front(struct list *_list_, size_t *values, size_t size);
|
||||
_Bool l_seq_push_at(struct list *_list_, size_t *values, size_t size, size_t index);
|
||||
_Bool l_seq_push_back(struct list *_list_, size_t *values, size_t size);
|
||||
_Bool l_seq_pop_at(struct list *_list_, size_t from, size_t to);
|
||||
struct list *l_seq_sublist(struct list *_list_, size_t from, size_t to);
|
||||
_Bool l_to_string(struct list *_list_, FILE *fptr);
|
||||
_Bool l_print(struct list *_list_, FILE *fptr, const char *start, const char *separator, const char *end);
|
||||
|
||||
#endif /* CMC_CMC_LIST_TEST_H */
|
||||
@@ -0,0 +1,71 @@
|
||||
|
||||
#ifndef CMC_CMC_QUEUE_TEST_H
|
||||
#define CMC_CMC_QUEUE_TEST_H
|
||||
|
||||
#include "macro_collections.h"
|
||||
|
||||
struct queue
|
||||
{
|
||||
size_t *buffer;
|
||||
size_t capacity;
|
||||
size_t count;
|
||||
size_t front;
|
||||
size_t back;
|
||||
int flag;
|
||||
struct queue_fval *f_val;
|
||||
struct cmc_alloc_node *alloc;
|
||||
struct cmc_callbacks *callbacks;
|
||||
};
|
||||
struct queue_fval
|
||||
{
|
||||
int (*cmp)(size_t, size_t);
|
||||
size_t (*cpy)(size_t);
|
||||
_Bool (*str)(FILE *, size_t);
|
||||
void (*free)(size_t);
|
||||
size_t (*hash)(size_t);
|
||||
int (*pri)(size_t, size_t);
|
||||
};
|
||||
struct queue *q_new(size_t capacity, struct queue_fval *f_val);
|
||||
struct queue *q_new_custom(size_t capacity, struct queue_fval *f_val, struct cmc_alloc_node *alloc,
|
||||
struct cmc_callbacks *callbacks);
|
||||
void q_clear(struct queue *_queue_);
|
||||
void q_free(struct queue *_queue_);
|
||||
void q_customize(struct queue *_queue_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks);
|
||||
_Bool q_enqueue(struct queue *_queue_, size_t value);
|
||||
_Bool q_dequeue(struct queue *_queue_);
|
||||
size_t q_peek(struct queue *_queue_);
|
||||
_Bool q_contains(struct queue *_queue_, size_t value);
|
||||
_Bool q_empty(struct queue *_queue_);
|
||||
_Bool q_full(struct queue *_queue_);
|
||||
size_t q_count(struct queue *_queue_);
|
||||
size_t q_capacity(struct queue *_queue_);
|
||||
int q_flag(struct queue *_queue_);
|
||||
_Bool q_resize(struct queue *_queue_, size_t capacity);
|
||||
struct queue *q_copy_of(struct queue *_queue_);
|
||||
_Bool q_equals(struct queue *_queue1_, struct queue *_queue2_);
|
||||
struct queue_iter
|
||||
{
|
||||
struct queue *target;
|
||||
size_t cursor;
|
||||
size_t index;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
};
|
||||
struct queue_iter q_iter_start(struct queue *target);
|
||||
struct queue_iter q_iter_end(struct queue *target);
|
||||
_Bool q_iter_at_start(struct queue_iter *iter);
|
||||
_Bool q_iter_at_end(struct queue_iter *iter);
|
||||
_Bool q_iter_to_start(struct queue_iter *iter);
|
||||
_Bool q_iter_to_end(struct queue_iter *iter);
|
||||
_Bool q_iter_next(struct queue_iter *iter);
|
||||
_Bool q_iter_prev(struct queue_iter *iter);
|
||||
_Bool q_iter_advance(struct queue_iter *iter, size_t steps);
|
||||
_Bool q_iter_rewind(struct queue_iter *iter, size_t steps);
|
||||
_Bool q_iter_go_to(struct queue_iter *iter, size_t index);
|
||||
size_t q_iter_value(struct queue_iter *iter);
|
||||
size_t *q_iter_rvalue(struct queue_iter *iter);
|
||||
size_t q_iter_index(struct queue_iter *iter);
|
||||
_Bool q_to_string(struct queue *_queue_, FILE *fptr);
|
||||
_Bool q_print(struct queue *_queue_, FILE *fptr, const char *start, const char *separator, const char *end);
|
||||
|
||||
#endif /* CMC_CMC_QUEUE_TEST_H */
|
||||
@@ -0,0 +1,72 @@
|
||||
|
||||
#ifndef CMC_CMC_SORTEDLIST_TEST_H
|
||||
#define CMC_CMC_SORTEDLIST_TEST_H
|
||||
|
||||
#include "macro_collections.h"
|
||||
|
||||
struct sortedlist
|
||||
{
|
||||
size_t *buffer;
|
||||
size_t capacity;
|
||||
size_t count;
|
||||
_Bool is_sorted;
|
||||
int flag;
|
||||
struct sortedlist_fval *f_val;
|
||||
struct cmc_alloc_node *alloc;
|
||||
struct cmc_callbacks *callbacks;
|
||||
};
|
||||
struct sortedlist_fval
|
||||
{
|
||||
int (*cmp)(size_t, size_t);
|
||||
size_t (*cpy)(size_t);
|
||||
_Bool (*str)(FILE *, size_t);
|
||||
void (*free)(size_t);
|
||||
size_t (*hash)(size_t);
|
||||
int (*pri)(size_t, size_t);
|
||||
};
|
||||
struct sortedlist *sl_new(size_t capacity, struct sortedlist_fval *f_val);
|
||||
struct sortedlist *sl_new_custom(size_t capacity, struct sortedlist_fval *f_val, struct cmc_alloc_node *alloc,
|
||||
struct cmc_callbacks *callbacks);
|
||||
void sl_clear(struct sortedlist *_list_);
|
||||
void sl_free(struct sortedlist *_list_);
|
||||
void sl_customize(struct sortedlist *_list_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks);
|
||||
_Bool sl_insert(struct sortedlist *_list_, size_t value);
|
||||
_Bool sl_remove(struct sortedlist *_list_, size_t index);
|
||||
size_t sl_max(struct sortedlist *_list_);
|
||||
size_t sl_min(struct sortedlist *_list_);
|
||||
size_t sl_get(struct sortedlist *_list_, size_t index);
|
||||
size_t sl_index_of(struct sortedlist *_list_, size_t value, _Bool from_start);
|
||||
_Bool sl_contains(struct sortedlist *_list_, size_t value);
|
||||
_Bool sl_empty(struct sortedlist *_list_);
|
||||
_Bool sl_full(struct sortedlist *_list_);
|
||||
size_t sl_count(struct sortedlist *_list_);
|
||||
size_t sl_capacity(struct sortedlist *_list_);
|
||||
int sl_flag(struct sortedlist *_list_);
|
||||
_Bool sl_resize(struct sortedlist *_list_, size_t capacity);
|
||||
void sl_sort(struct sortedlist *_list_);
|
||||
struct sortedlist *sl_copy_of(struct sortedlist *_list_);
|
||||
_Bool sl_equals(struct sortedlist *_list1_, struct sortedlist *_list2_);
|
||||
struct sortedlist_iter
|
||||
{
|
||||
struct sortedlist *target;
|
||||
size_t cursor;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
};
|
||||
struct sortedlist_iter sl_iter_start(struct sortedlist *target);
|
||||
struct sortedlist_iter sl_iter_end(struct sortedlist *target);
|
||||
_Bool sl_iter_at_start(struct sortedlist_iter *iter);
|
||||
_Bool sl_iter_at_end(struct sortedlist_iter *iter);
|
||||
_Bool sl_iter_to_start(struct sortedlist_iter *iter);
|
||||
_Bool sl_iter_to_end(struct sortedlist_iter *iter);
|
||||
_Bool sl_iter_next(struct sortedlist_iter *iter);
|
||||
_Bool sl_iter_prev(struct sortedlist_iter *iter);
|
||||
_Bool sl_iter_advance(struct sortedlist_iter *iter, size_t steps);
|
||||
_Bool sl_iter_rewind(struct sortedlist_iter *iter, size_t steps);
|
||||
_Bool sl_iter_go_to(struct sortedlist_iter *iter, size_t index);
|
||||
size_t sl_iter_value(struct sortedlist_iter *iter);
|
||||
size_t sl_iter_index(struct sortedlist_iter *iter);
|
||||
_Bool sl_to_string(struct sortedlist *_list_, FILE *fptr);
|
||||
_Bool sl_print(struct sortedlist *_list_, FILE *fptr, const char *start, const char *separator, const char *end);
|
||||
|
||||
#endif /* CMC_CMC_SORTEDLIST_TEST_H */
|
||||
@@ -0,0 +1,68 @@
|
||||
|
||||
#ifndef CMC_CMC_STACK_TEST_H
|
||||
#define CMC_CMC_STACK_TEST_H
|
||||
|
||||
#include "macro_collections.h"
|
||||
|
||||
struct stack
|
||||
{
|
||||
size_t *buffer;
|
||||
size_t capacity;
|
||||
size_t count;
|
||||
int flag;
|
||||
struct stack_fval *f_val;
|
||||
struct cmc_alloc_node *alloc;
|
||||
struct cmc_callbacks *callbacks;
|
||||
};
|
||||
struct stack_fval
|
||||
{
|
||||
int (*cmp)(size_t, size_t);
|
||||
size_t (*cpy)(size_t);
|
||||
_Bool (*str)(FILE *, size_t);
|
||||
void (*free)(size_t);
|
||||
size_t (*hash)(size_t);
|
||||
int (*pri)(size_t, size_t);
|
||||
};
|
||||
struct stack *s_new(size_t capacity, struct stack_fval *f_val);
|
||||
struct stack *s_new_custom(size_t capacity, struct stack_fval *f_val, struct cmc_alloc_node *alloc,
|
||||
struct cmc_callbacks *callbacks);
|
||||
void s_clear(struct stack *_stack_);
|
||||
void s_free(struct stack *_stack_);
|
||||
void s_customize(struct stack *_stack_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks);
|
||||
_Bool s_push(struct stack *_stack_, size_t value);
|
||||
_Bool s_pop(struct stack *_stack_);
|
||||
size_t s_top(struct stack *_stack_);
|
||||
_Bool s_contains(struct stack *_stack_, size_t value);
|
||||
_Bool s_empty(struct stack *_stack_);
|
||||
_Bool s_full(struct stack *_stack_);
|
||||
size_t s_count(struct stack *_stack_);
|
||||
size_t s_capacity(struct stack *_stack_);
|
||||
int s_flag(struct stack *_stack_);
|
||||
_Bool s_resize(struct stack *_stack_, size_t capacity);
|
||||
struct stack *s_copy_of(struct stack *_stack_);
|
||||
_Bool s_equals(struct stack *_stack1_, struct stack *_stack2_);
|
||||
struct stack_iter
|
||||
{
|
||||
struct stack *target;
|
||||
size_t cursor;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
};
|
||||
struct stack_iter s_iter_start(struct stack *target);
|
||||
struct stack_iter s_iter_end(struct stack *target);
|
||||
_Bool s_iter_at_start(struct stack_iter *iter);
|
||||
_Bool s_iter_at_end(struct stack_iter *iter);
|
||||
_Bool s_iter_to_start(struct stack_iter *iter);
|
||||
_Bool s_iter_to_end(struct stack_iter *iter);
|
||||
_Bool s_iter_next(struct stack_iter *iter);
|
||||
_Bool s_iter_prev(struct stack_iter *iter);
|
||||
_Bool s_iter_advance(struct stack_iter *iter, size_t steps);
|
||||
_Bool s_iter_rewind(struct stack_iter *iter, size_t steps);
|
||||
_Bool s_iter_go_to(struct stack_iter *iter, size_t index);
|
||||
size_t s_iter_value(struct stack_iter *iter);
|
||||
size_t *s_iter_rvalue(struct stack_iter *iter);
|
||||
size_t s_iter_index(struct stack_iter *iter);
|
||||
_Bool s_to_string(struct stack *_stack_, FILE *fptr);
|
||||
_Bool s_print(struct stack *_stack_, FILE *fptr, const char *start, const char *separator, const char *end);
|
||||
|
||||
#endif /* CMC_CMC_STACK_TEST_H */
|
||||
@@ -0,0 +1,92 @@
|
||||
|
||||
#ifndef CMC_CMC_TREEMAP_TEST_H
|
||||
#define CMC_CMC_TREEMAP_TEST_H
|
||||
|
||||
#include "macro_collections.h"
|
||||
|
||||
struct treemap
|
||||
{
|
||||
struct treemap_node *root;
|
||||
size_t count;
|
||||
int flag;
|
||||
struct treemap_fkey *f_key;
|
||||
struct treemap_fval *f_val;
|
||||
struct cmc_alloc_node *alloc;
|
||||
struct cmc_callbacks *callbacks;
|
||||
};
|
||||
struct treemap_node
|
||||
{
|
||||
size_t key;
|
||||
size_t value;
|
||||
unsigned char height;
|
||||
struct treemap_node *right;
|
||||
struct treemap_node *left;
|
||||
struct treemap_node *parent;
|
||||
};
|
||||
struct treemap_fkey
|
||||
{
|
||||
int (*cmp)(size_t, size_t);
|
||||
size_t (*cpy)(size_t);
|
||||
_Bool (*str)(FILE *, size_t);
|
||||
void (*free)(size_t);
|
||||
size_t (*hash)(size_t);
|
||||
int (*pri)(size_t, size_t);
|
||||
};
|
||||
struct treemap_fval
|
||||
{
|
||||
int (*cmp)(size_t, size_t);
|
||||
size_t (*cpy)(size_t);
|
||||
_Bool (*str)(FILE *, size_t);
|
||||
void (*free)(size_t);
|
||||
size_t (*hash)(size_t);
|
||||
int (*pri)(size_t, size_t);
|
||||
};
|
||||
struct treemap *tm_new(struct treemap_fkey *f_key, struct treemap_fval *f_val);
|
||||
struct treemap *tm_new_custom(struct treemap_fkey *f_key, struct treemap_fval *f_val, struct cmc_alloc_node *alloc,
|
||||
struct cmc_callbacks *callbacks);
|
||||
void tm_clear(struct treemap *_map_);
|
||||
void tm_free(struct treemap *_map_);
|
||||
void tm_customize(struct treemap *_map_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks);
|
||||
_Bool tm_insert(struct treemap *_map_, size_t key, size_t value);
|
||||
_Bool tm_update(struct treemap *_map_, size_t key, size_t new_value, size_t *old_value);
|
||||
_Bool tm_remove(struct treemap *_map_, size_t key, size_t *out_value);
|
||||
_Bool tm_max(struct treemap *_map_, size_t *key, size_t *value);
|
||||
_Bool tm_min(struct treemap *_map_, size_t *key, size_t *value);
|
||||
size_t tm_get(struct treemap *_map_, size_t key);
|
||||
size_t *tm_get_ref(struct treemap *_map_, size_t key);
|
||||
_Bool tm_contains(struct treemap *_map_, size_t key);
|
||||
_Bool tm_empty(struct treemap *_map_);
|
||||
size_t tm_count(struct treemap *_map_);
|
||||
int tm_flag(struct treemap *_map_);
|
||||
struct treemap *tm_copy_of(struct treemap *_map_);
|
||||
_Bool tm_equals(struct treemap *_map1_, struct treemap *_map2_);
|
||||
struct treemap_iter
|
||||
{
|
||||
struct treemap *target;
|
||||
struct treemap_node *cursor;
|
||||
struct treemap_node *first;
|
||||
struct treemap_node *last;
|
||||
size_t index;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
};
|
||||
struct treemap_iter tm_iter_start(struct treemap *target);
|
||||
struct treemap_iter tm_iter_end(struct treemap *target);
|
||||
_Bool tm_iter_at_start(struct treemap_iter *iter);
|
||||
_Bool tm_iter_at_end(struct treemap_iter *iter);
|
||||
_Bool tm_iter_to_start(struct treemap_iter *iter);
|
||||
_Bool tm_iter_to_end(struct treemap_iter *iter);
|
||||
_Bool tm_iter_next(struct treemap_iter *iter);
|
||||
_Bool tm_iter_prev(struct treemap_iter *iter);
|
||||
_Bool tm_iter_advance(struct treemap_iter *iter, size_t steps);
|
||||
_Bool tm_iter_rewind(struct treemap_iter *iter, size_t steps);
|
||||
_Bool tm_iter_go_to(struct treemap_iter *iter, size_t index);
|
||||
size_t tm_iter_key(struct treemap_iter *iter);
|
||||
size_t tm_iter_value(struct treemap_iter *iter);
|
||||
size_t *tm_iter_rvalue(struct treemap_iter *iter);
|
||||
size_t tm_iter_index(struct treemap_iter *iter);
|
||||
_Bool tm_to_string(struct treemap *_map_, FILE *fptr);
|
||||
_Bool tm_print(struct treemap *_map_, FILE *fptr, const char *start, const char *separator, const char *end,
|
||||
const char *key_val_sep);
|
||||
|
||||
#endif /* CMC_CMC_TREEMAP_TEST_H */
|
||||
@@ -0,0 +1,84 @@
|
||||
|
||||
#ifndef CMC_CMC_TREESET_TEST_H
|
||||
#define CMC_CMC_TREESET_TEST_H
|
||||
|
||||
#include "macro_collections.h"
|
||||
|
||||
struct treeset
|
||||
{
|
||||
struct treeset_node *root;
|
||||
size_t count;
|
||||
int flag;
|
||||
struct treeset_fval *f_val;
|
||||
struct cmc_alloc_node *alloc;
|
||||
struct cmc_callbacks *callbacks;
|
||||
};
|
||||
struct treeset_node
|
||||
{
|
||||
size_t value;
|
||||
unsigned char height;
|
||||
struct treeset_node *right;
|
||||
struct treeset_node *left;
|
||||
struct treeset_node *parent;
|
||||
};
|
||||
struct treeset_fval
|
||||
{
|
||||
int (*cmp)(size_t, size_t);
|
||||
size_t (*cpy)(size_t);
|
||||
_Bool (*str)(FILE *, size_t);
|
||||
void (*free)(size_t);
|
||||
size_t (*hash)(size_t);
|
||||
int (*pri)(size_t, size_t);
|
||||
};
|
||||
struct treeset *ts_new(struct treeset_fval *f_val);
|
||||
struct treeset *ts_new_custom(struct treeset_fval *f_val, struct cmc_alloc_node *alloc,
|
||||
struct cmc_callbacks *callbacks);
|
||||
void ts_clear(struct treeset *_set_);
|
||||
void ts_free(struct treeset *_set_);
|
||||
void ts_customize(struct treeset *_set_, struct cmc_alloc_node *alloc, struct cmc_callbacks *callbacks);
|
||||
_Bool ts_insert(struct treeset *_set_, size_t value);
|
||||
_Bool ts_remove(struct treeset *_set_, size_t value);
|
||||
_Bool ts_max(struct treeset *_set_, size_t *value);
|
||||
_Bool ts_min(struct treeset *_set_, size_t *value);
|
||||
_Bool ts_contains(struct treeset *_set_, size_t value);
|
||||
_Bool ts_empty(struct treeset *_set_);
|
||||
size_t ts_count(struct treeset *_set_);
|
||||
int ts_flag(struct treeset *_set_);
|
||||
struct treeset *ts_copy_of(struct treeset *_set_);
|
||||
_Bool ts_equals(struct treeset *_set1_, struct treeset *_set2_);
|
||||
struct treeset_iter
|
||||
{
|
||||
struct treeset *target;
|
||||
struct treeset_node *cursor;
|
||||
struct treeset_node *first;
|
||||
struct treeset_node *last;
|
||||
size_t index;
|
||||
_Bool start;
|
||||
_Bool end;
|
||||
};
|
||||
struct treeset_iter ts_iter_start(struct treeset *target);
|
||||
struct treeset_iter ts_iter_end(struct treeset *target);
|
||||
_Bool ts_iter_at_start(struct treeset_iter *iter);
|
||||
_Bool ts_iter_at_end(struct treeset_iter *iter);
|
||||
_Bool ts_iter_to_start(struct treeset_iter *iter);
|
||||
_Bool ts_iter_to_end(struct treeset_iter *iter);
|
||||
_Bool ts_iter_next(struct treeset_iter *iter);
|
||||
_Bool ts_iter_prev(struct treeset_iter *iter);
|
||||
_Bool ts_iter_advance(struct treeset_iter *iter, size_t steps);
|
||||
_Bool ts_iter_rewind(struct treeset_iter *iter, size_t steps);
|
||||
_Bool ts_iter_go_to(struct treeset_iter *iter, size_t index);
|
||||
size_t ts_iter_value(struct treeset_iter *iter);
|
||||
size_t ts_iter_index(struct treeset_iter *iter);
|
||||
struct treeset *ts_union(struct treeset *_set1_, struct treeset *_set2_);
|
||||
struct treeset *ts_intersection(struct treeset *_set1_, struct treeset *_set2_);
|
||||
struct treeset *ts_difference(struct treeset *_set1_, struct treeset *_set2_);
|
||||
struct treeset *ts_symmetric_difference(struct treeset *_set1_, struct treeset *_set2_);
|
||||
_Bool ts_is_subset(struct treeset *_set1_, struct treeset *_set2_);
|
||||
_Bool ts_is_superset(struct treeset *_set1_, struct treeset *_set2_);
|
||||
_Bool ts_is_proper_subset(struct treeset *_set1_, struct treeset *_set2_);
|
||||
_Bool ts_is_proper_superset(struct treeset *_set1_, struct treeset *_set2_);
|
||||
_Bool ts_is_disjointset(struct treeset *_set1_, struct treeset *_set2_);
|
||||
_Bool ts_to_string(struct treeset *_set_, FILE *fptr);
|
||||
_Bool ts_print(struct treeset *_set_, FILE *fptr, const char *start, const char *separator, const char *end);
|
||||
|
||||
#endif /* CMC_CMC_TREESET_TEST_H */
|
||||
@@ -1,139 +0,0 @@
|
||||
#include "../src/macro_collections.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int intcmp(int a, int b)
|
||||
{
|
||||
return (a > b) - (a < b);
|
||||
}
|
||||
|
||||
size_t inthash(int t)
|
||||
{
|
||||
size_t a = t;
|
||||
a += ~(a << 15);
|
||||
a ^= (a >> 10);
|
||||
a += (a << 3);
|
||||
a ^= (a >> 6);
|
||||
a += ~(a << 11);
|
||||
a ^= (a >> 16);
|
||||
return a;
|
||||
}
|
||||
|
||||
CMC_COLLECTION_GENERATE(LIST, l, list, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(STACK, s, stack, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(QUEUE, q, queue, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(DEQUE, d, deque, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(LINKEDLIST, ll, linked, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(HEAP, h, heap, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(TREESET, ts, tset, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(TREEMAP, tm, tmap, int, double)
|
||||
CMC_COLLECTION_GENERATE(HASHSET, hs, hset, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(HASHMAP, hm, hmap, int, double)
|
||||
|
||||
CMC_COLLECTION_GENERATE(INTERVALHEAP, ih, iheap, /* K */, int)
|
||||
CMC_COLLECTION_GENERATE(MULTIMAP, mm, mmap, int, double)
|
||||
CMC_COLLECTION_GENERATE(MULTISET, ms, mset, /* K */, int)
|
||||
|
||||
#define ITERATOR_TEST(NAME, PFX, sname, initfunc, insertbody, sumbody, \
|
||||
validation1, validation2) \
|
||||
void NAME##_iterator_test(void) \
|
||||
{ \
|
||||
int sum1 = 0; \
|
||||
double sum2 = 0.0; \
|
||||
\
|
||||
struct sname *coll = initfunc; \
|
||||
for (int i = 0; i < 10; i++) \
|
||||
{ \
|
||||
insertbody; \
|
||||
} \
|
||||
\
|
||||
struct 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, NULL); \
|
||||
\
|
||||
if ((validation1) && (validation2)) \
|
||||
printf("%12s PASSED\n", #NAME); \
|
||||
else \
|
||||
printf("%12s 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, (int)sum2 == (int)45)
|
||||
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, cmc_max_heap, 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, (int)sum2 == (int)45)
|
||||
ITERATOR_TEST(TREESET, ts, tset, ts_new(intcmp), ts_insert(coll, i),
|
||||
sum1 += ts_iter_value(&iter), sum1 == 450, 1)
|
||||
ITERATOR_TEST(INTERVALHEAP, ih, iheap, ih_new(20, intcmp), ih_insert(coll, i),
|
||||
sum1 += ih_iter_value(&iter), sum1 == 450, 1)
|
||||
ITERATOR_TEST(MULTIMAP, mm, mmap, mm_new(50, 0.8, intcmp, inthash),
|
||||
mm_insert(coll, i, (double)i / 10.0), sum1 += mm_iter_key(&iter);
|
||||
sum2 += mm_iter_value(&iter), sum1 == 450, (int)sum2 == (int)45)
|
||||
ITERATOR_TEST(MULTISET, ms, mset, ms_new(50, 0.6, intcmp, inthash),
|
||||
ms_insert(coll, i), sum1 += ms_iter_value(&iter);
|
||||
sum2 += ms_iter_multiplicity(&iter), sum1 == 450,
|
||||
(size_t)sum2 == 100)
|
||||
|
||||
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();
|
||||
|
||||
INTERVALHEAP_iterator_test();
|
||||
MULTIMAP_iterator_test();
|
||||
MULTISET_iterator_test();
|
||||
|
||||
printf("\n\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "unt/cmc/bitset.h"
|
||||
#include "unt/cmc/deque.h"
|
||||
#include "unt/cmc/hashbidimap.h"
|
||||
#include "unt/cmc/hashmap.h"
|
||||
#include "unt/cmc/hashmultimap.h"
|
||||
#include "unt/cmc/hashmultiset.h"
|
||||
#include "unt/cmc/hashset.h"
|
||||
#include "unt/cmc/heap.h"
|
||||
#include "unt/cmc/intervalheap.h"
|
||||
#include "unt/cmc/linkedlist.h"
|
||||
#include "unt/cmc/list.h"
|
||||
#include "unt/cmc/queue.h"
|
||||
#include "unt/cmc/sortedlist.h"
|
||||
#include "unt/cmc/stack.h"
|
||||
#include "unt/cmc/treemap.h"
|
||||
#include "unt/cmc/treeset.h"
|
||||
|
||||
#include "unt/utl/foreach.h"
|
||||
|
||||
#include "utl/assert.h"
|
||||
#include "utl/timer.h"
|
||||
|
||||
#include "./unt/utl.h"
|
||||
|
||||
#define cmc_run(unit, unit_fails, test_fails) \
|
||||
do \
|
||||
{ \
|
||||
uintmax_t f = unit(); \
|
||||
if (f != 0) \
|
||||
unit_fails += 1; \
|
||||
test_fails += f; \
|
||||
} while (0)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// clang-format off
|
||||
printf(" +---------------------------------------------------------------+\n");
|
||||
printf(" | C Macro Collections Library |\n");
|
||||
printf(" | |\n");
|
||||
printf(" | Test Suite |\n");
|
||||
printf(" | |\n");
|
||||
printf(" | https://github.com/LeoVen/C-Macro-Collections |\n");
|
||||
printf(" | Leonardo Vencovsky (leonardo.vencovsky@gmail.com) |\n");
|
||||
printf(" +---------------------------------------------------------------+\n\n");
|
||||
// clang-format on
|
||||
|
||||
struct cmc_timer timer;
|
||||
|
||||
cmc_timer_start(timer);
|
||||
uintmax_t tests = 0, units = 0;
|
||||
|
||||
cmc_run(CMCBitSet, units, tests);
|
||||
cmc_run(CMCBitSetIter, units, tests);
|
||||
cmc_run(CMCDeque, units, tests);
|
||||
cmc_run(CMCDequeIter, units, tests);
|
||||
cmc_run(CMCHashBidiMap, units, tests);
|
||||
cmc_run(CMCHashBidiMapIter, units, tests);
|
||||
cmc_run(CMCHashMap, units, tests);
|
||||
cmc_run(CMCHashMapIter, units, tests);
|
||||
cmc_run(CMCHashMultiMap, units, tests);
|
||||
cmc_run(CMCHashMultiMapIter, units, tests);
|
||||
cmc_run(CMCHashMultiSet, units, tests);
|
||||
cmc_run(CMCHashMultiSetIter, units, tests);
|
||||
cmc_run(CMCHashSet, units, tests);
|
||||
cmc_run(CMCHashSetIter, units, tests);
|
||||
cmc_run(CMCHeap, units, tests);
|
||||
cmc_run(CMCHeapIter, units, tests);
|
||||
cmc_run(CMCIntervalHeap, units, tests);
|
||||
cmc_run(CMCIntervalHeapIter, units, tests);
|
||||
cmc_run(CMCLinkedList, units, tests);
|
||||
cmc_run(CMCLinkedListIter, units, tests);
|
||||
cmc_run(CMCList, units, tests);
|
||||
cmc_run(CMCListIter, units, tests);
|
||||
cmc_run(CMCQueue, units, tests);
|
||||
cmc_run(CMCQueueIter, units, tests);
|
||||
cmc_run(CMCSortedList, units, tests);
|
||||
cmc_run(CMCSortedListIter, units, tests);
|
||||
cmc_run(CMCStack, units, tests);
|
||||
cmc_run(CMCStackIter, units, tests);
|
||||
cmc_run(CMCTreeMap, units, tests);
|
||||
cmc_run(CMCTreeMapIter, units, tests);
|
||||
cmc_run(CMCTreeSet, units, tests);
|
||||
cmc_run(CMCTreeSetIter, units, tests);
|
||||
|
||||
cmc_run(ForEach, units, tests);
|
||||
|
||||
cmc_timer_stop(timer);
|
||||
|
||||
printf(" +---------------------------------------------------------------+\n");
|
||||
printf(" | SUMMARY |\n");
|
||||
printf(" +---------------------------------------------------------------+\n");
|
||||
printf(" | Total Units Failed : %25" PRIuMAX " units |\n", units);
|
||||
printf(" | Total Tests Failed : %25" PRIuMAX " tests |\n", tests);
|
||||
printf(" | Total Asserts Failed : %25" PRIuMAX " asserts |\n", cmc_assert_failed);
|
||||
printf(" | Total Runtime : %25.0lf milliseconds |\n", timer.result);
|
||||
printf(" +---------------------------------------------------------------+\n");
|
||||
|
||||
return tests;
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
CC = gcc
|
||||
CFLAGS = -std=c11 -Wall -Wextra
|
||||
CFLAGS += -Wno-unused -Wno-missing-braces
|
||||
DBFLAGS = -g3
|
||||
CVFLAGS = --coverage -O0
|
||||
INCLUDE = ../../src/
|
||||
UNIT = ./unt
|
||||
|
||||
main: FORCE
|
||||
$(CC) main.c -o main.exe $(CFLAGS) $(CVFLAGS) -I $(INCLUDE) -DCMC_TEST_COLOR
|
||||
./main.exe
|
||||
gcov ./main.c
|
||||
|
||||
nocov: FORCE
|
||||
$(CC) main.c -o main.exe $(CFLAGS) -I $(INCLUDE) -DCMC_TEST_COLOR
|
||||
./main.exe
|
||||
rm *.exe
|
||||
|
||||
bare: FORCE
|
||||
$(CC) main.c -o main.exe $(CFLAGS) -I $(INCLUDE)
|
||||
./main.exe
|
||||
rm *.exe
|
||||
|
||||
debug: FORCE
|
||||
$(CC) main.c -o main.exe $(CFLAGS) -I $(INCLUDE) -DCMC_TEST_COLOR $(DBFLAGS)
|
||||
|
||||
valgrind: debug
|
||||
valgrind --leak-check=full ./main.exe
|
||||
|
||||
all: bitset deque hashbidimap hashmap hashmultimap hashmultiset hashset heap intervalheap linkedlist list queue sortedlist stack treemap treeset
|
||||
rm ./main.exe
|
||||
|
||||
bitset: $(UNIT)/bitset.c $(INCLUDE)/cmc/bitset.h
|
||||
$(CC) $^ -o main.exe -I $(INCLUDE) -DCMC_TEST_MAIN -DCMC_TEST_COLOR -DCMC_BITSET_WORD_TYPE=uint8_t
|
||||
./main.exe
|
||||
$(CC) $^ -o main.exe -I $(INCLUDE) -DCMC_TEST_MAIN -DCMC_TEST_COLOR -DCMC_BITSET_WORD_TYPE=uint16_t
|
||||
./main.exe
|
||||
$(CC) $^ -o main.exe -I $(INCLUDE) -DCMC_TEST_MAIN -DCMC_TEST_COLOR -DCMC_BITSET_WORD_TYPE=uint32_t
|
||||
./main.exe
|
||||
$(CC) $^ -o main.exe -I $(INCLUDE) -DCMC_TEST_MAIN -DCMC_TEST_COLOR -DCMC_BITSET_WORD_TYPE=uint64_t
|
||||
./main.exe
|
||||
|
||||
deque: $(UNIT)/deque.c $(INCLUDE)/cmc/deque.h
|
||||
$(CC) $^ -o main.exe -I $(INCLUDE) -DCMC_TEST_MAIN -DCMC_TEST_COLOR
|
||||
./main.exe
|
||||
|
||||
hashbidimap: $(UNIT)/hashbidimap.c $(INCLUDE)/cmc/hashbidimap.h
|
||||
$(CC) $^ -o main.exe -I $(INCLUDE) -DCMC_TEST_MAIN -DCMC_TEST_COLOR
|
||||
./main.exe
|
||||
|
||||
hashmap: $(UNIT)/hashmap.c $(INCLUDE)/cmc/hashmap.h
|
||||
$(CC) $^ -o main.exe -I $(INCLUDE) -DCMC_TEST_MAIN -DCMC_TEST_COLOR
|
||||
./main.exe
|
||||
|
||||
hashmultimap: $(UNIT)/hashmultimap.c $(INCLUDE)/cmc/hashmultimap.h
|
||||
$(CC) $^ -o main.exe -I $(INCLUDE) -DCMC_TEST_MAIN -DCMC_TEST_COLOR
|
||||
./main.exe
|
||||
|
||||
hashmultiset: $(UNIT)/hashmultiset.c $(INCLUDE)/cmc/hashmultiset.h
|
||||
$(CC) $^ -o main.exe -I $(INCLUDE) -DCMC_TEST_MAIN -DCMC_TEST_COLOR
|
||||
./main.exe
|
||||
|
||||
hashset: $(UNIT)/hashset.c $(INCLUDE)/cmc/hashset.h
|
||||
$(CC) $^ -o main.exe -I $(INCLUDE) -DCMC_TEST_MAIN -DCMC_TEST_COLOR
|
||||
./main.exe
|
||||
|
||||
heap: $(UNIT)/heap.c $(INCLUDE)/cmc/heap.h
|
||||
$(CC) $^ -o main.exe -I $(INCLUDE) -DCMC_TEST_MAIN -DCMC_TEST_COLOR
|
||||
./main.exe
|
||||
|
||||
intervalheap: $(UNIT)/intervalheap.c $(INCLUDE)/cmc/intervalheap.h
|
||||
$(CC) $^ -o main.exe -I $(INCLUDE) -DCMC_TEST_MAIN -DCMC_TEST_COLOR
|
||||
./main.exe
|
||||
|
||||
linkedlist: $(UNIT)/linkedlist.c $(INCLUDE)/cmc/linkedlist.h
|
||||
$(CC) $^ -o main.exe -I $(INCLUDE) -DCMC_TEST_MAIN -DCMC_TEST_COLOR
|
||||
./main.exe
|
||||
|
||||
list: $(UNIT)/list.c $(INCLUDE)/cmc/list.h
|
||||
$(CC) $^ -o main.exe -I $(INCLUDE) -DCMC_TEST_MAIN -DCMC_TEST_COLOR
|
||||
./main.exe
|
||||
|
||||
queue: $(UNIT)/queue.c $(INCLUDE)/cmc/queue.h
|
||||
$(CC) $^ -o main.exe -I $(INCLUDE) -DCMC_TEST_MAIN -DCMC_TEST_COLOR
|
||||
./main.exe
|
||||
|
||||
sortedlist: $(UNIT)/sortedlist.c $(INCLUDE)/cmc/sortedlist.h
|
||||
$(CC) $^ -o main.exe -I $(INCLUDE) -DCMC_TEST_MAIN -DCMC_TEST_COLOR
|
||||
./main.exe
|
||||
|
||||
stack: $(UNIT)/stack.c $(INCLUDE)/cmc/stack.h
|
||||
$(CC) $^ -o main.exe -I $(INCLUDE) -DCMC_TEST_MAIN -DCMC_TEST_COLOR
|
||||
./main.exe
|
||||
|
||||
treemap: $(UNIT)/treemap.c $(INCLUDE)/cmc/treemap.h
|
||||
$(CC) $^ -o main.exe -I $(INCLUDE) -DCMC_TEST_MAIN -DCMC_TEST_COLOR
|
||||
./main.exe
|
||||
|
||||
treeset: $(UNIT)/treeset.c $(INCLUDE)/cmc/treeset.h
|
||||
$(CC) $^ -o main.exe -I $(INCLUDE) -DCMC_TEST_MAIN -DCMC_TEST_COLOR
|
||||
./main.exe
|
||||
|
||||
FORCE:
|
||||
@@ -1,3 +0,0 @@
|
||||
# main
|
||||
|
||||
This folder hosts the main tests for the C Macro Collections Library.
|
||||
Loaded 100 of 142 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user