58 Commits
Author SHA1 Message Date
Leonardo de744f5822 v1.7.2 2019-10-18 11:15:52 -03:00
Leonardo 5583ca38b3 Changed default_type functions to compound literals 2019-10-17 01:37:55 -03:00
Leonardo 2d3b441d74 Added resize to multimap, multiset and sortedlist 2019-10-16 21:34:30 -03:00
Leonardo 99cd01ba1e Added intervalheap resize 2019-10-15 23:52:09 -03:00
Leonardo 1f11b6d2da Added preview of bidimap 2019-10-14 22:37:39 -03:00
Leonardo e41fe14502 Refactoring multiset code to be at most 100 characters per line 2019-10-12 00:27:38 -03:00
Leonardo 63d0453341 Finally releasing sortedlist 2019-10-11 02:14:33 -03:00
Leonardo 5e1a26b72e Added queue and stack resize 2019-10-10 15:10:37 -03:00
Leonardo e06e795ed8 hashmap quickfix 2019-10-09 00:53:40 -03:00
Leonardo b9b507bf07 Added heap and list resize function and refactored some tests and added some more 2019-10-08 13:57:58 -03:00
Leonardo 9f8671f75f Added resize function to hashmap and hashset 2019-10-07 19:57:20 -03:00
Leonardo f0b7b125b9 Added deque.h resize and added more deque and hashmap tests 2019-10-05 00:31:29 -03:00
Leonardo 8483eda701 Added two working examples, hanoi and printer 2019-10-04 01:19:18 -03:00
Leonardo b870649627 Refactoring tests 2019-10-03 11:29:35 -03:00
Leonardo 93ac623ffe Update README and benchmark 2019-10-02 00:11:08 -03:00
Leonardo 5997302a8c Fixed deque and queue bug and added more tests 2019-10-01 00:48:09 -03:00
Leonardo f52a9ff702 Refactoring tests and added sortedlist test 2019-09-30 18:27:19 -03:00
Leonardo 376c0ad4e7 Minor optimization to list.h and added finished more TODOs from sortedlist.h 2019-09-30 18:26:31 -03:00
Leonardo 34e649d82a Removed all conditional IO 2019-09-29 15:49:10 -03:00
Leonardo bfb8426183 Fixing travis 2019-09-28 15:01:02 -03:00
Leonardo 4f755f0915 Redone tests
./codecov is a stalled version for code coverage. It will be merged with main when the library is done with breaking changes
2019-09-28 14:58:10 -03:00
Leonardo dea77b5ca2 A minor fix to intervalheap.h 2019-09-27 00:06:26 -03:00
Leonardo b300c889f3 Added cmc prefix to timer 2019-09-27 00:05:22 -03:00
Leonardo 2126da3f25 Removed unnecessary typedefs for log.h and test.h and fixed the latter 2019-09-26 01:17:18 -03:00
Leonardo fb7854ef5d Update assert.h and removed
Added 3 new assertion macros:

cmc_assert_array_equals_any
cmc_assert_array_within_any
cmc_assert_array_outside_any
cmc_assert_array_sorted_any (renamed)
2019-09-25 16:41:40 -03:00
Leonardo 1ff3142769 Update assert.h
Renamed the parameters to and from to to_index and from_index
2019-09-24 23:35:00 -03:00
Leonardo 331fb32b73 Small additions and fixes to sortedlist 2019-09-23 22:34:23 -03:00
Leonardo Vencovsky fa03379580 Merge pull request #5 from LeoVen/dev
v1.7.1 fast forward master
2019-09-22 01:20:01 -03:00
Leonardo 43f4ae9f16 v1.7.1 2019-09-21 19:19:36 -03:00
Leonardo d9171a11cf Fixed some include guards for cmc_hashtable_primes and cmc_entry_state
Also removed unnecessary typedef for enum cmc_entry_state
Now cmc_entry state is in another guard, separated from the cmc_hashtable_primes guard
2019-09-21 18:25:01 -03:00
Leonardo 344e9f77fe Renamed list and linkedlist functions
push - push_at
pop - pop_at

The list prepend, append and insert - seq_push_front, seq_push_back, seq_push_at
2019-09-21 00:37:56 -03:00
Leonardo 2c84c35264 Adding sortedlist skeleton
Some functions are already working but there is still too much to be optimized
2019-09-18 02:29:11 -03:00
Leonardo c27edd53f6 Added cmc_assert_sorted 2019-09-18 02:28:20 -03:00
Leonardo a0db76b50d Update README.md
Trying to fix the shield's icon
2019-09-17 12:00:40 -03:00
Leonardo bb3efd75ff Update README and TODO 2019-09-17 00:37:12 -03:00
Leonardo 3d7e218195 Move the string format to each collection files and quick fix on deque
Now the format to print them is only declared if you actually include the header
2019-09-16 23:50:06 -03:00
Leonardo 191c47fc7c v1.7.0 2019-09-16 14:47:54 -03:00
Leonardo f2f806612f Moving documentation to the docs folder 2019-09-16 14:47:42 -03:00
Leonardo 5e2e001265 Merge branch 'master' of https://github.com/LeoVen/C-Macro-Containers 2019-09-16 14:45:45 -03:00
Leonardo 2ca2210a77 Added CMC prefix to all macros and removed FMOD 2019-09-16 14:45:24 -03:00
Leonardo Vencovsky 747aa8cb4e Merge pull request #4 from LeoVen/dev
Merge pull request #2 from LeoVen/master
2019-09-16 14:35:55 -03:00
Leonardo 4fe4e96811 v1.6.3 2019-09-14 00:38:45 -03:00
Leonardo 0df0ebbdeb Update TODO, quick fixes in a makefile and in assert.h 2019-09-14 00:38:13 -03:00
Leonardo e834aaee81 Added iter_advance, iter_rewind and iter_go_to to all collections
Also reworked many iterator functions that could cause strange behavior
2019-09-13 18:46:00 -03:00
Leonardo 1928fdd6d5 Reworked assert.h and test.h and added the cmc prefix to the logging utility
Integrated the assert utility with the test utility. Now any assertion that fails inside the unit test will trigger failure and is no longer needed to manually pass or fail a test.
Also reworked makefiles.
2019-09-06 12:17:11 -03:00
Leonardo abdbfa2018 v1.6.2 2019-09-05 01:48:51 -03:00
Leonardo a1a940399a Unified _set and _update functions
Also _remove now accepts an optional parameter if to retrieve or not the removed value. _update also has the same optional parameter that retrieves the old value.
The multimap will allocate an array based on the amount of keys and add all the values to that array.
2019-09-05 01:33:54 -03:00
Leonardo 855e085996 Fixed benchmark 2019-09-05 01:09:06 -03:00
Leonardo e95379bdd7 Updated tests 2019-09-03 17:07:34 -03:00
Leonardo 762b95db26 Some fixes and improvements to hashmap, hashset and multimap 2019-09-03 17:07:15 -03:00
Leonardo 396066f289 Update README.md 2019-09-03 16:54:21 -03:00
Leonardo f070d274f4 Added _equals function to all collections and fixed some issues with multimap 2019-08-29 23:25:32 -03:00
Leonardo 1f50add1bb Added _copy_of functions to all collections 2019-08-28 16:34:15 -03:00
Leonardo e68b8a8e0e Fixing main unit test 2019-08-27 01:38:34 -03:00
Leonardo 5ee7bfa23a v1.6.1 2019-08-27 01:36:06 -03:00
Leonardo 8ec768d30e removed linkedqueue and now _free and _clear have a deallocator parameter 2019-08-27 01:33:58 -03:00
Leonardo Vencovsky 35d27ffb39 Merge pull request #2 from LeoVen/master
Fast forward dev
2019-08-08 15:43:04 -03:00
Leonardo 613392ae76 Changed how _update works and added _set
_update: retrieves old value
_set: ignores old value
2019-08-05 23:28:12 -03:00
90 changed files with 18522 additions and 11193 deletions

No files matched your search

+3 -4
View File
@@ -12,9 +12,8 @@ addons:
script:
- sudo ln -s /usr/bin/gcc-6 /usr/local/bin/gcc
- export CC=gcc-7
- cd ./tests
- make --always-make
- cd ./main
- make --always-make
- make -C ./tests/
- make -C ./tests/main/
- make -C ./tests/codecov/
after_success:
- bash <(curl -s https://codecov.io/bash)
+42
View File
@@ -1,5 +1,47 @@
# RELEASE.MAJOR.MINOR
1.7.2
- Added resize function to array based collections
- Added the following functions to hashtable based collections:
- load
- full
- Added more assert macros utility
- Added plenty more tests
- Substituted impl_default_value / key by compound literals
- Removed unnecessary conditional input and output functions
- Minor fixes throughout the library
1.7.1
- Added new assert macro cmc_assert_sorted
- Fixed some include guards for hashtables
- Moved the cmc string format to each file
- Renamed some list functions (sequence input/output)
- Renamed list and linkedlist functions push and pop to push_at and pop_at
1.7.0
- Removed FMOD (function modifier)
- Added CMC prefix to all macros defined within the library
1.6.3
- Added iterator functions to all collections:
- iter_advance
- iter_rewind
- iter_go_to
- Added cmc prefix to the logging utility
- Integrated the assert utility with the test utility. Now any assertion that fails inside the unit test will trigger failure and is no longer needed to manually pass or fail tests.
1.6.2
Added new functions to all collections:
- copy_of
- equals
Added the new collections to the tests
Fixed some collections and some improvements to the hashtables
Unified the functions set and update from the map implementations
1.6.1
Removed ./ext/linkedqueue.h
Added a deallocator parameter to all _free and _clear functions
1.6.0
Added ./ext/intervalheap.h
Added ./ext/multimap.h
+82 -54
View File
@@ -1,11 +1,31 @@
# C-Macro-Collections
# C Macro Collections
Generate Simple Data Structures of any type in C for you to use in your projects.
<p align="center">
<img src="https://leoven.github.io/C-Macro-Collections/images/logo.png" alt="C Macro Collections Logo" width="300"/>
</p>
![License](https://img.shields.io/badge/License-MIT-blue.svg)
![Version](https://img.shields.io/badge/Version-v1.6.0-orange.svg)
[![Build](https://travis-ci.org/LeoVen/C-Macro-Collections.svg?branch=master)](https://travis-ci.org/LeoVen/C-Macro-Collections)
[![codecov](https://codecov.io/gh/LeoVen/C-Macro-Collections/branch/master/graph/badge.svg)](https://codecov.io/gh/LeoVen/C-Macro-Collections)
<p align="center">Header only, macro generated, generic and type-safe Collections in C.</p>
<p align="center">
<a href="https://github.com/LeoVen/C-Macro-Collections"><img src="https://img.shields.io/badge/GitHub-C%20Macro%20Collections-lightgrey.svg?logo=github" alt="LinkToRepo"/></a>
<a href="https://leoven.github.io/C-Macro-Collections/"><img style="color: #ffffff;" src="https://img.shields.io/badge/Read%20the%20Docs-5A5A5A.svg?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHN0eWxlPSIiPjxyZWN0IGlkPSJiYWNrZ3JvdW5kcmVjdCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgeD0iMCIgeT0iMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJub25lIi8%2BPHRpdGxlPmljbi9kb2MtdGV4dDwvdGl0bGU%2BPGcgY2xhc3M9ImN1cnJlbnRMYXllciIgc3R5bGU9IiI%2BPHRpdGxlPkxheWVyIDE8L3RpdGxlPjxwYXRoIGQ9Ik01IDFoNC4yNDRhMiAyIDAgMCAxIDEuNDM0LjYwNmwyLjc1NiAyLjgzNEEyIDIgMCAwIDEgMTQgNS44MzVWMTJhMyAzIDAgMCAxLTMgM0g1YTMgMyAwIDAgMS0zLTNWNGEzIDMgMCAwIDEgMy0zem0wIDJhMSAxIDAgMCAwLTEgMXY4YTEgMSAwIDAgMCAxIDFoNmExIDEgMCAwIDAgMS0xVjUuODM1TDkuMjQ0IDNINXptMS41IDdoM2EuNS41IDAgMSAxIDAgMWgtM2EuNS41IDAgMSAxIDAtMXptMC0yaDJhLjUuNSAwIDAgMSAwIDFoLTJhLjUuNSAwIDAgMSAwLTF6TTggMmwzIDEuOTk1TDEzIDdIOWExIDEgMCAwIDEtMS0xVjJ6IiBpZD0iYSIgY2xhc3M9IiIgZmlsbD0iI2ZmZmZmZiIgZmlsbC1vcGFjaXR5PSIxIi8%2BPC9nPjwvc3ZnPg%3D%3D" alt="LinkToDocs"/></a>
</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>
<a href="#"><img src="https://img.shields.io/badge/Version-v1.7.2-orange.svg" alt="Version"/></a>
<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>
</p>
## Table of Contents
* Project Structure
* Available Collections
* Overall To-Do
* Design Decisions
* What to use
* How to use
## Project Structure
@@ -15,38 +35,51 @@ Generate Simple Data Structures of any type in C for you to use in your projects
* __cmc__ - The main C Macro Collections Library
* __dev__ - The main C Macro Collections Library for development (containing logging)
* __ext__ - Extra collections
* __sac__ - Stack Allocated Collections
* __sac__ - Statically Allocated Collections
* __utl__ - Utility like ForEach macros, logging, etc
* __macro\_collections.h__ - Master header containing all collections and utilities
* __tests__ - Where all tests are hosted
Only Collections located in __cmc__ are to be documented at *Documentation.md*.
## Available Collections
* Main C Macro Collections Library
* Deque
* HashMap
* HashSet
* Heap
* LinkedList
* List
* Queue
* Stack
* TreeMap
* TreeSet
* Extra Collections Library
* IntervalHeap
* LinkedQueue
* MultiMap
* MultiSet
* Stack Allocated Collections Library
* Queue
* Stack
* Development Collections Library
* Deque
* Linear Collections
* List, LinkedList, Deque, Stack, Queue
* Sets
* HashSet, TreeSet, MultiSet
* Maps
* HashMap, TreeMap, MultiMap
* Heaps
* Heap, IntervalHeap
* Coming Soon
* BidiMap, SortedList
Check out **Documentation.md** for more information about each collection.
| Collection <img width=250/> | Abstract Data Type <img width=250/> | Data Structure <img width=250/> | Details |
| :--------------------------------: | :---------------------------------: | :-----------------------------: | :-----------------------------------: |
| BidiMap <br> _bidimap.h_ | Bidirectional Map | Two Hashtables | A bijection between two sets of unique keys and unique values `K <-> V` using two hashtables |
| 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 |
| HashMap <br> _hashmap.h_ | Map | 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 |
| HashSet <br> _hashset.h_ | Set | 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 |
| MultiMap <br> _multimap.h_ | Multimap | Custom Hashtable | A mapping of multiple keys with one node per key using a hashtable with separate chaining |
| Multiset <br> _multiset.h_ | Multiset | Hashtable | A mapping of a value and its multiplicity using a hashtable with open addressing and robin hood hashing |
| 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 |
| 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 |
| 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 |
## 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 (all those included in `cmc` and `ext`);
* Reorganize and complete all tests for `cmc` and `ext`;
* 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`.
## Design Decisions
@@ -101,36 +134,31 @@ Every collection is separated by two parts:
All collections have three main macros:
* `SNAME_GENERATE` - Generates `SNAME_GENERATE_HEADER` and `SNAME_GENERATE_SOURCE`.
* `CMC_GENERATE_SNAME` - Generates `CMC_GENERATE_SNAME_HEADER` and `CMC_GENERATE_SNAME_SOURCE`.
Or you can generate each part individually:
* `SNAME_GENERATE_HEADER` - Generates all struct definitions and function definitions.
* `SNAME_GENERATE_SOURCE` - Generates all function implementations.
* `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 (*LIST*, *LINKEDLIST*, *STACK*, *QUEUE*, *DEQUE*, *HEAP*, *TREESET*, *TREEMAP*, *HASHSET*, *HASHMAP*).
* __PFX__ - Functions prefix or namespace.
* __SNAME__ - Structure name (`typedef struct SNAME##_s 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:
* `FOR_EACH` - Starts at the start of the collection towards the end.
* `FOR_EACH_REV` - Starts at the end of the collection towards the start.
Check out the **Documentation.md** to know exactly what represents the *end* and the *start* of each collection.
### Parameters
When including `macro_collections.h` in your source code you gain access to a macro called `COLLECTION_GENERATE` with the following parameters:
* __C__ - Container name in uppercase (*LIST*, *LINKEDLIST*, *STACK*, *QUEUE*, *DEQUE*, *HEAP*, *TREESET*, *TREEMAP*, *HASHSET*, *HASHMAP*).
* __PFX__ - Functions prefix or namespace.
* __SNAME__ - Structure name (`typedef struct SNAME##_s SNAME`).
* __FMOD__ - Function modifier (`static` or empty).
* \*__K__ - Key type. Only used in *HASHMAP* and *TREEMAP*; ignored by others.
* __V__ - Value type. Primary type for most collections, or value to be mapped by *HASHMAP* and *TREEMAP*.
\* Required only by *HASHMAP* and *TREEMAP*
**In fact, all macros follow this pattern.** So whenever you see a macro with a bunch of parameters and you don't know what they are, you can check out the above list.
* `CMC_FOR_EACH` - Starts at the start of the collection towards the end.
* `CMC_FOR_EACH_REV` - Starts at the end of the collection towards the start.
When including `foreach.h` in your source code you gain access to all for-each macros with the following parameters:
@@ -139,7 +167,7 @@ When including `foreach.h` in your source code you gain access to all for-each m
* __TARGET__ - The variable name of the collection you wish to iterate over.
* __BODY__ - Block of code.
Inside body you will have access to the iterator variable. With it you can use functions to access the key, value or index from the iterator. Checkout the documentation for more details.
Inside body you will have access to the iterator variable `iter`. With it you can use functions to access the key, value or index from the iterator. Checkout the documentation for more details.
<hr>
+26 -30
View File
@@ -5,43 +5,34 @@ TODO
[~] - Needs to be reviewed
[/] Documentation
[/] Tests
[X] Remove PUBLIC and PRIVATE
[ ] Extra Collections
[X] Extra Collections
[X] Add MultiSet
[X] Add MultiMap
[X] Add IntervalHeap
[ ] Add TreeHashMap
[ ] Add functions
[/] Add SortedList
[/] Add BiDiMap
[/] Add functions
[X] update {hashmap, treemap, multimap}
[/] to_string {all}
[ ] iter_advance {all} (iterators)
[ ] iter_rewind {all} (iterators)
[ ] iter_go_to {all} (iterators)
[X] set {hashmap, treemap, multimap}
[X] to_string {all}
[X] iter_advance {all} (iterators)
[X] iter_rewind {all} (iterators)
[X] iter_go_to {all} (iterators)
[ ] from_array {all}
[ ] to_array {all}
[ ] equals {all}
[ ] resize {dynamic arrays and circular buffers}
[ ] dispose {all}
[ ] copy_of {all}
[ ] save {all} (serialization)
[ ] load {all} (serialization)
[ ] read {all} (serialization)
[ ] write {all} (serialization)
[ ] Range IO
[ ] Sequences
[ ] seq_push_front
[ ] seq_push_at
[ ] seq_push_back
[ ] seq_remove
[ ] seq_extract
[ ] Others
[ ] seq_insert
[ ] seq_remove (attention on how to treat this)
[ ] seq_extract (attention on how to treat this)
[ ] Iterator IO
[ ] range_insert
[ ] range_remove
[ ] Stack Allocated Collections
[X] equals {all}
[X] copy_of {all}
[X] resize {array based collections}
[ ] Serialization
[ ] save {all}
[ ] load {all}
[ ] serialize {all}
[ ] deserialize {all}
[ ] Callback utility
[ ] Zip Iterators
[ ] Statically Allocated Collections
[ ] Deque
[ ] HashMap
[ ] HashSet
@@ -69,3 +60,8 @@ TODO
[X] log.h
[X] test.h
[X] timer.h
[ ] Optimizations
[ ] Hashtable insertion can avoid a call to impl_get_entry to check if a key already exists
[ ] Use binary search to find optimum hashtable prime size inside impl_calculate_size
+39 -29
View File
@@ -59,20 +59,20 @@ void shuffle(int *array, mt_state_ptr st)
}
}
COLLECTION_GENERATE(DEQUE, d, deque, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(HASHMAP, hm, hmap, /* FMOD */, int, int)
COLLECTION_GENERATE(HASHSET, hs, hset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(HEAP, h, heap, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(LINKEDLIST, ll, linked, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(LIST, l, list, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(QUEUE, q, queue, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(STACK, s, stack, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(TREEMAP, tm, tmap, /* FMOD */, int, int)
COLLECTION_GENERATE(TREESET, ts, tset, /* FMOD */, /* K */, int)
CMC_COLLECTION_GENERATE(DEQUE, d, deque, /* K */, int)
CMC_COLLECTION_GENERATE(HASHMAP, hm, hmap, int, int)
CMC_COLLECTION_GENERATE(HASHSET, hs, hset, /* K */, int)
CMC_COLLECTION_GENERATE(HEAP, h, heap, /* K */, int)
CMC_COLLECTION_GENERATE(LINKEDLIST, ll, linked, /* K */, int)
CMC_COLLECTION_GENERATE(LIST, l, list, /* K */, int)
CMC_COLLECTION_GENERATE(QUEUE, q, queue, /* K */, int)
CMC_COLLECTION_GENERATE(STACK, s, stack, /* K */, int)
CMC_COLLECTION_GENERATE(TREEMAP, tm, tmap, int, int)
CMC_COLLECTION_GENERATE(TREESET, ts, tset, /* K */, int)
COLLECTION_GENERATE(INTERVALHEAP, ih, iheap, , , int)
COLLECTION_GENERATE(MULTIMAP, mm, mmap, /* FMOD */, int, int)
COLLECTION_GENERATE(MULTISET, ms, mset, /* FMOD */, /* K */, int)
CMC_COLLECTION_GENERATE(INTERVALHEAP, ih, iheap, /* k */, int)
CMC_COLLECTION_GENERATE(MULTIMAP, mm, mmap, int, int)
CMC_COLLECTION_GENERATE(MULTISET, ms, mset, /* K */, int)
#define BENCHMARK(NAME, PFX, sname, initfunc, insertbody, removebody, searchbody) \
void NAME##_io_benchmark(int *array, int *sarray, size_t s) \
@@ -85,17 +85,17 @@ COLLECTION_GENERATE(MULTISET, ms, mset, /* FMOD */, /* K */, int)
\
sname *coll = initfunc; \
\
timer_start(total); \
timer_start(timer); \
cmc_timer_start(total); \
cmc_timer_start(timer); \
\
for (size_t i = 0; i < NTOTAL; i++) \
{ \
insertbody; \
} \
\
timer_stop(timer); \
cmc_timer_stop(timer); \
\
timer_calc(timer); \
cmc_timer_calc(timer); \
\
size_t s1 = PFX##_count(coll); \
\
@@ -103,16 +103,16 @@ COLLECTION_GENERATE(MULTISET, ms, mset, /* FMOD */, /* K */, int)
\
double input_time = timer.result; \
\
timer_start(timer); \
cmc_timer_start(timer); \
\
for (size_t i = 0; i < s; i++) \
{ \
searchbody; \
} \
\
timer_stop(timer); \
cmc_timer_stop(timer); \
\
timer_calc(timer); \
cmc_timer_calc(timer); \
\
printf(" SEARCH %10s TOOK %8.0lf milliseconds for %8" PRIuMAX " elements\n", #NAME, timer.result, s); \
\
@@ -120,30 +120,30 @@ COLLECTION_GENERATE(MULTISET, ms, mset, /* FMOD */, /* K */, int)
\
sname##_iter iter; \
\
timer_start(timer); \
cmc_timer_start(timer); \
\
for (PFX##_iter_init(&iter, coll); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
{ \
} \
\
timer_stop(timer); \
cmc_timer_stop(timer); \
\
timer_calc(timer); \
cmc_timer_calc(timer); \
\
printf("ITERATION %10s TOOK %8.0lf milliseconds for %8" PRIuMAX " elements\n", #NAME, timer.result, s1); \
\
double iter_time = timer.result; \
\
timer_start(timer); \
cmc_timer_start(timer); \
\
for (size_t i = 0; i < NTOTAL; i++) \
{ \
removebody; \
} \
\
timer_stop(timer); \
cmc_timer_stop(timer); \
\
timer_calc(timer); \
cmc_timer_calc(timer); \
\
size_t s2 = PFX##_count(coll); \
\
@@ -151,10 +151,10 @@ COLLECTION_GENERATE(MULTISET, ms, mset, /* FMOD */, /* K */, int)
\
double output_time = timer.result; \
\
timer_stop(total); \
timer_calc(total); \
cmc_timer_stop(total); \
cmc_timer_calc(total); \
\
PFX##_free(coll); \
PFX##_free(coll, NULL); \
\
double adj_search_time = (total.result - search_time) + (search_time * (double)NTOTAL) / (double)s; \
double no_search = input_time + iter_time + output_time; \
@@ -221,6 +221,9 @@ int main(void)
// Linear containers have to search for NMIN elements and non-linear (hash
// and tree) have to search for all elements.
cmc_timer timer;
cmc_timer_start(timer);
DEQUE_io_benchmark(array, sarray, NMIN);
HASHMAP_io_benchmark(array, sarray, NTOTAL);
HASHSET_io_benchmark(array, sarray, NTOTAL);
@@ -236,6 +239,13 @@ int main(void)
MULTIMAP_io_benchmark(array, array, NTOTAL);
MULTISET_io_benchmark(array, array, NTOTAL);
cmc_timer_stop(timer);
cmc_timer_calc(timer);
printf("+-----------------------------------------------------------+ \n");
printf("| Total Benchmark Running Time : %12.0lf seconds | \n", timer.result / 1000);
printf("+-----------------------------------------------------------+ \n");
free(array);
free(sarray);
@@ -1,3 +1,5 @@
__Check out the new documentation at__ https://leoven.github.io/C-Macro-Collections/
<span id="collections_index"> Collections Documentation </span>
* [Deque](#Deque)
+247
View File
@@ -0,0 +1,247 @@
THIS IS A SAFE COPY OF THE MARKDOWN FOR THE DOCUMENTATION LOCATED AT https://leoven.github.io/C-Macro-Collections/
---
title: CMC Documentation
toc_footers:
- <a href='https://github.com/lord/slate'>Documentation Powered by Slate</a>
language_tabs:
- C
search: true
---
# Introduction
[![github](https://img.shields.io/badge/GitHub-C%20Macro%20Collections-lightgrey.svg?logo=github)](https://github.com/LeoVen/C-Macro-Collections)
![License](https://img.shields.io/badge/License-MIT-blue.svg)
![Version](https://img.shields.io/badge/Version-v1.6.2-orange.svg)
[![Build](https://travis-ci.org/LeoVen/C-Macro-Collections.svg?branch=master)](https://travis-ci.org/LeoVen/C-Macro-Collections)
[![codecov](https://codecov.io/gh/LeoVen/C-Macro-Collections/branch/master/graph/badge.svg)](https://codecov.io/gh/LeoVen/C-Macro-Collections)
The C Macro Collections Library is a compilation of macros that can be used to generate common data structures for any desired type. These data structures are [type safe](https://en.wikipedia.org/wiki/Type_safety).
The documentation is currently being written in hopes that in the future it can be used to help you get to know better this amazing C library.
## Why this library
C is a low level language and lacks all the data structures that we commonly use. Many high level languages already come with these collections so that we don't have to implement everything ourselves. This is why the C Macro Collections Library was created.
The library currently provides many data structures, such as:
* Linear Collections
* List, LinkedList, Deque, Stack, Queue
* Sets
* HashSet, TreeSet, MultiSet
* Maps
* HashMap, TreeMap, MultiMap
* Heaps
* Heap, IntervalHeap
All with the following features:
* __Type-safe__ - No `void *` pointers are used. A collection of type `int` will only accept integers;
* __Customization__ - Custom struct name and function namespace;
* __Bidirectional Iterators__ - Full support for iterators;
* __Nesting__ - Collections can be nested (List of Lists, HashSet of Stacks, etc).
## Library Structure
The `src` folder is subdivided in 5 other folders and one file:
> The `dev` folder is an exact copy of `cmc` but it is filled with logging information regarding the code execution and debugging.
> The `sac` library contains fixed-length collections with an internal C array.
* __cmc__ - The main C Macro Collections Library
* __dev__ - The main C Macro Collections Library for development
* __ext__ - Extra collections
* __sac__ - Statically Allocated Collections
* __utl__ - Utility like ForEach macros, logging, etc
* __macro\_collections.h__ - Master header containing all collections and utilities
## How to install
> Include header files like this
```c
#include <cmc/list.h>
#include <dev/deque.h>
#include <utl/assert.h>
```
> Not like this
```c
#include <list.h>
#include <deque.h> // dev or cmc?
#include <assert.h> // this will import from the standard library
```
No installation is required. All you have to do is include the appropriate header files, generate any collections that you desire and then compile your program. It is recommended that you include the headers relative to the `src` folder and include it with `-I path/to/library/src` as shown in the following example.
The library has no external dependencies other than the C standard library.
## Minimal Example
Lets create a list of type `int`, add some elements to it and get the sum of all the elements printed on the screen.
### Include headers
```c
#include <cmc/list.h>
```
First you need to include only the necessary headers. It is not recommended that you include everything with `macro_collections.h`, only in cases where you might be using almost all features from the library.
### Generating a list
```c
// CMC_GENERATE_LIST(PFX, SNAME, V)
CMC_GENERATE_LIST(il, int_list, int)
```
The List is also known as `vector`, `ArrayList` and dynamic array. In fact the latter is the best description for this collection. It is a dynamic array that can grow and shrink as needed. To generate it we can simply call the macro `CMC_GENERATE_LIST` after our includes. It has three parameters:
| Parameter name | Purpose |
| :------------: | ------- |
| __PFX__ | Functions prefix (namespace) |
| __SNAME__ | Struct name |
| __V__ | The list value type (can be any valid data type) |
<aside class="notice">
All collections can be generated by using the macro CMC_GENERATE_ and then the name of the include (in this case list.h) but in uppercase without the `.h`.
</aside>
### Initializing and adding elements
```c
// Allocate an int_list with an initial capacity of 100
int_list *list = il_new(100);
// Adding elements to the back of the list
for (int i = 0; i <= 1000; i++)
{
if (!il_push_back(list, i))
{
// Something went wrong (check out documentation)
}
}
```
To initialize any collection we call a function `_new`. Since the `PFX` parameter is set to `il` all functions related to our list of integer will be prefixed by `il`, so `_new` becomes `il_new`.
The list name is `int_list` as defined by `SNAME`. This type is a typedef like:
`typedef struct SNAME##_s SNAME;`
Which expands to:
`typedef struct int_list_s int_list`
To add elements to the back of a list we can use `il_push_back`. This function will first check if the list has enough space for a new element. If not, reallocate the internal buffer with doubled size and then add the new element.
### Iteration
> It is recommended that the iterator is allocated on the stack
```c
// Resulting sum will be stored here
int sum = 0;
// Declare our iterator (allocating it on the stack)
int_list_iter it;
// Loop for each element
for (il_iter_init(&it, list); !il_iter_end(&it); il_iter_next(&it))
{
// Accessing the value
int elem = il_iter_value(&it);
sum += elem;
}
printf("%d\n", sum);
```
There are 6 (2 optional) steps to iterate over the elements of any collection:
| Step | Description | Function |
| :--: | ----------- | -------- |
| 1 | Allocate the iterator (optional) | `il_iter_new` |
| 2 | Initialize the iterator given a target list | `il_iter_init` |
| 3 | Access the iterator's elements (value, index, etc) | `il_iter_value` |
| 4 | Go to the next element | `il_iter_next` |
| 5 | Check if we haven't reached the end of the list | `il_iter_end` |
| 6 | Free the iterator if it was allocated on the heap | `il_iter_free` |
Note that all iterator functions are prefixed by the user defined prefix and then by `iter` (`il + iter = il_iter`). Also, the steps __1__ and __6__ are optional so `il_iter_new` and `il_iter_free` are not used in the example.
By the end of the example we have the variable `sum` with the sum of all integers inside our list. We can then print it and this example is almost done.
### Freeing resources
```c
// void il_free(int_list *_list_, void(*deallocator)(int))
il_free(list, NULL);
```
The list is currently allocated in memory. To deallocate it we call `il_free`. This function takes a pointer to the allocated list and a pointer to a `deallocator` function that will be responsible for deallocating each element in the list. This last parameter is optional and we won't be using it since our data type `int` is not allocated in the heap. This optional parameter can be set to `NULL` to be ignored by the `il_free` function.
### Compile and run
> source.c
```c
#include <cmc/list.h>
CMC_GENERATE_LIST(il, int_list, int)
int main(void)
{
int_list *list = il_new(100);
for (int i = 0; i <= 1000; i++)
{
if (!il_push_back(list, i))
{
// Something went wrong (check out documentation)
}
}
int sum = 0;
int_list_iter it;
for (il_iter_init(&it, list); !il_iter_end(&it); il_iter_next(&it))
{
int elem = il_iter_value(&it);
sum += elem;
}
printf("%d\n", sum);
il_free(list, NULL);
}
```
If the source file is `source.c`, all you have to do is to include the `src` folder to the include path and compile. The following example uses `gcc`:
`gcc source.c -I path/to/library/src`
### Conclusion
The C Macro Collections Library is prepared to accept any data type and is highly customizable. It is also very easy to integrate and no previous compilation is required. The library also comes with many utilities in the `utl` folder that are designed to work well with all collections.
# Upcoming
This documentation is still being written. Here is some of the things you will be able to find here:
* Full explanation about data structures
* Full documentation about all current collections and others to come
* Fully explained examples
* Benchmark examples
+73
View File
@@ -0,0 +1,73 @@
#include <cmc/stack.h>
#include <utl/log.h>
CMC_GENERATE_STACK(stk, stack, int)
struct
{
stack *from;
stack *aux;
stack *to;
} print_aux = {NULL};
void print_stacks()
{
for (int i = 9; i >= 0; i--)
{
int ia = print_aux.from->buffer[i];
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("+---+---+---+\n\n");
}
void move(stack *from, stack *to)
{
stk_push(to, stk_top(from));
stk_pop(from);
}
void hanoi(int n, stack *from, stack *aux, stack *to)
{
if (n == 0)
return;
hanoi(n - 1, from, to, aux);
move(from, to);
print_stacks();
hanoi(n - 1, aux, from, to);
}
int main(int argc, char const *argv[])
{
stack *from = stk_new(10);
stack *to = stk_new(10);
stack *aux = stk_new(10);
for (int i = 4; i >= 1; i--)
stk_push(from, i);
print_aux.from = from;
print_aux.aux = aux;
print_aux.to = to;
print_stacks();
hanoi(stk_count(from), from, aux, to);
stk_free(from, NULL);
stk_free(to, NULL);
stk_free(aux, NULL);
return 0;
}
+208
View File
@@ -0,0 +1,208 @@
#include <cmc/list.h>
#include <utl/log.h>
#define TAB_SIZE 4
#define ROW_INI_CAP DOC_LETTERS_IN_ROW
#define DOC_LETTERS_IN_ROW 100
#define DOC_ROWS_IN_PAGE 50
#define DOC_MARGIN 4
CMC_GENERATE_LIST(row, row, char)
CMC_GENERATE_LIST(doc, document, row *)
void row_deallocator(row *r)
{
row_free(r, NULL);
}
document *document_load(const char *file_name);
void document_empty_line(FILE *fptr);
void document_page_outline(FILE *fptr, int outline);
void document_page_margin(FILE *fptr, int margin);
void document_print(document *doc, FILE *fptr);
document *document_load(const char *file_name)
{
FILE *file = fopen(file_name, "r");
if (!file)
{
cmc_log_error("File %s not found\n", file_name);
return NULL;
}
row *initial_row = row_new(ROW_INI_CAP);
document *doc = doc_new(100);
doc_push_back(doc, initial_row);
int ch;
while ((ch = getc(file)) != EOF)
{
char c = (char)ch;
row *current_row = doc_back(doc);
if (c == '\n')
{
row *new_row = row_new(ROW_INI_CAP);
doc_push_back(doc, new_row);
}
else if (c == '\t')
{
intmax_t left = TAB_SIZE;
while (left > 0 && row_count(current_row) < DOC_LETTERS_IN_ROW)
{
row_push_back(current_row, ' ');
left--;
}
if (left > 0)
{
row *new_row = row_new(ROW_INI_CAP);
doc_push_back(doc, new_row);
while (left > 0)
{
row_push_back(new_row, ' ');
left--;
}
}
}
else if (DOC_LETTERS_IN_ROW == row_count(current_row))
{
row *new_row = row_new(ROW_INI_CAP);
row_push_back(new_row, c);
doc_push_back(doc, new_row);
}
else
row_push_back(current_row, c);
}
return doc;
}
void document_empty_line(FILE *fptr)
{
fputs("|", fptr);
for (size_t i = 0; i < DOC_LETTERS_IN_ROW + DOC_MARGIN * 2; i++)
{
fputc(' ', fptr);
}
fputs("|\n", fptr);
}
void document_page_outline(FILE *fptr, int outline /* 0 - header, 1 - footer */)
{
if (outline == 1)
{
document_empty_line(fptr);
#ifdef DOC_PAGE_NUMBER
static intmax_t page = 1;
fputs("|", fptr);
for (size_t i = 0; i < (DOC_LETTERS_IN_ROW + DOC_MARGIN) - 8; i++)
{
fputc(' ', fptr);
}
fprintf(fptr, "%8" PRIdMAX "", page);
page++;
document_page_margin(fptr, 1);
document_empty_line(fptr);
#endif
}
fputs("+", fptr);
for (size_t i = 0; i < DOC_LETTERS_IN_ROW + DOC_MARGIN * 2; i++)
{
fputc('-', fptr);
}
fputs("+\n", fptr);
if (outline == 0)
document_empty_line(fptr);
}
void document_page_margin(FILE *fptr, int margin /* 0 - first margin, 1 - second margin */)
{
if (margin == 0)
fputs("|", fptr);
for (size_t i = 0; i < DOC_MARGIN; i++)
{
fputc(' ', fptr);
}
if (margin == 1)
fputs("|\n", fptr);
}
void document_print(document *doc, FILE *fptr)
{
fputc('\n', fptr);
intmax_t current_page_row = 0, total_rows = doc_count(doc);
// Print document
for (intmax_t i = 0; i < total_rows; i++, current_page_row++)
{
if (current_page_row == 0)
document_page_outline(fptr, 0);
row *current_row = doc_get(doc, i);
if (!current_row)
cmc_log_fatal("Unexpected NULL pointer for %s", "current_row");
document_page_margin(fptr, 0);
for (size_t k = 0; k < row_count(current_row); k++)
fputc(row_get(current_row, k), fptr);
// Trailing margin
for (size_t k = 0; k < DOC_LETTERS_IN_ROW - row_count(current_row); k++)
fputc(' ', fptr);
document_page_margin(fptr, 1);
// Print the end of the page and reset
if (current_page_row == DOC_ROWS_IN_PAGE - 1)
{
document_page_outline(fptr, 1);
current_page_row = -1;
fputc('\n', fptr);
}
}
// Print trailing page
if (total_rows % DOC_ROWS_IN_PAGE != 0)
{
for (size_t i = 0; i < DOC_ROWS_IN_PAGE - current_page_row; i++)
document_empty_line(fptr);
document_page_outline(fptr, 1);
}
fputc('\n', fptr);
}
int main(int argc, char const *argv[])
{
if (argc != 2)
{
cmc_log_error("Please define one argument only for %s", argv[0]);
return 1;
}
document *doc = document_load(argv[1]);
document_print(doc, stdout);
doc_free(doc, row_deallocator);
return 0;
}
+525 -410
View File
@@ -31,24 +31,28 @@
#ifndef CMC_DEQUE_H
#define CMC_DEQUE_H
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../utl/cmc_string.h"
#define DEQUE_GENERATE(PFX, SNAME, FMOD, V) \
DEQUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
DEQUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* to_string format */
static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRIuMAX ", count:%" PRIuMAX ", front:%" PRIuMAX ", back:%" PRIuMAX " }";
#define DEQUE_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \
DEQUE_GENERATE_HEADER(PFX, SNAME, FMOD, V)
#define CMC_GENERATE_DEQUE(PFX, SNAME, V) \
CMC_GENERATE_DEQUE_HEADER(PFX, SNAME, V) \
CMC_GENERATE_DEQUE_SOURCE(PFX, SNAME, V)
#define DEQUE_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \
DEQUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
#define CMC_WRAPGEN_DEQUE_HEADER(PFX, SNAME, K, V) \
CMC_GENERATE_DEQUE_HEADER(PFX, SNAME, V)
#define CMC_WRAPGEN_DEQUE_SOURCE(PFX, SNAME, K, V) \
CMC_GENERATE_DEQUE_SOURCE(PFX, SNAME, V)
/* HEADER ********************************************************************/
#define DEQUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
#define CMC_GENERATE_DEQUE_HEADER(PFX, SNAME, V) \
\
/* Deque Structure */ \
typedef struct SNAME##_s \
@@ -98,421 +102,532 @@
\
/* 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_); \
SNAME *PFX##_new(size_t capacity); \
void PFX##_clear(SNAME *_deque_, void (*deallocator)(V)); \
void PFX##_free(SNAME *_deque_, void (*deallocator)(V)); \
/* 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); \
bool PFX##_push_front(SNAME *_deque_, V element); \
bool PFX##_push_back(SNAME *_deque_, V element); \
bool PFX##_pop_front(SNAME *_deque_); \
bool PFX##_pop_back(SNAME *_deque_); \
/* Element Access */ \
FMOD V PFX##_front(SNAME *_deque_); \
FMOD V PFX##_back(SNAME *_deque_); \
V PFX##_front(SNAME *_deque_); \
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_); \
bool PFX##_contains(SNAME *_deque_, V element, int (*comparator)(V, V)); \
bool PFX##_empty(SNAME *_deque_); \
bool PFX##_full(SNAME *_deque_); \
size_t PFX##_count(SNAME *_deque_); \
size_t PFX##_capacity(SNAME *_deque_); \
/* Collection Utility */ \
FMOD cmc_string PFX##_to_string(SNAME *_deque_); \
bool PFX##_resize(SNAME *_deque_, size_t capacity); \
SNAME *PFX##_copy_of(SNAME *_deque_, V (*copy_func)(V)); \
bool PFX##_equals(SNAME *_deque1_, SNAME *_deque2_, int (*comparator)(V, V)); \
cmc_string PFX##_to_string(SNAME *_deque_); \
\
/* Iterator Functions */ \
/* Iterator Allocation and Deallocation */ \
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \
FMOD void PFX##_iter_free(SNAME##_iter *iter); \
SNAME##_iter *PFX##_iter_new(SNAME *target); \
void PFX##_iter_free(SNAME##_iter *iter); \
/* Iterator Initialization */ \
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \
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); \
bool PFX##_iter_start(SNAME##_iter *iter); \
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); \
void PFX##_iter_to_start(SNAME##_iter *iter); \
void PFX##_iter_to_end(SNAME##_iter *iter); \
bool PFX##_iter_next(SNAME##_iter *iter); \
bool PFX##_iter_prev(SNAME##_iter *iter); \
bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \
bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \
bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \
/* 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_; \
} \
V PFX##_iter_value(SNAME##_iter *iter); \
V *PFX##_iter_rvalue(SNAME##_iter *iter); \
size_t PFX##_iter_index(SNAME##_iter *iter); \
\
/* 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) \
return NULL; \
\
SNAME *_deque_ = malloc(sizeof(SNAME)); \
\
if (!_deque_) \
return NULL; \
\
_deque_->buffer = malloc(sizeof(V) * capacity); \
\
if (!_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; \
\
return _deque_; \
} \
\
FMOD void PFX##_clear(SNAME *_deque_) \
{ \
memset(_deque_->buffer, 0, sizeof(V) * _deque_->capacity); \
\
_deque_->count = 0; \
_deque_->front = 0; \
_deque_->back = 0; \
} \
\
FMOD void PFX##_free(SNAME *_deque_) \
{ \
free(_deque_->buffer); \
free(_deque_); \
} \
\
FMOD bool PFX##_push_front(SNAME *_deque_, V element) \
{ \
if (PFX##_full(_deque_)) \
{ \
if (!PFX##_impl_grow(_deque_)) \
return false; \
} \
\
_deque_->front = (_deque_->front == 0) ? _deque_->capacity - 1 : _deque_->front - 1; \
\
_deque_->buffer[_deque_->front] = element; \
\
_deque_->count++; \
\
return true; \
} \
\
FMOD bool PFX##_push_back(SNAME *_deque_, V element) \
{ \
if (PFX##_full(_deque_)) \
{ \
if (!PFX##_impl_grow(_deque_)) \
return false; \
} \
\
_deque_->buffer[_deque_->back] = element; \
\
_deque_->back = (_deque_->back == _deque_->capacity - 1) ? 0 : _deque_->back + 1; \
\
_deque_->count++; \
\
return true; \
} \
\
FMOD bool PFX##_pop_front(SNAME *_deque_) \
{ \
if (PFX##_empty(_deque_)) \
return false; \
\
_deque_->buffer[_deque_->front] = PFX##_impl_default_value(); \
\
_deque_->front = (_deque_->front == _deque_->capacity - 1) ? 0 : _deque_->front + 1; \
\
_deque_->count--; \
\
return true; \
} \
\
FMOD bool PFX##_pop_back(SNAME *_deque_) \
{ \
if (PFX##_empty(_deque_)) \
return false; \
\
_deque_->back = (_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1; \
\
_deque_->buffer[_deque_->back] = PFX##_impl_default_value(); \
\
_deque_->count--; \
\
return true; \
} \
\
FMOD bool PFX##_push_front_if(SNAME *_deque_, V element, bool condition) \
{ \
if (condition) \
return PFX##_push_front(_deque_, element); \
\
return false; \
} \
\
FMOD bool PFX##_push_back_if(SNAME *_deque_, V element, bool condition) \
{ \
if (condition) \
return PFX##_push_back(_deque_, element); \
\
return false; \
} \
\
FMOD bool PFX##_pop_front_if(SNAME *_deque_, bool condition) \
{ \
if (condition) \
return PFX##_pop_front(_deque_); \
\
return false; \
} \
\
FMOD bool PFX##_pop_back_if(SNAME *_deque_, bool condition) \
{ \
if (condition) \
return PFX##_pop_back(_deque_); \
\
return false; \
} \
\
FMOD V PFX##_front(SNAME *_deque_) \
{ \
if (PFX##_empty(_deque_)) \
return PFX##_impl_default_value(); \
\
return _deque_->buffer[_deque_->front]; \
} \
\
FMOD V PFX##_back(SNAME *_deque_) \
{ \
if (PFX##_empty(_deque_)) \
return PFX##_impl_default_value(); \
\
return _deque_->buffer[(_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1]; \
} \
\
FMOD bool PFX##_contains(SNAME *_deque_, V element, int (*comparator)(V, V)) \
{ \
for (size_t i = _deque_->front, j = 0; j < _deque_->count; i = (i + 1) % _deque_->count, j++) \
{ \
if (comparator(_deque_->buffer[i], element) == 0) \
return true; \
} \
\
return false; \
} \
\
FMOD bool PFX##_empty(SNAME *_deque_) \
{ \
return _deque_->count == 0; \
} \
\
FMOD bool PFX##_full(SNAME *_deque_) \
{ \
return _deque_->count >= _deque_->capacity; \
} \
\
FMOD size_t PFX##_count(SNAME *_deque_) \
{ \
return _deque_->count; \
} \
\
FMOD size_t PFX##_capacity(SNAME *_deque_) \
{ \
return _deque_->capacity; \
} \
\
FMOD cmc_string PFX##_to_string(SNAME *_deque_) \
{ \
cmc_string str; \
SNAME *d_ = _deque_; \
const char *name = #SNAME; \
\
snprintf(str.s, cmc_string_len, cmc_string_fmt_deque, \
name, d_, d_->buffer, d_->capacity, d_->count, d_->front, d_->back); \
\
return str; \
} \
\
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \
{ \
SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \
\
if (!iter) \
return NULL; \
\
PFX##_iter_init(iter, target); \
\
return iter; \
} \
\
FMOD void PFX##_iter_free(SNAME##_iter *iter) \
{ \
free(iter); \
} \
\
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \
{ \
iter->target = target; \
iter->cursor = target->front; \
iter->index = 0; \
iter->start = true; \
iter->end = PFX##_empty(target); \
} \
\
FMOD bool PFX##_iter_start(SNAME##_iter *iter) \
{ \
return PFX##_empty(iter->target) || iter->start; \
} \
\
FMOD bool PFX##_iter_end(SNAME##_iter *iter) \
{ \
return PFX##_empty(iter->target) || iter->end; \
} \
\
FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \
{ \
iter->cursor = iter->target->front; \
iter->index = 0; \
iter->start = true; \
iter->end = PFX##_empty(iter->target); \
} \
\
FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
iter->cursor = 0; \
else \
iter->cursor = (iter->target->back == 0) ? iter->target->capacity - 1 : iter->target->back - 1; \
\
iter->index = iter->target->count - 1; \
iter->start = PFX##_empty(iter->target); \
iter->end = true; \
} \
\
FMOD bool PFX##_iter_next(SNAME##_iter *iter) \
{ \
if (iter->end) \
return false; \
\
iter->start = PFX##_empty(iter->target); \
\
if (iter->index == iter->target->count - 1) \
iter->end = true; \
else \
{ \
iter->cursor = (iter->cursor + 1) % (iter->target->capacity); \
iter->index++; \
} \
\
return true; \
} \
\
FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \
{ \
if (iter->start) \
return false; \
\
iter->end = PFX##_empty(iter->target); \
\
if (iter->index == 0) \
iter->start = true; \
else \
{ \
iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; \
iter->index--; \
} \
\
return true; \
} \
\
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return 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 bool PFX##_impl_grow(SNAME *_deque_) \
{ \
size_t new_capacity = _deque_->capacity * 2; \
\
V *new_buffer = malloc(sizeof(V) * new_capacity); \
\
if (!new_buffer) \
return false; \
\
for (size_t i = _deque_->front, j = 0; j < _deque_->count; i = (i + 1) % _deque_->capacity, j++) \
{ \
new_buffer[j] = _deque_->buffer[i]; \
} \
\
free(_deque_->buffer); \
\
_deque_->buffer = new_buffer; \
_deque_->capacity = new_capacity; \
_deque_->front = 0; \
_deque_->back = _deque_->count; \
\
return true; \
} \
\
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; \
#define CMC_GENERATE_DEQUE_SOURCE(PFX, SNAME, V) \
\
/* Implementation Detail Functions */ \
static SNAME##_iter PFX##_impl_it_start(SNAME *_deque_); \
static SNAME##_iter PFX##_impl_it_end(SNAME *_deque_); \
\
SNAME *PFX##_new(size_t capacity) \
{ \
if (capacity < 1) \
return NULL; \
\
SNAME *_deque_ = malloc(sizeof(SNAME)); \
\
if (!_deque_) \
return NULL; \
\
_deque_->buffer = malloc(sizeof(V) * capacity); \
\
if (!_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; \
\
return _deque_; \
} \
\
void PFX##_clear(SNAME *_deque_, void (*deallocator)(V)) \
{ \
if (deallocator) \
{ \
for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) \
{ \
deallocator(_deque_->buffer[i]); \
\
i = (i + 1) % _deque_->capacity; \
} \
} \
\
memset(_deque_->buffer, 0, sizeof(V) * _deque_->capacity); \
\
_deque_->count = 0; \
_deque_->front = 0; \
_deque_->back = 0; \
} \
\
void PFX##_free(SNAME *_deque_, void (*deallocator)(V)) \
{ \
if (deallocator) \
{ \
for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) \
{ \
deallocator(_deque_->buffer[i]); \
\
i = (i + 1) % _deque_->capacity; \
} \
} \
\
free(_deque_->buffer); \
free(_deque_); \
} \
\
bool PFX##_push_front(SNAME *_deque_, V element) \
{ \
if (PFX##_full(_deque_)) \
{ \
if (!PFX##_resize(_deque_, PFX##_capacity(_deque_) * 2)) \
return false; \
} \
\
_deque_->front = (_deque_->front == 0) ? _deque_->capacity - 1 : _deque_->front - 1; \
\
_deque_->buffer[_deque_->front] = element; \
\
_deque_->count++; \
\
return true; \
} \
\
bool PFX##_push_back(SNAME *_deque_, V element) \
{ \
if (PFX##_full(_deque_)) \
{ \
if (!PFX##_resize(_deque_, PFX##_capacity(_deque_) * 2)) \
return false; \
} \
\
_deque_->buffer[_deque_->back] = element; \
\
_deque_->back = (_deque_->back == _deque_->capacity - 1) ? 0 : _deque_->back + 1; \
\
_deque_->count++; \
\
return true; \
} \
\
bool PFX##_pop_front(SNAME *_deque_) \
{ \
if (PFX##_empty(_deque_)) \
return false; \
\
_deque_->buffer[_deque_->front] = (V){0}; \
\
_deque_->front = (_deque_->front == _deque_->capacity - 1) ? 0 : _deque_->front + 1; \
\
_deque_->count--; \
\
return true; \
} \
\
bool PFX##_pop_back(SNAME *_deque_) \
{ \
if (PFX##_empty(_deque_)) \
return false; \
\
_deque_->back = (_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1; \
\
_deque_->buffer[_deque_->back] = (V){0}; \
\
_deque_->count--; \
\
return true; \
} \
\
V PFX##_front(SNAME *_deque_) \
{ \
if (PFX##_empty(_deque_)) \
return (V){0}; \
\
return _deque_->buffer[_deque_->front]; \
} \
\
V PFX##_back(SNAME *_deque_) \
{ \
if (PFX##_empty(_deque_)) \
return (V){0}; \
\
return _deque_->buffer[(_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1]; \
} \
\
bool PFX##_contains(SNAME *_deque_, V element, int (*comparator)(V, V)) \
{ \
for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) \
{ \
if (comparator(_deque_->buffer[i], element) == 0) \
return true; \
\
i = (i + 1) % _deque_->capacity; \
} \
\
return false; \
} \
\
bool PFX##_empty(SNAME *_deque_) \
{ \
return _deque_->count == 0; \
} \
\
bool PFX##_full(SNAME *_deque_) \
{ \
return _deque_->count >= _deque_->capacity; \
} \
\
size_t PFX##_count(SNAME *_deque_) \
{ \
return _deque_->count; \
} \
\
size_t PFX##_capacity(SNAME *_deque_) \
{ \
return _deque_->capacity; \
} \
\
bool PFX##_resize(SNAME *_deque_, size_t capacity) \
{ \
if (PFX##_capacity(_deque_) == capacity) \
return true; \
\
if (capacity < PFX##_count(_deque_)) \
return false; \
\
V *new_buffer = malloc(sizeof(V) * capacity); \
\
if (!new_buffer) \
return false; \
\
for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) \
{ \
new_buffer[j] = _deque_->buffer[i]; \
\
i = (i + 1) % PFX##_capacity(_deque_); \
} \
\
free(_deque_->buffer); \
\
_deque_->buffer = new_buffer; \
_deque_->capacity = capacity; \
_deque_->front = 0; \
_deque_->back = _deque_->count; \
\
return true; \
} \
\
SNAME *PFX##_copy_of(SNAME *_deque_, V (*copy_func)(V)) \
{ \
SNAME *result = PFX##_new(_deque_->capacity); \
\
if (!result) \
return NULL; \
\
if (copy_func) \
{ \
for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) \
{ \
result->buffer[j] = copy_func(_deque_->buffer[i]); \
\
i = (i + 1) % _deque_->capacity; \
} \
} \
else \
{ \
for (size_t i = _deque_->front, j = 0; j < _deque_->count; j++) \
{ \
result->buffer[j] = _deque_->buffer[i]; \
\
i = (i + 1) % _deque_->capacity; \
} \
} \
\
result->count = _deque_->count; \
\
return result; \
} \
\
bool PFX##_equals(SNAME *_deque1_, SNAME *_deque2_, int (*comparator)(V, V)) \
{ \
if (PFX##_count(_deque1_) != PFX##_count(_deque2_)) \
return false; \
\
size_t i, j, k; \
for (i = _deque1_->front, j = _deque2_->front, k = 0; k < PFX##_count(_deque1_); k++) \
{ \
if (comparator(_deque1_->buffer[i], _deque2_->buffer[j]) != 0) \
return false; \
\
i = (i + 1) % _deque1_->capacity; \
j = (j + 1) % _deque2_->capacity; \
} \
\
return true; \
} \
\
cmc_string PFX##_to_string(SNAME *_deque_) \
{ \
cmc_string str; \
SNAME *d_ = _deque_; \
const char *name = #SNAME; \
\
snprintf(str.s, cmc_string_len, cmc_string_fmt_deque, \
name, d_, d_->buffer, d_->capacity, d_->count, d_->front, d_->back); \
\
return str; \
} \
\
SNAME##_iter *PFX##_iter_new(SNAME *target) \
{ \
SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \
\
if (!iter) \
return NULL; \
\
PFX##_iter_init(iter, target); \
\
return iter; \
} \
\
void PFX##_iter_free(SNAME##_iter *iter) \
{ \
free(iter); \
} \
\
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); \
} \
\
bool PFX##_iter_start(SNAME##_iter *iter) \
{ \
return PFX##_empty(iter->target) || iter->start; \
} \
\
bool PFX##_iter_end(SNAME##_iter *iter) \
{ \
return PFX##_empty(iter->target) || iter->end; \
} \
\
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); \
} \
\
void PFX##_iter_to_end(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
{ \
iter->cursor = 0; \
iter->index = 0; \
} \
else \
{ \
if (iter->target->back == 0) \
iter->cursor = iter->target->capacity - 1; \
else \
iter->cursor = iter->target->back - 1; \
\
iter->index = PFX##_count(iter->target) - 1; \
} \
\
iter->start = PFX##_empty(iter->target); \
iter->end = true; \
} \
\
bool PFX##_iter_next(SNAME##_iter *iter) \
{ \
if (iter->end) \
return false; \
\
if (iter->index + 1 == PFX##_count(iter->target)) \
{ \
iter->end = true; \
return false; \
} \
\
iter->start = PFX##_empty(iter->target); \
\
iter->cursor = (iter->cursor + 1) % (iter->target->capacity); \
iter->index++; \
\
return true; \
} \
\
bool PFX##_iter_prev(SNAME##_iter *iter) \
{ \
if (iter->start) \
return false; \
\
if (iter->index == 0) \
{ \
iter->start = true; \
return false; \
} \
\
iter->end = 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 PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \
{ \
if (iter->end) \
return false; \
\
if (iter->index + 1 == PFX##_count(iter->target)) \
{ \
iter->end = true; \
return false; \
} \
\
if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \
return false; \
\
iter->start = 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 PFX##_iter_rewind(SNAME##_iter *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 = PFX##_empty(iter->target); \
\
iter->index -= steps; \
\
/* Prevent underflow */ \
if (iter->cursor < steps) \
iter->cursor += PFX##_capacity(iter->target); \
\
iter->cursor -= steps; \
\
return true; \
} \
\
/* Returns true only if the iterator was able to be positioned at the given index */ \
bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \
{ \
if (index >= PFX##_count(iter->target)) \
return false; \
\
if (iter->index > index) \
return PFX##_iter_rewind(iter, iter->index - index); \
else if (iter->index < index) \
return PFX##_iter_advance(iter, index - iter->index); \
\
return true; \
} \
\
V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return (V){0}; \
\
return iter->target->buffer[iter->cursor]; \
} \
\
V *PFX##_iter_rvalue(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return NULL; \
\
return &(iter->target->buffer[iter->cursor]); \
} \
\
size_t PFX##_iter_index(SNAME##_iter *iter) \
{ \
return iter->index; \
} \
\
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 */
+853 -678
View File
File diff suppressed because it is too large. Load diff
+960 -798
View File
File diff suppressed because it is too large. Load diff
+284 -186
View File
@@ -30,136 +30,131 @@
#ifndef CMC_HEAP_H
#define CMC_HEAP_H
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../utl/cmc_string.h"
/* to_string format */
static const char *cmc_string_fmt_heap = "%s at %p { buffer:%p, capacity:%" PRIuMAX ", count:%" PRIuMAX ", type:%s, cmp:%p }";
typedef enum cmc_heap_order_e
{
cmc_max_heap = 1,
cmc_min_heap = -1
} cmc_heap_order;
#define HEAP_GENERATE(PFX, SNAME, FMOD, V) \
HEAP_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
HEAP_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
#define CMC_GENERATE_HEAP(PFX, SNAME, V) \
CMC_GENERATE_HEAP_HEADER(PFX, SNAME, V) \
CMC_GENERATE_HEAP_SOURCE(PFX, SNAME, V)
#define HEAP_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \
HEAP_GENERATE_HEADER(PFX, SNAME, FMOD, V)
#define CMC_WRAPGEN_HEAP_HEADER(PFX, SNAME, K, V) \
CMC_GENERATE_HEAP_HEADER(PFX, SNAME, V)
#define HEAP_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \
HEAP_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
#define CMC_WRAPGEN_HEAP_SOURCE(PFX, SNAME, K, V) \
CMC_GENERATE_HEAP_SOURCE(PFX, SNAME, V)
/* HEADER ********************************************************************/
#define HEAP_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
\
/* Heap Structure */ \
typedef struct SNAME##_s \
{ \
/* Dynamic array of elements */ \
V *buffer; \
\
/* Current array capacity */ \
size_t capacity; \
\
/* Current amount of elements in the heap */ \
size_t count; \
\
/* Heap order (MaxHeap or MinHeap) */ \
enum cmc_heap_order_e HO; \
\
/* Element comparison function */ \
int (*cmp)(V, V); \
\
/* Function that returns an iterator to the start of the heap */ \
struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
\
/* Function that returns an iterator to the end of the heap */ \
struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
\
} SNAME, *SNAME##_ptr; \
\
/* Heap Iterator */ \
typedef struct SNAME##_iter_s \
{ \
/* Target heap */ \
struct SNAME##_s *target; \
\
/* Cursor's position (index) */ \
size_t cursor; \
\
/* If the iterator has reached the start of the iteration */ \
bool start; \
\
/* If the iterator has reached the end of the iteration */ \
bool end; \
\
} SNAME##_iter, *SNAME##_iter_ptr; \
\
/* Collection Functions */ \
/* Collection Allocation and Deallocation */ \
FMOD SNAME *PFX##_new(size_t capacity, cmc_heap_order HO, int (*compare)(V, V)); \
FMOD void PFX##_clear(SNAME *_heap_); \
FMOD void PFX##_free(SNAME *_heap_); \
/* Collection Input and Output */ \
FMOD bool PFX##_insert(SNAME *_heap_, V element); \
FMOD bool PFX##_remove(SNAME *_heap_, V *result); \
/* Conditional Input and Output */ \
FMOD bool PFX##_insert_if(SNAME *_heap_, V element, bool condition); \
FMOD bool PFX##_remove_if(SNAME *_heap_, V *result, bool condition); \
/* Element Access */ \
FMOD V PFX##_peek(SNAME *_heap_); \
FMOD V *PFX##_peek_ref(SNAME *_heap_); \
/* Collection State */ \
FMOD bool PFX##_contains(SNAME *_heap_, V element); \
FMOD bool PFX##_empty(SNAME *_heap_); \
FMOD bool PFX##_full(SNAME *_heap_); \
FMOD size_t PFX##_count(SNAME *_heap_); \
FMOD size_t PFX##_capacity(SNAME *_heap_); \
/* Collection Utility */ \
FMOD cmc_string PFX##_to_string(SNAME *_heap_); \
\
/* Iterator Functions */ \
/* Iterator Allocation and Deallocation */ \
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \
FMOD void PFX##_iter_free(SNAME##_iter *iter); \
/* Iterator Initialization */ \
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \
/* Iterator State */ \
FMOD bool PFX##_iter_start(SNAME##_iter *iter); \
FMOD bool PFX##_iter_end(SNAME##_iter *iter); \
/* Iterator Movement */ \
FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \
FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \
FMOD bool PFX##_iter_next(SNAME##_iter *iter); \
FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \
/* Iterator Access */ \
FMOD V PFX##_iter_value(SNAME##_iter *iter); \
FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \
\
/* Default Value */ \
static inline V PFX##_impl_default_value(void) \
{ \
V _empty_value_; \
\
memset(&_empty_value_, 0, sizeof(V)); \
\
return _empty_value_; \
} \
\
#define CMC_GENERATE_HEAP_HEADER(PFX, SNAME, V) \
\
/* Heap Structure */ \
typedef struct SNAME##_s \
{ \
/* Dynamic array of elements */ \
V *buffer; \
\
/* Current array capacity */ \
size_t capacity; \
\
/* Current amount of elements in the heap */ \
size_t count; \
\
/* Heap order (MaxHeap or MinHeap) */ \
enum cmc_heap_order_e HO; \
\
/* Element comparison function */ \
int (*cmp)(V, V); \
\
/* Function that returns an iterator to the start of the heap */ \
struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
\
/* Function that returns an iterator to the end of the heap */ \
struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
\
} SNAME, *SNAME##_ptr; \
\
/* Heap Iterator */ \
typedef struct SNAME##_iter_s \
{ \
/* Target heap */ \
struct SNAME##_s *target; \
\
/* Cursor's position (index) */ \
size_t cursor; \
\
/* If the iterator has reached the start of the iteration */ \
bool start; \
\
/* If the iterator has reached the end of the iteration */ \
bool end; \
\
} SNAME##_iter, *SNAME##_iter_ptr; \
\
/* Collection Functions */ \
/* Collection Allocation and Deallocation */ \
SNAME *PFX##_new(size_t capacity, cmc_heap_order HO, int (*compare)(V, V)); \
void PFX##_clear(SNAME *_heap_, void (*deallocator)(V)); \
void PFX##_free(SNAME *_heap_, void (*deallocator)(V)); \
/* Collection Input and Output */ \
bool PFX##_insert(SNAME *_heap_, V element); \
bool PFX##_remove(SNAME *_heap_, V *result); \
/* Element Access */ \
V PFX##_peek(SNAME *_heap_); \
/* Collection State */ \
bool PFX##_contains(SNAME *_heap_, V element); \
bool PFX##_empty(SNAME *_heap_); \
bool PFX##_full(SNAME *_heap_); \
size_t PFX##_count(SNAME *_heap_); \
size_t PFX##_capacity(SNAME *_heap_); \
/* Collection Utility */ \
bool PFX##_resize(SNAME *_heap_, size_t capacity); \
SNAME *PFX##_copy_of(SNAME *_heap_, V (*copy_func)(V)); \
bool PFX##_equals(SNAME *_heap1_, SNAME *_heap2_); \
cmc_string PFX##_to_string(SNAME *_heap_); \
\
/* Iterator Functions */ \
/* Iterator Allocation and Deallocation */ \
SNAME##_iter *PFX##_iter_new(SNAME *target); \
void PFX##_iter_free(SNAME##_iter *iter); \
/* Iterator Initialization */ \
void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \
/* Iterator State */ \
bool PFX##_iter_start(SNAME##_iter *iter); \
bool PFX##_iter_end(SNAME##_iter *iter); \
/* Iterator Movement */ \
void PFX##_iter_to_start(SNAME##_iter *iter); \
void PFX##_iter_to_end(SNAME##_iter *iter); \
bool PFX##_iter_next(SNAME##_iter *iter); \
bool PFX##_iter_prev(SNAME##_iter *iter); \
bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \
bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \
bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \
/* Iterator Access */ \
V PFX##_iter_value(SNAME##_iter *iter); \
size_t PFX##_iter_index(SNAME##_iter *iter); \
\
/* SOURCE ********************************************************************/
#define HEAP_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \
#define CMC_GENERATE_HEAP_SOURCE(PFX, SNAME, V) \
\
/* Implementation Detail Functions */ \
static bool PFX##_impl_grow(SNAME *_heap_); \
static bool PFX##_impl_float_up(SNAME *_heap_, size_t index); \
static bool PFX##_impl_float_down(SNAME *_heap_, size_t index); \
static SNAME##_iter PFX##_impl_it_start(SNAME *_heap_); \
static SNAME##_iter PFX##_impl_it_end(SNAME *_heap_); \
\
FMOD SNAME *PFX##_new(size_t capacity, cmc_heap_order HO, int (*compare)(V, V)) \
SNAME *PFX##_new(size_t capacity, cmc_heap_order HO, int (*compare)(V, V)) \
{ \
if (capacity < 1) \
return NULL; \
@@ -193,24 +188,40 @@ typedef enum cmc_heap_order_e
return _heap_; \
} \
\
FMOD void PFX##_clear(SNAME *_heap_) \
void PFX##_clear(SNAME *_heap_, void (*deallocator)(V)) \
{ \
if (deallocator) \
{ \
for (size_t i = 0; i < _heap_->count; i++) \
{ \
deallocator(_heap_->buffer[i]); \
} \
} \
\
memset(_heap_->buffer, 0, sizeof(V) * _heap_->capacity); \
\
_heap_->count = 0; \
} \
\
FMOD void PFX##_free(SNAME *_heap_) \
void PFX##_free(SNAME *_heap_, void (*deallocator)(V)) \
{ \
if (deallocator) \
{ \
for (size_t i = 0; i < _heap_->count; i++) \
{ \
deallocator(_heap_->buffer[i]); \
} \
} \
\
free(_heap_->buffer); \
free(_heap_); \
} \
\
FMOD bool PFX##_insert(SNAME *_heap_, V element) \
bool PFX##_insert(SNAME *_heap_, V element) \
{ \
if (PFX##_full(_heap_)) \
{ \
if (!PFX##_impl_grow(_heap_)) \
if (!PFX##_resize(_heap_, PFX##_count(_heap_) * 2)) \
return false; \
} \
\
@@ -228,14 +239,14 @@ typedef enum cmc_heap_order_e
return true; \
} \
\
FMOD bool PFX##_remove(SNAME *_heap_, V *result) \
bool PFX##_remove(SNAME *_heap_, V *result) \
{ \
if (PFX##_empty(_heap_)) \
return false; \
\
*result = _heap_->buffer[0]; \
_heap_->buffer[0] = _heap_->buffer[_heap_->count - 1]; \
_heap_->buffer[_heap_->count - 1] = PFX##_impl_default_value(); \
_heap_->buffer[_heap_->count - 1] = (V){0}; \
\
_heap_->count--; \
\
@@ -245,39 +256,15 @@ typedef enum cmc_heap_order_e
return true; \
} \
\
FMOD bool PFX##_insert_if(SNAME *_heap_, V element, bool condition) \
{ \
if (condition) \
return PFX##_insert(_heap_, element); \
\
return false; \
} \
\
FMOD bool PFX##_remove_if(SNAME *_heap_, V *result, bool condition) \
{ \
if (condition) \
return PFX##_remove(_heap_, result); \
\
return false; \
} \
\
FMOD V PFX##_peek(SNAME *_heap_) \
V PFX##_peek(SNAME *_heap_) \
{ \
if (PFX##_empty(_heap_)) \
return PFX##_impl_default_value(); \
return (V){0}; \
\
return _heap_->buffer[0]; \
} \
\
FMOD V *PFX##_peek_ref(SNAME *_heap_) \
{ \
if (PFX##_empty(_heap_)) \
return NULL; \
\
return &(_heap_->buffer[0]); \
} \
\
FMOD bool PFX##_contains(SNAME *_heap_, V element) \
bool PFX##_contains(SNAME *_heap_, V element) \
{ \
for (size_t i = 0; i < _heap_->count; i++) \
{ \
@@ -288,27 +275,80 @@ typedef enum cmc_heap_order_e
return false; \
} \
\
FMOD bool PFX##_empty(SNAME *_heap_) \
bool PFX##_empty(SNAME *_heap_) \
{ \
return _heap_->count == 0; \
} \
\
FMOD bool PFX##_full(SNAME *_heap_) \
bool PFX##_full(SNAME *_heap_) \
{ \
return _heap_->count >= _heap_->capacity; \
} \
\
FMOD size_t PFX##_count(SNAME *_heap_) \
size_t PFX##_count(SNAME *_heap_) \
{ \
return _heap_->count; \
} \
\
FMOD size_t PFX##_capacity(SNAME *_heap_) \
size_t PFX##_capacity(SNAME *_heap_) \
{ \
return _heap_->capacity; \
} \
\
FMOD cmc_string PFX##_to_string(SNAME *_heap_) \
bool PFX##_resize(SNAME *_heap_, size_t capacity) \
{ \
if (PFX##_capacity(_heap_) == capacity) \
return true; \
\
if (capacity < PFX##_count(_heap_)) \
return false; \
\
V *new_buffer = realloc(_heap_->buffer, sizeof(V) * capacity); \
\
if (!new_buffer) \
return false; \
\
_heap_->buffer = new_buffer; \
_heap_->capacity = capacity; \
\
return true; \
} \
\
SNAME *PFX##_copy_of(SNAME *_heap_, V (*copy_func)(V)) \
{ \
SNAME *result = PFX##_new(_heap_->capacity, _heap_->HO, _heap_->cmp); \
\
if (!result) \
return NULL; \
\
if (copy_func) \
{ \
for (size_t i = 0; i < _heap_->count; i++) \
result->buffer[i] = copy_func(_heap_->buffer[i]); \
} \
else \
memcpy(result->buffer, _heap_->buffer, sizeof(V) * _heap_->count); \
\
result->count = _heap_->count; \
\
return result; \
} \
\
bool PFX##_equals(SNAME *_heap1_, SNAME *_heap2_) \
{ \
if (PFX##_count(_heap1_) != PFX##_count(_heap2_)) \
return false; \
\
for (size_t i = 0; i < PFX##_count(_heap1_); i++) \
{ \
if (_heap1_->cmp(_heap1_->buffer[i], _heap2_->buffer[i]) != 0) \
return false; \
} \
\
return true; \
} \
\
cmc_string PFX##_to_string(SNAME *_heap_) \
{ \
cmc_string str; \
SNAME *h_ = _heap_; \
@@ -321,7 +361,7 @@ typedef enum cmc_heap_order_e
return str; \
} \
\
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \
SNAME##_iter *PFX##_iter_new(SNAME *target) \
{ \
SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \
\
@@ -333,12 +373,12 @@ typedef enum cmc_heap_order_e
return iter; \
} \
\
FMOD void PFX##_iter_free(SNAME##_iter *iter) \
void PFX##_iter_free(SNAME##_iter *iter) \
{ \
free(iter); \
} \
\
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \
void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \
{ \
iter->target = target; \
iter->cursor = 0; \
@@ -346,88 +386,146 @@ typedef enum cmc_heap_order_e
iter->end = PFX##_empty(target); \
} \
\
FMOD bool PFX##_iter_start(SNAME##_iter *iter) \
bool PFX##_iter_start(SNAME##_iter *iter) \
{ \
return PFX##_empty(iter->target) || iter->start; \
} \
\
FMOD bool PFX##_iter_end(SNAME##_iter *iter) \
bool PFX##_iter_end(SNAME##_iter *iter) \
{ \
return PFX##_empty(iter->target) || iter->end; \
} \
\
FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \
void PFX##_iter_to_start(SNAME##_iter *iter) \
{ \
iter->cursor = 0; \
iter->start = true; \
iter->end = PFX##_empty(iter->target); \
if (!PFX##_empty(iter->target)) \
{ \
iter->cursor = 0; \
iter->start = true; \
iter->end = PFX##_empty(iter->target); \
} \
} \
\
FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \
void PFX##_iter_to_end(SNAME##_iter *iter) \
{ \
iter->cursor = iter->target->count - 1; \
iter->start = PFX##_empty(iter->target); \
iter->end = true; \
if (!PFX##_empty(iter->target)) \
{ \
iter->cursor = PFX##_count(iter->target) - 1; \
iter->start = PFX##_empty(iter->target); \
iter->end = true; \
} \
} \
\
FMOD bool PFX##_iter_next(SNAME##_iter *iter) \
bool PFX##_iter_next(SNAME##_iter *iter) \
{ \
if (iter->end) \
return false; \
\
iter->start = false; \
\
if (iter->cursor == iter->target->count - 1) \
if (iter->cursor + 1 == PFX##_count(iter->target)) \
{ \
iter->end = true; \
else \
iter->cursor++; \
return false; \
} \
\
iter->start = PFX##_empty(iter->target); \
\
iter->cursor++; \
\
return true; \
} \
\
FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \
bool PFX##_iter_prev(SNAME##_iter *iter) \
{ \
if (iter->start) \
return false; \
\
iter->end = false; \
\
if (iter->cursor == 0) \
{ \
iter->start = true; \
else \
iter->cursor--; \
return false; \
} \
\
iter->end = PFX##_empty(iter->target); \
\
iter->cursor--; \
\
return true; \
} \
\
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
/* Returns true only if the iterator moved */ \
bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \
{ \
if (iter->start) \
return false; \
\
if (iter->cursor + 1 == PFX##_count(iter->target)) \
{ \
iter->end = true; \
return false; \
} \
\
if (steps == 0 || iter->cursor + steps >= PFX##_count(iter->target)) \
return false; \
\
iter->start = PFX##_empty(iter->target); \
\
if (iter->end) \
return false; \
\
iter->cursor += steps; \
\
return true; \
} \
\
/* Returns true only if the iterator moved */ \
bool PFX##_iter_rewind(SNAME##_iter *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 = 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 PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \
{ \
if (index >= PFX##_count(iter->target)) \
return false; \
\
if (iter->cursor > index) \
return PFX##_iter_rewind(iter, iter->cursor - index); \
else if (iter->cursor < index) \
return PFX##_iter_advance(iter, index - iter->cursor); \
\
return true; \
} \
\
V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return PFX##_impl_default_value(); \
return (V){0}; \
\
return iter->target->buffer[iter->cursor]; \
} \
\
FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \
size_t PFX##_iter_index(SNAME##_iter *iter) \
{ \
return iter->cursor; \
} \
\
static bool PFX##_impl_grow(SNAME *_heap_) \
{ \
size_t new_capacity = _heap_->capacity * 2; \
\
V *new_buffer = realloc(_heap_->buffer, sizeof(V) * new_capacity); \
\
if (!new_buffer) \
return false; \
\
_heap_->buffer = new_buffer; \
_heap_->capacity = new_capacity; \
\
return true; \
} \
\
static bool PFX##_impl_float_up(SNAME *_heap_, size_t index) \
{ \
/* Current index */ \
+861 -741
View File
File diff suppressed because it is too large. Load diff
+729 -646
View File
File diff suppressed because it is too large. Load diff
+478 -350
View File
@@ -43,24 +43,28 @@
#ifndef CMC_QUEUE_H
#define CMC_QUEUE_H
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../utl/cmc_string.h"
#define QUEUE_GENERATE(PFX, SNAME, FMOD, V) \
QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* to_string format */
static const char *cmc_string_fmt_queue = "%s at %p { buffer:%p, capacity:%" PRIuMAX ", count:%" PRIuMAX ", front:%" PRIuMAX ", back:%" PRIuMAX " }";
#define QUEUE_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \
QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V)
#define CMC_GENERATE_QUEUE(PFX, SNAME, V) \
CMC_GENERATE_QUEUE_HEADER(PFX, SNAME, V) \
CMC_GENERATE_QUEUE_SOURCE(PFX, SNAME, V)
#define QUEUE_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \
QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
#define CMC_WRAPGEN_QUEUE_HEADER(PFX, SNAME, K, V) \
CMC_GENERATE_QUEUE_HEADER(PFX, SNAME, V)
#define CMC_WRAPGEN_QUEUE_SOURCE(PFX, SNAME, K, V) \
CMC_GENERATE_QUEUE_SOURCE(PFX, SNAME, V)
/* HEADER ********************************************************************/
#define QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
#define CMC_GENERATE_QUEUE_HEADER(PFX, SNAME, V) \
\
/* Queue Structure */ \
typedef struct SNAME##_s \
@@ -110,361 +114,485 @@
\
/* Collection Functions */ \
/* Collection Allocation and Deallocation */ \
FMOD SNAME *PFX##_new(size_t capacity); \
FMOD void PFX##_clear(SNAME *_queue_); \
FMOD void PFX##_free(SNAME *_queue_); \
SNAME *PFX##_new(size_t capacity); \
void PFX##_clear(SNAME *_queue_, void (*deallocator)(V)); \
void PFX##_free(SNAME *_queue_, void (*deallocator)(V)); \
/* 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); \
bool PFX##_enqueue(SNAME *_queue_, V element); \
bool PFX##_dequeue(SNAME *_queue_); \
/* Element Access */ \
FMOD V PFX##_peek(SNAME *_queue_); \
V PFX##_peek(SNAME *_queue_); \
/* Collection State */ \
FMOD bool PFX##_contains(SNAME *_queue_, V element, int (*comparator)(V, V)); \
FMOD bool PFX##_empty(SNAME *_queue_); \
FMOD bool PFX##_full(SNAME *_queue_); \
FMOD size_t PFX##_count(SNAME *_queue_); \
FMOD size_t PFX##_capacity(SNAME *_queue_); \
bool PFX##_contains(SNAME *_queue_, V element, int (*comparator)(V, V)); \
bool PFX##_empty(SNAME *_queue_); \
bool PFX##_full(SNAME *_queue_); \
size_t PFX##_count(SNAME *_queue_); \
size_t PFX##_capacity(SNAME *_queue_); \
/* Collection Utility */ \
FMOD cmc_string PFX##_to_string(SNAME *_queue_); \
bool PFX##_resize(SNAME *_queue_, size_t capacity); \
SNAME *PFX##_copy_of(SNAME *_queue_, V (*copy_func)(V)); \
bool PFX##_equals(SNAME *_queue1_, SNAME *_queue2_, int (*comparator)(V, V)); \
cmc_string PFX##_to_string(SNAME *_queue_); \
\
/* Iterator Functions */ \
/* Iterator Allocation and Deallocation */ \
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \
FMOD void PFX##_iter_free(SNAME##_iter *iter); \
SNAME##_iter *PFX##_iter_new(SNAME *target); \
void PFX##_iter_free(SNAME##_iter *iter); \
/* Iterator Initialization */ \
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \
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); \
bool PFX##_iter_start(SNAME##_iter *iter); \
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); \
void PFX##_iter_to_start(SNAME##_iter *iter); \
void PFX##_iter_to_end(SNAME##_iter *iter); \
bool PFX##_iter_next(SNAME##_iter *iter); \
bool PFX##_iter_prev(SNAME##_iter *iter); \
bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \
bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \
bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \
/* 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_; \
} \
V PFX##_iter_value(SNAME##_iter *iter); \
V *PFX##_iter_rvalue(SNAME##_iter *iter); \
size_t PFX##_iter_index(SNAME##_iter *iter); \
\
/* SOURCE ********************************************************************/
#define QUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \
\
/* Implementation Detail Functions */ \
static bool PFX##_impl_grow(SNAME *_queue_); \
static SNAME##_iter PFX##_impl_it_start(SNAME *_queue_); \
static SNAME##_iter PFX##_impl_it_end(SNAME *_queue_); \
\
FMOD SNAME *PFX##_new(size_t capacity) \
{ \
if (capacity < 1) \
return NULL; \
\
SNAME *_queue_ = malloc(sizeof(SNAME)); \
\
if (!_queue_) \
return NULL; \
\
_queue_->buffer = malloc(sizeof(V) * capacity); \
\
if (!_queue_->buffer) \
{ \
free(_queue_); \
return NULL; \
} \
\
memset(_queue_->buffer, 0, sizeof(V) * capacity); \
\
_queue_->capacity = capacity; \
_queue_->count = 0; \
_queue_->front = 0; \
_queue_->back = 0; \
\
_queue_->it_start = PFX##_impl_it_start; \
_queue_->it_end = PFX##_impl_it_end; \
\
return _queue_; \
} \
\
FMOD void PFX##_clear(SNAME *_queue_) \
{ \
memset(_queue_->buffer, 0, sizeof(V) * _queue_->capacity); \
\
_queue_->count = 0; \
_queue_->front = 0; \
_queue_->back = 0; \
} \
\
FMOD void PFX##_free(SNAME *_queue_) \
{ \
free(_queue_->buffer); \
free(_queue_); \
} \
\
FMOD bool PFX##_enqueue(SNAME *_queue_, V element) \
{ \
if (PFX##_full(_queue_)) \
{ \
if (!PFX##_impl_grow(_queue_)) \
return false; \
} \
\
_queue_->buffer[_queue_->back] = element; \
\
_queue_->back = (_queue_->back == _queue_->capacity - 1) ? 0 : _queue_->back + 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 == _queue_->capacity - 1) ? 0 : _queue_->front + 1; \
_queue_->count--; \
\
return true; \
} \
\
FMOD bool PFX##_enqueue_if(SNAME *_queue_, V element, bool condition) \
{ \
if (condition) \
return PFX##_enqueue(_queue_, element); \
\
return false; \
} \
\
FMOD bool PFX##_dequeue_if(SNAME *_queue_, bool condition) \
{ \
if (condition) \
return PFX##_dequeue(_queue_); \
\
return false; \
} \
\
FMOD V PFX##_peek(SNAME *_queue_) \
{ \
if (PFX##_empty(_queue_)) \
return 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 >= _queue_->capacity; \
} \
\
FMOD size_t PFX##_count(SNAME *_queue_) \
{ \
return _queue_->count; \
} \
\
FMOD size_t PFX##_capacity(SNAME *_queue_) \
{ \
return _queue_->capacity; \
} \
\
FMOD cmc_string PFX##_to_string(SNAME *_queue_) \
{ \
cmc_string str; \
SNAME *q_ = _queue_; \
const char *name = #SNAME; \
\
snprintf(str.s, cmc_string_len, cmc_string_fmt_queue, \
name, q_, q_->buffer, q_->capacity, q_->count, q_->front, q_->back); \
\
return str; \
} \
\
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \
{ \
SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \
\
if (!iter) \
return NULL; \
\
PFX##_iter_init(iter, target); \
\
return iter; \
} \
\
FMOD void PFX##_iter_free(SNAME##_iter *iter) \
{ \
free(iter); \
} \
\
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \
{ \
iter->target = target; \
iter->cursor = target->front; \
iter->index = 0; \
iter->start = true; \
iter->end = PFX##_empty(target); \
} \
\
FMOD bool PFX##_iter_start(SNAME##_iter *iter) \
{ \
return PFX##_empty(iter->target) || iter->start; \
} \
\
FMOD bool PFX##_iter_end(SNAME##_iter *iter) \
{ \
return PFX##_empty(iter->target) || iter->end; \
} \
\
FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \
{ \
iter->cursor = iter->target->front; \
iter->index = 0; \
iter->start = true; \
iter->end = PFX##_empty(iter->target); \
} \
\
FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
iter->cursor = 0; \
else \
iter->cursor = (iter->target->back == 0) ? iter->target->capacity - 1 : iter->target->back - 1; \
\
iter->index = iter->target->count - 1; \
iter->start = PFX##_empty(iter->target); \
iter->end = true; \
} \
\
FMOD bool PFX##_iter_next(SNAME##_iter *iter) \
{ \
if (iter->end) \
return false; \
\
iter->start = PFX##_empty(iter->target); \
\
if (iter->index == iter->target->count - 1) \
iter->end = true; \
else \
{ \
iter->cursor = (iter->cursor + 1) % (iter->target->capacity); \
iter->index++; \
} \
\
return true; \
} \
\
FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \
{ \
if (iter->start) \
return false; \
\
iter->end = PFX##_empty(iter->target); \
\
if (iter->index == 0) \
iter->start = true; \
else \
{ \
iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; \
iter->index--; \
} \
\
return true; \
} \
\
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return 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 bool PFX##_impl_grow(SNAME *_queue_) \
{ \
\
size_t new_capacity = _queue_->capacity * 2; \
\
V *new_buffer = malloc(sizeof(V) * new_capacity); \
\
if (!new_buffer) \
return false; \
\
for (size_t i = _queue_->front, j = 0; j < _queue_->count; i = (i + 1) % _queue_->capacity, j++) \
{ \
new_buffer[j] = _queue_->buffer[i]; \
} \
\
free(_queue_->buffer); \
\
_queue_->buffer = new_buffer; \
_queue_->capacity = new_capacity; \
_queue_->front = 0; \
_queue_->back = _queue_->count; \
\
return true; \
} \
\
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; \
#define CMC_GENERATE_QUEUE_SOURCE(PFX, SNAME, V) \
\
/* Implementation Detail Functions */ \
static SNAME##_iter PFX##_impl_it_start(SNAME *_queue_); \
static SNAME##_iter PFX##_impl_it_end(SNAME *_queue_); \
\
SNAME *PFX##_new(size_t capacity) \
{ \
if (capacity < 1) \
return NULL; \
\
SNAME *_queue_ = malloc(sizeof(SNAME)); \
\
if (!_queue_) \
return NULL; \
\
_queue_->buffer = malloc(sizeof(V) * capacity); \
\
if (!_queue_->buffer) \
{ \
free(_queue_); \
return NULL; \
} \
\
memset(_queue_->buffer, 0, sizeof(V) * capacity); \
\
_queue_->capacity = capacity; \
_queue_->count = 0; \
_queue_->front = 0; \
_queue_->back = 0; \
\
_queue_->it_start = PFX##_impl_it_start; \
_queue_->it_end = PFX##_impl_it_end; \
\
return _queue_; \
} \
\
void PFX##_clear(SNAME *_queue_, void (*deallocator)(V)) \
{ \
if (deallocator) \
{ \
for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) \
{ \
deallocator(_queue_->buffer[i]); \
\
i = (i + 1) % _queue_->capacity; \
} \
} \
\
memset(_queue_->buffer, 0, sizeof(V) * _queue_->capacity); \
\
_queue_->count = 0; \
_queue_->front = 0; \
_queue_->back = 0; \
} \
\
void PFX##_free(SNAME *_queue_, void (*deallocator)(V)) \
{ \
if (deallocator) \
{ \
for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) \
{ \
deallocator(_queue_->buffer[i]); \
\
i = (i + 1) % _queue_->capacity; \
} \
} \
\
free(_queue_->buffer); \
free(_queue_); \
} \
\
bool PFX##_enqueue(SNAME *_queue_, V element) \
{ \
if (PFX##_full(_queue_)) \
{ \
if (!PFX##_resize(_queue_, PFX##_capacity(_queue_) * 2)) \
return false; \
} \
\
_queue_->buffer[_queue_->back] = element; \
\
_queue_->back = (_queue_->back == _queue_->capacity - 1) ? 0 : _queue_->back + 1; \
_queue_->count++; \
\
return true; \
} \
\
bool PFX##_dequeue(SNAME *_queue_) \
{ \
if (PFX##_empty(_queue_)) \
return false; \
\
_queue_->buffer[_queue_->front] = (V){0}; \
\
_queue_->front = (_queue_->front == _queue_->capacity - 1) ? 0 : _queue_->front + 1; \
_queue_->count--; \
\
return true; \
} \
\
V PFX##_peek(SNAME *_queue_) \
{ \
if (PFX##_empty(_queue_)) \
return (V){0}; \
\
return _queue_->buffer[_queue_->front]; \
} \
\
bool PFX##_contains(SNAME *_queue_, V element, int (*comparator)(V, V)) \
{ \
for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) \
{ \
if (comparator(_queue_->buffer[i], element) == 0) \
return true; \
\
i = (i + 1) % _queue_->capacity; \
} \
\
return false; \
} \
\
bool PFX##_empty(SNAME *_queue_) \
{ \
return _queue_->count == 0; \
} \
\
bool PFX##_full(SNAME *_queue_) \
{ \
return _queue_->count >= _queue_->capacity; \
} \
\
size_t PFX##_count(SNAME *_queue_) \
{ \
return _queue_->count; \
} \
\
size_t PFX##_capacity(SNAME *_queue_) \
{ \
return _queue_->capacity; \
} \
\
bool PFX##_resize(SNAME *_queue_, size_t capacity) \
{ \
if (PFX##_capacity(_queue_) == capacity) \
return true; \
\
if (capacity < PFX##_count(_queue_)) \
return false; \
\
V *new_buffer = malloc(sizeof(V) * capacity); \
\
if (!new_buffer) \
return false; \
\
for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) \
{ \
new_buffer[j] = _queue_->buffer[i]; \
\
i = (i + 1) % PFX##_capacity(_queue_); \
} \
\
free(_queue_->buffer); \
\
_queue_->buffer = new_buffer; \
_queue_->capacity = capacity; \
_queue_->front = 0; \
_queue_->back = _queue_->count; \
\
return true; \
} \
\
SNAME *PFX##_copy_of(SNAME *_queue_, V (*copy_func)(V)) \
{ \
SNAME *result = PFX##_new(_queue_->capacity); \
\
if (!result) \
return NULL; \
\
if (copy_func) \
{ \
for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) \
{ \
result->buffer[j] = copy_func(_queue_->buffer[i]); \
\
i = (i + 1) % _queue_->capacity; \
} \
} \
else \
{ \
for (size_t i = _queue_->front, j = 0; j < _queue_->count; j++) \
{ \
result->buffer[j] = _queue_->buffer[i]; \
\
i = (i + 1) % _queue_->capacity; \
} \
} \
\
result->count = _queue_->count; \
\
return result; \
} \
\
bool PFX##_equals(SNAME *_queue1_, SNAME *_queue2_, int (*comparator)(V, V)) \
{ \
if (PFX##_count(_queue1_) != PFX##_count(_queue2_)) \
return false; \
\
size_t i, j, k; \
for (i = _queue1_->front, j = _queue2_->front, k = 0; k < PFX##_count(_queue1_); k++) \
{ \
if (comparator(_queue1_->buffer[i], _queue2_->buffer[j]) != 0) \
return false; \
\
i = (i + 1) % _queue1_->capacity; \
j = (j + 1) % _queue2_->capacity; \
} \
\
return true; \
} \
\
cmc_string PFX##_to_string(SNAME *_queue_) \
{ \
cmc_string str; \
SNAME *q_ = _queue_; \
const char *name = #SNAME; \
\
snprintf(str.s, cmc_string_len, cmc_string_fmt_queue, \
name, q_, q_->buffer, q_->capacity, q_->count, q_->front, q_->back); \
\
return str; \
} \
\
SNAME##_iter *PFX##_iter_new(SNAME *target) \
{ \
SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \
\
if (!iter) \
return NULL; \
\
PFX##_iter_init(iter, target); \
\
return iter; \
} \
\
void PFX##_iter_free(SNAME##_iter *iter) \
{ \
free(iter); \
} \
\
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); \
} \
\
bool PFX##_iter_start(SNAME##_iter *iter) \
{ \
return PFX##_empty(iter->target) || iter->start; \
} \
\
bool PFX##_iter_end(SNAME##_iter *iter) \
{ \
return PFX##_empty(iter->target) || iter->end; \
} \
\
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); \
} \
\
void PFX##_iter_to_end(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
iter->cursor = 0; \
else \
{ \
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 = PFX##_empty(iter->target); \
iter->end = true; \
} \
\
bool PFX##_iter_next(SNAME##_iter *iter) \
{ \
if (iter->end) \
return false; \
\
if (iter->index + 1 == PFX##_count(iter->target)) \
{ \
iter->end = true; \
return false; \
} \
\
iter->start = PFX##_empty(iter->target); \
\
iter->cursor = (iter->cursor + 1) % (iter->target->capacity); \
iter->index++; \
\
return true; \
} \
\
bool PFX##_iter_prev(SNAME##_iter *iter) \
{ \
if (iter->start) \
return false; \
\
if (iter->index == 0) \
{ \
iter->start = true; \
return false; \
} \
\
iter->end = 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 PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \
{ \
if (iter->end) \
return false; \
\
if (iter->index + 1 == PFX##_count(iter->target)) \
{ \
iter->end = true; \
return false; \
} \
\
if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \
return false; \
\
iter->start = 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 PFX##_iter_rewind(SNAME##_iter *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 = PFX##_empty(iter->target); \
\
iter->index -= steps; \
\
/* Prevent underflow */ \
if (iter->cursor < steps) \
iter->cursor += PFX##_capacity(iter->target); \
\
iter->cursor -= steps; \
\
return true; \
} \
\
/* Returns true only if the iterator was able to be positioned at the given index */ \
bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \
{ \
if (index >= PFX##_count(iter->target)) \
return false; \
\
if (iter->index > index) \
return PFX##_iter_rewind(iter, iter->index - index); \
else if (iter->index < index) \
return PFX##_iter_advance(iter, index - iter->index); \
\
return true; \
} \
\
V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return (V){0}; \
\
return iter->target->buffer[iter->cursor]; \
} \
\
V *PFX##_iter_rvalue(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return NULL; \
\
return &(iter->target->buffer[iter->cursor]); \
} \
\
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_QUEUE_H */
+217 -129
View File
@@ -28,24 +28,28 @@
#ifndef CMC_STACK_H
#define CMC_STACK_H
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../utl/cmc_string.h"
#define STACK_GENERATE(PFX, SNAME, FMOD, V) \
STACK_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* to_string format */
static const char *cmc_string_fmt_stack = "%s at %p { buffer:%p, capacity:%" PRIuMAX ", count:%" PRIuMAX " }";
#define STACK_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \
STACK_GENERATE_HEADER(PFX, SNAME, FMOD, V)
#define CMC_GENERATE_STACK(PFX, SNAME, V) \
CMC_GENERATE_STACK_HEADER(PFX, SNAME, V) \
CMC_GENERATE_STACK_SOURCE(PFX, SNAME, V)
#define STACK_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \
STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
#define CMC_WRAPGEN_STACK_HEADER(PFX, SNAME, K, V) \
CMC_GENERATE_STACK_HEADER(PFX, SNAME, V)
#define CMC_WRAPGEN_STACK_SOURCE(PFX, SNAME, K, V) \
CMC_GENERATE_STACK_SOURCE(PFX, SNAME, V)
/* HEADER ********************************************************************/
#define STACK_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
#define CMC_GENERATE_STACK_HEADER(PFX, SNAME, V) \
\
/* Stack Structure */ \
typedef struct SNAME##_s \
@@ -86,64 +90,56 @@
\
/* Collection Functions */ \
/* Collection Allocation and Deallocation */ \
FMOD SNAME *PFX##_new(size_t capacity); \
FMOD void PFX##_clear(SNAME *_stack_); \
FMOD void PFX##_free(SNAME *_stack_); \
SNAME *PFX##_new(size_t capacity); \
void PFX##_clear(SNAME *_stack_, void (*deallocator)(V)); \
void PFX##_free(SNAME *_stack_, void (*deallocator)(V)); \
/* 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); \
bool PFX##_push(SNAME *_stack_, V element); \
bool PFX##_pop(SNAME *_stack_); \
/* Element Access */ \
FMOD V PFX##_top(SNAME *_stack_); \
V PFX##_top(SNAME *_stack_); \
/* Collection State */ \
FMOD bool PFX##_contains(SNAME *_stack_, V element, int (*comparator)(V, V)); \
FMOD bool PFX##_empty(SNAME *_stack_); \
FMOD bool PFX##_full(SNAME *_stack_); \
FMOD size_t PFX##_count(SNAME *_stack_); \
FMOD size_t PFX##_capacity(SNAME *_stack_); \
bool PFX##_contains(SNAME *_stack_, V element, int (*comparator)(V, V)); \
bool PFX##_empty(SNAME *_stack_); \
bool PFX##_full(SNAME *_stack_); \
size_t PFX##_count(SNAME *_stack_); \
size_t PFX##_capacity(SNAME *_stack_); \
/* Collection Utility */ \
FMOD cmc_string PFX##_to_string(SNAME *_stack_); \
bool PFX##_resize(SNAME *_stack_, size_t capacity); \
SNAME *PFX##_copy_of(SNAME *_stack_, V (*copy_func)(V)); \
bool PFX##_equals(SNAME *_stack1_, SNAME *_stack2_, int (*comparator)(V, V)); \
cmc_string PFX##_to_string(SNAME *_stack_); \
\
/* Iterator Functions */ \
/* Iterator Allocation and Deallocation */ \
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \
FMOD void PFX##_iter_free(SNAME##_iter *iter); \
SNAME##_iter *PFX##_iter_new(SNAME *target); \
void PFX##_iter_free(SNAME##_iter *iter); \
/* Iterator Initialization */ \
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \
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); \
bool PFX##_iter_start(SNAME##_iter *iter); \
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); \
void PFX##_iter_to_start(SNAME##_iter *iter); \
void PFX##_iter_to_end(SNAME##_iter *iter); \
bool PFX##_iter_next(SNAME##_iter *iter); \
bool PFX##_iter_prev(SNAME##_iter *iter); \
bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \
bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \
bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \
/* 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_; \
} \
V PFX##_iter_value(SNAME##_iter *iter); \
V *PFX##_iter_rvalue(SNAME##_iter *iter); \
size_t PFX##_iter_index(SNAME##_iter *iter); \
\
/* SOURCE ********************************************************************/
#define STACK_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \
#define CMC_GENERATE_STACK_SOURCE(PFX, SNAME, V) \
\
/* Implementation Detail Functions */ \
static bool PFX##_impl_grow(SNAME *_stack_); \
static SNAME##_iter PFX##_impl_it_start(SNAME *_stack_); \
static SNAME##_iter PFX##_impl_it_end(SNAME *_stack_); \
\
FMOD SNAME *PFX##_new(size_t capacity) \
SNAME *PFX##_new(size_t capacity) \
{ \
if (capacity < 1) \
return NULL; \
@@ -172,24 +168,36 @@
return _stack_; \
} \
\
FMOD void PFX##_clear(SNAME *_stack_) \
void PFX##_clear(SNAME *_stack_, void (*deallocator)(V)) \
{ \
if (deallocator) \
{ \
for (size_t i = 0; i < _stack_->count; i++) \
deallocator(_stack_->buffer[i]); \
} \
\
memset(_stack_->buffer, 0, sizeof(V) * _stack_->capacity); \
\
_stack_->count = 0; \
} \
\
FMOD void PFX##_free(SNAME *_stack_) \
void PFX##_free(SNAME *_stack_, void (*deallocator)(V)) \
{ \
free(_stack_->buffer); \
if (deallocator) \
{ \
for (size_t i = 0; i < _stack_->count; i++) \
deallocator(_stack_->buffer[i]); \
} \
\
free(_stack_); \
} \
\
FMOD bool PFX##_push(SNAME *_stack_, V element) \
bool PFX##_push(SNAME *_stack_, V element) \
{ \
if (PFX##_full(_stack_)) \
{ \
if (!PFX##_impl_grow(_stack_)) \
if (!PFX##_resize(_stack_, PFX##_capacity(_stack_) * 2)) \
return false; \
} \
\
@@ -198,41 +206,25 @@
return true; \
} \
\
FMOD bool PFX##_pop(SNAME *_stack_) \
bool PFX##_pop(SNAME *_stack_) \
{ \
if (PFX##_empty(_stack_)) \
return false; \
\
_stack_->buffer[--_stack_->count] = PFX##_impl_default_value(); \
_stack_->buffer[--_stack_->count] = (V){0}; \
\
return true; \
} \
\
FMOD bool PFX##_push_if(SNAME *_stack_, V element, bool condition) \
{ \
if (condition) \
return PFX##_push(_stack_, element); \
\
return false; \
} \
\
FMOD bool PFX##_pop_if(SNAME *_stack_, bool condition) \
{ \
if (condition) \
return PFX##_pop(_stack_); \
\
return false; \
} \
\
FMOD V PFX##_top(SNAME *_stack_) \
V PFX##_top(SNAME *_stack_) \
{ \
if (PFX##_empty(_stack_)) \
return PFX##_impl_default_value(); \
return (V){0}; \
\
return _stack_->buffer[_stack_->count - 1]; \
} \
\
FMOD bool PFX##_contains(SNAME *_stack_, V element, int (*comparator)(V, V)) \
bool PFX##_contains(SNAME *_stack_, V element, int (*comparator)(V, V)) \
{ \
for (size_t i = 0; i < _stack_->count; i++) \
{ \
@@ -243,27 +235,80 @@
return false; \
} \
\
FMOD bool PFX##_empty(SNAME *_stack_) \
bool PFX##_empty(SNAME *_stack_) \
{ \
return _stack_->count == 0; \
} \
\
FMOD bool PFX##_full(SNAME *_stack_) \
bool PFX##_full(SNAME *_stack_) \
{ \
return _stack_->count >= _stack_->capacity; \
} \
\
FMOD size_t PFX##_count(SNAME *_stack_) \
size_t PFX##_count(SNAME *_stack_) \
{ \
return _stack_->count; \
} \
\
FMOD size_t PFX##_capacity(SNAME *_stack_) \
size_t PFX##_capacity(SNAME *_stack_) \
{ \
return _stack_->capacity; \
} \
\
FMOD cmc_string PFX##_to_string(SNAME *_stack_) \
bool PFX##_resize(SNAME *_stack_, size_t capacity) \
{ \
if (PFX##_capacity(_stack_) == capacity) \
return true; \
\
if (capacity < PFX##_count(_stack_)) \
return false; \
\
V *new_buffer = realloc(_stack_->buffer, sizeof(V) * capacity); \
\
if (!new_buffer) \
return false; \
\
_stack_->buffer = new_buffer; \
_stack_->capacity = capacity; \
\
return true; \
} \
\
SNAME *PFX##_copy_of(SNAME *_stack_, V (*copy_func)(V)) \
{ \
SNAME *result = PFX##_new(_stack_->capacity); \
\
if (!result) \
return NULL; \
\
if (copy_func) \
{ \
for (size_t i = 0; i < _stack_->count; i++) \
result->buffer[i] = copy_func(_stack_->buffer[i]); \
} \
else \
memcpy(result->buffer, _stack_->buffer, sizeof(V) * _stack_->count); \
\
result->count = _stack_->count; \
\
return result; \
} \
\
bool PFX##_equals(SNAME *_stack1_, SNAME *_stack2_, int (*comparator)(V, V)) \
{ \
if (PFX##_count(_stack1_) != PFX##_count(_stack2_)) \
return false; \
\
for (size_t i = 0; i < PFX##_count(_stack1_); i++) \
{ \
if (comparator(_stack1_->buffer[i], _stack2_->buffer[i]) != 0) \
return false; \
} \
\
return true; \
} \
\
cmc_string PFX##_to_string(SNAME *_stack_) \
{ \
cmc_string str; \
SNAME *s_ = _stack_; \
@@ -275,7 +320,7 @@
return str; \
} \
\
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \
SNAME##_iter *PFX##_iter_new(SNAME *target) \
{ \
SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \
\
@@ -287,95 +332,153 @@
return iter; \
} \
\
FMOD void PFX##_iter_free(SNAME##_iter *iter) \
void PFX##_iter_free(SNAME##_iter *iter) \
{ \
free(iter); \
} \
\
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \
void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \
{ \
iter->target = target; \
\
if (PFX##_empty(target)) \
iter->cursor = 0; \
else \
iter->cursor = iter->target->count - 1; \
\
iter->cursor = PFX##_empty(target) ? 0 : iter->target->count - 1; \
iter->start = true; \
iter->end = PFX##_empty(target); \
} \
\
FMOD bool PFX##_iter_start(SNAME##_iter *iter) \
bool PFX##_iter_start(SNAME##_iter *iter) \
{ \
return PFX##_empty(iter->target) || iter->start; \
} \
\
FMOD bool PFX##_iter_end(SNAME##_iter *iter) \
bool PFX##_iter_end(SNAME##_iter *iter) \
{ \
return PFX##_empty(iter->target) || iter->end; \
} \
\
FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \
void PFX##_iter_to_start(SNAME##_iter *iter) \
{ \
iter->cursor = iter->target->count - 1; \
iter->start = true; \
iter->end = PFX##_empty(iter->target); \
if (!PFX##_empty(iter->target)) \
{ \
iter->cursor = iter->target->count - 1; \
iter->start = true; \
iter->end = PFX##_empty(iter->target); \
} \
} \
\
FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \
void PFX##_iter_to_end(SNAME##_iter *iter) \
{ \
iter->cursor = 0; \
iter->start = PFX##_empty(iter->target); \
iter->end = true; \
if (!PFX##_empty(iter->target)) \
{ \
iter->cursor = 0; \
iter->start = PFX##_empty(iter->target); \
iter->end = true; \
} \
} \
\
FMOD bool PFX##_iter_next(SNAME##_iter *iter) \
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; \
\
return false; \
} \
else \
iter->cursor--; \
\
iter->start = PFX##_empty(iter->target); \
\
iter->cursor--; \
\
return true; \
} \
\
FMOD bool PFX##_iter_prev(SNAME##_iter *iter) \
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) \
if (iter->cursor + 1 == PFX##_count(iter->target)) \
{ \
iter->start = true; \
\
return false; \
} \
else \
iter->cursor++; \
\
iter->end = PFX##_empty(iter->target); \
\
iter->cursor++; \
\
return true; \
} \
\
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
/* Returns true only if the iterator moved */ \
bool PFX##_iter_advance(SNAME##_iter *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 = PFX##_empty(iter->target); \
\
iter->cursor -= steps; \
\
return true; \
} \
\
/* Returns true only if the iterator moved */ \
bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \
{ \
if (iter->start) \
return false; \
\
if (iter->cursor + 1 == PFX##_count(iter->target)) \
{ \
iter->start = true; \
return false; \
} \
\
if (steps == 0 || iter->cursor + steps >= PFX##_count(iter->target)) \
return false; \
\
iter->end = 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 PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \
{ \
if (index >= PFX##_count(iter->target)) \
return false; \
\
if (iter->cursor > index) \
return PFX##_iter_rewind(iter, iter->cursor - index); \
else if (iter->cursor < index) \
return PFX##_iter_advance(iter, index - iter->cursor); \
\
return true; \
} \
\
V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return PFX##_impl_default_value(); \
return (V){0}; \
\
return iter->target->buffer[iter->cursor]; \
} \
\
FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \
V *PFX##_iter_rvalue(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return NULL; \
@@ -383,7 +486,7 @@
return &(iter->target->buffer[iter->cursor]); \
} \
\
FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \
size_t PFX##_iter_index(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return 0; \
@@ -391,21 +494,6 @@
return iter->target->count - 1 - iter->cursor; \
} \
\
static bool PFX##_impl_grow(SNAME *_stack_) \
{ \
size_t new_capacity = _stack_->capacity * 2; \
\
V *new_buffer = realloc(_stack_->buffer, sizeof(V) * new_capacity); \
\
if (!new_buffer) \
return false; \
\
_stack_->buffer = new_buffer; \
_stack_->capacity = new_capacity; \
\
return true; \
} \
\
static SNAME##_iter PFX##_impl_it_start(SNAME *_stack_) \
{ \
SNAME##_iter iter; \
+985 -881
View File
File diff suppressed because it is too large. Load diff
+1038 -929
View File
File diff suppressed because it is too large. Load diff
+873
View File
@@ -0,0 +1,873 @@
/**
* bidimap.h
*
* Creation Date: 26/09/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
#ifndef CMC_BIDIMAP_H
#define CMC_BIDIMAP_H
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../utl/cmc_string.h"
/**
* THIS IS A PREVIEW ONLY
*
* BidiMap
*
* A bidirectional map is a map that allows you to create a bijection in both
* directions between two sets of elements (K <-> V).
*
* This implementation uses two arrays of pointers to an entry containing both
* the key and the value.
*/
/* to_string format */
static const char *cmc_string_fmt_bidimap = "%s at %p { key_buffer:%p, val_buffer:%p, capacity:%" PRIuMAX ", count:%" PRIuMAX ", load:%lf, key_cmp:%p, val_cmp:%p, key_hash:%p, val_hash:%p }";
#ifndef CMC_ENTRY_DELETED
#define CMC_ENTRY_DELETED ((void *)1)
#endif /* CMC_ENTRY_DELETED */
#ifndef CMC_IMPL_HASHTABLE_SETUP
#define CMC_IMPL_HASHTABLE_SETUP
static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
3067, 6143, 12289, 24571, 49157,
98299, 196613, 393209, 786431,
1572869, 3145721, 6291449,
12582917, 25165813, 50331653,
100663291, 201326611, 402653189,
805306357, 1610612741,
3221225473, 6442450939,
12884901893, 25769803799,
51539607551, 103079215111,
206158430209, 412316860441,
824633720831, 1649267441651,
3298534883309, 6597069766657,
13194139533299, 26388279066623,
52776558133303, 105553116266489,
211106232532969, 422212465066001,
844424930131963,
1688849860263953,
3377699720527861,
6755399441055731,
13510798882111483,
27021597764222939,
54043195528445957,
108086391056891903,
216172782113783773,
432345564227567621,
864691128455135207,
1729382256910270481,
3458764513820540933,
6917529027641081903,
13835058055282163729llu};
#endif /* CMC_IMPL_HASHTABLE_SETUP */
#define CMC_GENERATE_BIDIMAP(PFX, SNAME, K, V) \
CMC_GENERATE_BIDIMAP_HEADER(PFX, SNAME, K, V) \
CMC_GENERATE_BIDIMAP_SOURCE(PFX, SNAME, K, V)
#define CMC_WRAPGEN_BIDIMAP_HEADER(PFX, SNAME, K, V) \
CMC_GENERATE_BIDIMAP_HEADER(PFX, SNAME, K, V)
#define CMC_WRAPGEN_BIDIMAP_SOURCE(PFX, SNAME, K, V) \
CMC_GENERATE_BIDIMAP_SOURCE(PFX, SNAME, K, V)
/* HEADER ********************************************************************/
#define CMC_GENERATE_BIDIMAP_HEADER(PFX, SNAME, K, V) \
\
/* BidiMap Structure */ \
typedef struct SNAME##_s \
{ \
/* Array of Entries mapping K -> V */ \
struct SNAME##_entry_s **key_buffer; \
\
/* Array of entries mapping V -> K */ \
struct SNAME##_entry_s **val_buffer; \
\
/* Current arrays capacity */ \
size_t capacity; \
\
/* Current amount of keys */ \
size_t count; \
\
/* Load factor in range (0.0, 1.0) */ \
double load; \
\
/* Key comparison function */ \
int (*key_cmp)(K, K); \
\
/* Value comparison function */ \
int (*val_cmp)(V, V); \
\
/* Key hash function */ \
size_t (*key_hash)(K); \
\
/* Value hash function */ \
size_t (*val_hash)(V); \
\
/* Function that returns an iterator to the start of the bidimap */ \
struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
\
/* Function that returns an iterator to the end of the bidimap */ \
struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
\
} SNAME, *SNAME##_ptr; \
\
/* BidiMap Entry */ \
typedef struct SNAME##_entry_s \
{ \
/* Entry Key */ \
K key; \
\
/* Entry Value */ \
V value; \
\
/* The distance of this node to its original position, used by */ \
/* robin-hood hashing relative to the key_buffer */ \
size_t key_dist; \
\
/* The distance of this node to its original position, used by */ \
/* robin-hood hashing relative to the value_buffer */ \
size_t val_dist; \
\
} SNAME##_entry, *SNAME##_entry_ptr; \
\
/* BidiMap Iterator */ \
typedef struct SNAME##_iter_s \
{ \
/* Target bidimap */ \
struct SNAME##_s *target; \
\
/* Cursor's position (index) */ \
size_t cursor; \
\
/* Keeps track of relative index to the iteration of elements */ \
size_t index; \
\
/* The index of the first element */ \
size_t first; \
\
/* The index of the last element */ \
size_t last; \
\
/* If the iterator has reached the start of the iteration */ \
bool start; \
\
/* If the iterator has reached the end of the iteration */ \
bool end; \
\
} SNAME##_iter, *SNAME##_iter_ptr; \
\
/* Collection Functions */ \
/* Collection Allocation and Deallocation */ \
SNAME *PFX##_new(size_t capacity, double load, \
int (*key_cmp)(K, K), size_t (*key_hash)(K), \
int (*val_cmp)(V, V), size_t (*val_hash)(V)); \
void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)); \
void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)); \
/* Collection Input and Output */ \
bool PFX##_insert(SNAME *_map_, K key, V value); \
bool PFX##_update_key(SNAME *_map_, K key, K *old_key); \
bool PFX##_update_val(SNAME *_map_, V val, V *old_val); \
bool PFX##_remove_by_key(SNAME *_map_, K key, V *out_value); \
bool PFX##_remove_by_val(SNAME *_map_, V value, K *out_key); \
/* Element Access */ \
K PFX##_get_key(SNAME *_map_, V val); \
V PFX##_get_val(SNAME *_map_, K key); \
/* Collection State */ \
bool PFX##_contains_key(SNAME *_map_, K key); \
bool PFX##_contains_val(SNAME *_map_, V val); \
bool PFX##_empty(SNAME *_map_); \
bool PFX##_full(SNAME *_map_); \
size_t PFX##_count(SNAME *_map_); \
size_t PFX##_capacity(SNAME *_map_); \
double PFX##_load(SNAME *_map_); \
/* Collection Utility */ \
SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)); \
bool PFX##_equals(SNAME *_map1_, SNAME *_map2_); \
cmc_string PFX##_to_string(SNAME *_map_); \
\
/* Iterator Functions */ \
/* Iterator Allocation and Deallocation */ \
SNAME##_iter *PFX##_iter_new(SNAME *target); \
void PFX##_iter_free(SNAME##_iter *iter); \
/* Iterator Initialization */ \
void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \
/* Iterator State */ \
bool PFX##_iter_start(SNAME##_iter *iter); \
bool PFX##_iter_end(SNAME##_iter *iter); \
/* Iterator Movement */ \
void PFX##_iter_to_start(SNAME##_iter *iter); \
void PFX##_iter_to_end(SNAME##_iter *iter); \
bool PFX##_iter_next(SNAME##_iter *iter); \
bool PFX##_iter_prev(SNAME##_iter *iter); \
bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \
bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \
bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \
/* Iterator Access */ \
K PFX##_iter_key(SNAME##_iter *iter); \
V PFX##_iter_value(SNAME##_iter *iter); \
size_t PFX##_iter_index(SNAME##_iter *iter); \
\
/* SOURCE ********************************************************************/
#define CMC_GENERATE_BIDIMAP_SOURCE(PFX, SNAME, K, V) \
\
/* Implementation Detail Functions */ \
static bool PFX##_impl_grow(SNAME *_map_); \
static SNAME##_entry *PFX##_impl_new_entry(K key, V value); \
static SNAME##_entry **PFX##_impl_get_entry_by_key(SNAME *_map_, K key); \
static SNAME##_entry **PFX##_impl_get_entry_by_val(SNAME *_map_, V val); \
static SNAME##_entry **PFX##_impl_add_entry_to_key(SNAME *_map_, SNAME##_entry *entry); \
static SNAME##_entry **PFX##_impl_add_entry_to_val(SNAME *_map_, SNAME##_entry *entry); \
static size_t PFX##_impl_calculate_size(size_t required); \
static SNAME##_iter PFX##_impl_it_start(SNAME *_map_); \
static SNAME##_iter PFX##_impl_it_end(SNAME *_map_); \
\
SNAME *PFX##_new(size_t capacity, double load, \
int (*key_cmp)(K, K), size_t (*key_hash)(K), \
int (*val_cmp)(V, V), size_t (*val_hash)(V)) \
{ \
if (capacity == 0 || load <= 0 || load >= 1) \
return NULL; \
\
/* Prevent integer overflow */ \
if (capacity >= UINTMAX_MAX * load) \
return NULL; \
\
size_t real_capacity = PFX##_impl_calculate_size(capacity / load); \
\
SNAME *_map_ = malloc(sizeof(SNAME)); \
\
if (!_map_) \
return NULL; \
\
_map_->key_buffer = calloc(real_capacity, sizeof(SNAME##_entry *)); \
_map_->val_buffer = calloc(real_capacity, sizeof(SNAME##_entry *)); \
\
if (!_map_->key_buffer || !_map_->val_buffer) \
{ \
free(_map_->key_buffer); \
free(_map_->val_buffer); \
free(_map_); \
return NULL; \
} \
\
_map_->count = 0; \
_map_->capacity = real_capacity; \
_map_->load = load; \
_map_->key_cmp = key_cmp; \
_map_->val_cmp = val_cmp; \
_map_->key_hash = key_hash; \
_map_->val_hash = val_hash; \
\
_map_->it_start = PFX##_impl_it_start; \
_map_->it_end = PFX##_impl_it_end; \
\
return _map_; \
} \
\
void PFX##_clear(SNAME *_map_, void (*deallocator)(K, V)) \
{ \
for (size_t i = 0; i < _map_->capacity; i++) \
{ \
SNAME##_entry *entry = _map_->key_buffer[i]; \
\
if (entry != NULL && entry != CMC_ENTRY_DELETED) \
{ \
if (deallocator) \
deallocator(entry->key, entry->value); \
\
free(entry); \
} \
\
_map_->key_buffer[i] = NULL; \
_map_->val_buffer[i] = NULL; \
} \
\
_map_->count = 0; \
} \
\
void PFX##_free(SNAME *_map_, void (*deallocator)(K, V)) \
{ \
PFX##_clear(_map_, deallocator); \
\
free(_map_->key_buffer); \
free(_map_->val_buffer); \
free(_map_); \
} \
\
bool PFX##_insert(SNAME *_map_, K key, V value) \
{ \
if (PFX##_full(_map_)) \
{ \
if (!PFX##_impl_grow(_map_)) \
return false; \
} \
\
if (PFX##_impl_get_entry_by_key(_map_, key) != NULL || \
PFX##_impl_get_entry_by_val(_map_, value) != NULL) \
return false; \
\
SNAME##_entry *entry = PFX##_impl_new_entry(key, value); \
\
SNAME##_entry **key_entry = PFX##_impl_add_entry_to_key(_map_, entry); \
SNAME##_entry **val_entry = PFX##_impl_add_entry_to_val(_map_, entry); \
\
if (!key_entry || !val_entry) \
{ \
if (key_entry) \
*key_entry = CMC_ENTRY_DELETED; \
if (val_entry) \
*val_entry = CMC_ENTRY_DELETED; \
\
free(entry); \
\
return false; \
} \
\
_map_->count++; \
\
return true; \
} \
\
bool PFX##_update_key(SNAME *_map_, K key, K *old_key) \
{ \
if (PFX##_empty(_map_)) \
return false; \
\
return true; \
} \
\
bool PFX##_update_val(SNAME *_map_, V val, V *old_val) \
{ \
if (PFX##_empty(_map_)) \
return false; \
\
return true; \
} \
\
bool PFX##_remove_by_key(SNAME *_map_, K key, V *out_value) \
{ \
if (PFX##_empty(_map_)) \
return false; \
\
return true; \
} \
\
bool PFX##_remove_by_val(SNAME *_map_, V value, K *out_key) \
{ \
if (PFX##_empty(_map_)) \
return false; \
\
return true; \
} \
\
K PFX##_get_key(SNAME *_map_, V val) \
{ \
SNAME##_entry **entry = PFX##_impl_get_entry_by_val(_map_, val); \
\
if (!entry) \
return (V){0}; \
\
return (*entry)->key; \
} \
\
V PFX##_get_val(SNAME *_map_, K key) \
{ \
SNAME##_entry **entry = PFX##_impl_get_entry_by_key(_map_, key); \
\
if (!entry) \
return (V){0}; \
\
return (*entry)->value; \
} \
\
bool PFX##_contains_key(SNAME *_map_, K key) \
{ \
return PFX##_impl_get_entry_by_key(_map_, key) != NULL; \
} \
\
bool PFX##_contains_val(SNAME *_map_, V val) \
{ \
return PFX##_impl_get_entry_by_val(_map_, val) != NULL; \
} \
\
bool PFX##_empty(SNAME *_map_) \
{ \
return _map_->count == 0; \
} \
\
bool PFX##_full(SNAME *_map_) \
{ \
return (double)PFX##_capacity(_map_) * PFX##_load(_map_) <= (double)PFX##_count(_map_); \
} \
\
size_t PFX##_count(SNAME *_map_) \
{ \
return _map_->count; \
} \
\
size_t PFX##_capacity(SNAME *_map_) \
{ \
return _map_->capacity; \
} \
\
double PFX##_load(SNAME *_map_) \
{ \
return _map_->load; \
} \
\
SNAME *PFX##_copy_of(SNAME *_map_, K (*key_copy_func)(K), V (*value_copy_func)(V)) \
{ \
return NULL; \
} \
\
bool PFX##_equals(SNAME *_map1_, SNAME *_map2_) \
{ \
return false; \
} \
\
cmc_string PFX##_to_string(SNAME *_map_) \
{ \
cmc_string str; \
SNAME *m_ = _map_; \
const char *name = #SNAME; \
\
snprintf(str.s, cmc_string_len, cmc_string_fmt_bidimap, \
name, m_, m_->key_buffer, m_->val_buffer, m_->capacity, m_->count, \
m_->load, m_->key_cmp, m_->val_cmp, m_->key_hash, m_->val_hash); \
\
return str; \
} \
\
SNAME##_iter *PFX##_iter_new(SNAME *target) \
{ \
SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \
\
if (!iter) \
return NULL; \
\
PFX##_iter_init(iter, target); \
\
return iter; \
} \
\
void PFX##_iter_free(SNAME##_iter *iter) \
{ \
free(iter); \
} \
\
void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \
{ \
memset(iter, 0, sizeof(SNAME##_iter)); \
\
iter->target = target; \
iter->start = true; \
iter->end = PFX##_empty(target); \
\
if (!PFX##_empty(target)) \
{ \
for (size_t i = 0; i < target->capacity; i++) \
{ \
SNAME##_entry *tmp = target->key_buffer[i]; \
\
if (tmp != NULL && tmp != CMC_ENTRY_DELETED) \
{ \
iter->first = i; \
break; \
} \
} \
\
iter->cursor = iter->first; \
\
for (size_t i = target->capacity; i > 0; i--) \
{ \
SNAME##_entry *tmp = target->key_buffer[i - 1]; \
\
if (tmp != NULL && tmp != CMC_ENTRY_DELETED) \
{ \
iter->last = i - 1; \
break; \
} \
} \
} \
} \
\
bool PFX##_iter_start(SNAME##_iter *iter) \
{ \
return PFX##_empty(iter->target) || iter->start; \
} \
\
bool PFX##_iter_end(SNAME##_iter *iter) \
{ \
return PFX##_empty(iter->target) || iter->end; \
} \
\
void PFX##_iter_to_start(SNAME##_iter *iter) \
{ \
if (!PFX##_empty(iter->target)) \
{ \
iter->cursor = iter->first; \
iter->index = 0; \
iter->start = true; \
iter->end = false; \
} \
} \
\
void PFX##_iter_to_end(SNAME##_iter *iter) \
{ \
if (!PFX##_empty(iter->target)) \
{ \
iter->cursor = iter->last; \
iter->index = PFX##_count(iter->target) - 1; \
iter->start = false; \
iter->end = true; \
} \
} \
\
bool PFX##_iter_next(SNAME##_iter *iter) \
{ \
if (iter->end) \
return false; \
\
if (iter->index + 1 == PFX##_count(iter->target)) \
{ \
iter->end = true; \
return false; \
} \
\
iter->start = PFX##_empty(iter->target); \
\
SNAME##_entry *scan = iter->target->key_buffer[iter->cursor]; \
\
iter->index++; \
\
while (1) \
{ \
iter->cursor++; \
scan = iter->target->key_buffer[iter->cursor]; \
\
if (scan != NULL && scan != CMC_ENTRY_DELETED) \
break; \
} \
\
return true; \
} \
\
bool PFX##_iter_prev(SNAME##_iter *iter) \
{ \
if (iter->start) \
return false; \
\
if (iter->index == 0) \
{ \
iter->start = true; \
return false; \
} \
\
iter->end = PFX##_empty(iter->target); \
\
SNAME##_entry *scan = iter->target->key_buffer[iter->cursor]; \
\
iter->index--; \
\
while (1) \
{ \
iter->cursor--; \
scan = iter->target->key_buffer[iter->cursor]; \
\
if (scan != NULL && scan != CMC_ENTRY_DELETED) \
break; \
} \
\
return true; \
} \
\
/* Returns true only if the iterator moved */ \
bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \
{ \
if (iter->end) \
return false; \
\
if (iter->index + 1 == PFX##_count(iter->target)) \
{ \
iter->end = true; \
return false; \
} \
\
if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \
return false; \
\
for (size_t i = 0; i < steps; i++) \
PFX##_iter_next(iter); \
\
return true; \
} \
\
/* Returns true only if the iterator moved */ \
bool PFX##_iter_rewind(SNAME##_iter *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++) \
PFX##_iter_prev(iter); \
\
return true; \
} \
\
/* Returns true only if the iterator was able to be positioned at the given index */ \
bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \
{ \
if (index >= PFX##_count(iter->target)) \
return false; \
\
if (iter->index > index) \
return PFX##_iter_rewind(iter, iter->index - index); \
else if (iter->index < index) \
return PFX##_iter_advance(iter, index - iter->index); \
\
return true; \
} \
\
K PFX##_iter_key(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return (K){0}; \
\
return iter->target->key_buffer[iter->cursor]->key; \
} \
\
V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return (V){0}; \
\
return iter->target->key_buffer[iter->cursor]->value; \
} \
\
size_t PFX##_iter_index(SNAME##_iter *iter) \
{ \
return iter->index; \
} \
\
static bool PFX##_impl_grow(SNAME *_map_) \
{ \
/* TODO */ \
return false; \
} \
\
static SNAME##_entry *PFX##_impl_new_entry(K key, V value) \
{ \
SNAME##_entry *entry = malloc(sizeof(SNAME##_entry)); \
\
if (!entry) \
return NULL; \
\
entry->key = key; \
entry->value = value; \
entry->key_dist = 0; \
entry->val_dist = 0; \
\
return entry; \
} \
\
static SNAME##_entry **PFX##_impl_get_entry_by_key(SNAME *_map_, K key) \
{ \
size_t hash = _map_->key_hash(key); \
size_t pos = hash % _map_->capacity; \
\
SNAME##_entry *target = _map_->key_buffer[pos]; \
\
while (target != NULL) \
{ \
if (target != CMC_ENTRY_DELETED && _map_->key_cmp(target->key, key) == 0) \
return &(_map_->key_buffer[pos % _map_->capacity]); \
\
pos++; \
target = _map_->key_buffer[pos % _map_->capacity]; \
} \
\
return NULL; \
} \
\
static SNAME##_entry **PFX##_impl_get_entry_by_val(SNAME *_map_, V val) \
{ \
size_t hash = _map_->val_hash(val); \
size_t pos = hash % _map_->capacity; \
\
SNAME##_entry *target = _map_->val_buffer[pos]; \
\
while (target != NULL) \
{ \
if (target != CMC_ENTRY_DELETED && _map_->val_cmp(target->value, val) == 0) \
return &(_map_->val_buffer[pos % _map_->capacity]); \
\
pos++; \
target = _map_->val_buffer[pos % _map_->capacity]; \
} \
\
return NULL; \
} \
\
static SNAME##_entry **PFX##_impl_add_entry_to_key(SNAME *_map_, SNAME##_entry *entry) \
{ \
SNAME##_entry **to_return = NULL; \
\
size_t hash = _map_->key_hash(entry->key); \
size_t original_pos = hash % _map_->capacity; \
size_t pos = original_pos; \
\
SNAME##_entry **scan = &(_map_->key_buffer[hash % _map_->capacity]); \
\
if (*scan == NULL) \
{ \
*scan = entry; \
\
return scan; \
} \
else \
{ \
while (true) \
{ \
pos++; \
scan = &(_map_->key_buffer[pos % _map_->capacity]); \
\
if (*scan == NULL || *scan == CMC_ENTRY_DELETED) \
{ \
if (!to_return) \
to_return = scan; \
\
*scan = entry; \
entry->key_dist = pos - original_pos; \
\
return to_return; \
} \
else if ((*scan)->key_dist < pos - original_pos) \
{ \
if (!to_return) \
to_return = scan; \
\
size_t tmp_dist = (*scan)->key_dist; \
entry->key_dist = pos - original_pos; \
original_pos = pos - tmp_dist; \
\
SNAME##_entry *_tmp_ = *scan; \
*scan = entry; \
entry = _tmp_; \
} \
} \
} \
\
return NULL; \
} \
\
static SNAME##_entry **PFX##_impl_add_entry_to_val(SNAME *_map_, SNAME##_entry *entry) \
{ \
SNAME##_entry **to_return = NULL; \
\
size_t hash = _map_->val_hash(entry->value); \
size_t original_pos = hash % _map_->capacity; \
size_t pos = original_pos; \
\
SNAME##_entry **scan = &(_map_->val_buffer[hash % _map_->capacity]); \
\
if (*scan == NULL) \
{ \
*scan = entry; \
\
return scan; \
} \
else \
{ \
while (true) \
{ \
pos++; \
scan = &(_map_->val_buffer[pos % _map_->capacity]); \
\
if (*scan == NULL || *scan == CMC_ENTRY_DELETED) \
{ \
if (!to_return) \
to_return = scan; \
\
*scan = entry; \
entry->val_dist = pos - original_pos; \
\
return to_return; \
} \
else if ((*scan)->val_dist < pos - original_pos) \
{ \
if (!to_return) \
to_return = scan; \
\
size_t tmp_dist = (*scan)->val_dist; \
entry->val_dist = pos - original_pos; \
original_pos = pos - tmp_dist; \
\
SNAME##_entry *_tmp_ = *scan; \
*scan = entry; \
entry = _tmp_; \
} \
} \
} \
\
return NULL; \
} \
\
static size_t PFX##_impl_calculate_size(size_t required) \
{ \
const size_t count = sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]); \
\
if (cmc_hashtable_primes[count - 1] < required) \
return required; \
\
size_t i = 0; \
while (cmc_hashtable_primes[i] < required) \
i++; \
\
return cmc_hashtable_primes[i]; \
} \
\
static SNAME##_iter PFX##_impl_it_start(SNAME *_map_) \
{ \
SNAME##_iter iter; \
\
PFX##_iter_init(&iter, _map_); \
\
return iter; \
} \
\
static SNAME##_iter PFX##_impl_it_end(SNAME *_map_) \
{ \
SNAME##_iter iter; \
\
PFX##_iter_init(&iter, _map_); \
PFX##_iter_to_end(&iter); \
\
return iter; \
}
#endif /* CMC_BIDIMAP_H */
+915 -804
View File
File diff suppressed because it is too large. Load diff
-384
View File
@@ -1,384 +0,0 @@
/**
* linkedqueue.h
*
* Creation Date: 21/06/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
/**
* A node-based Queue using a Singly Linked List
*
* enqueue : is equivalent to a push_back from a LinkedList
* dequeue : is equivalent to a pop_front from a LinkedList
*
* This Queue has a one-way iterator
*/
#ifndef CMC_LINKEDQUEUE_H
#define CMC_LINKEDQUEUE_H
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define LINKEDQUEUE_GENERATE(PFX, SNAME, FMOD, V) \
LINKEDQUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
LINKEDQUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
#define LINKEDQUEUE_WRAPGEN_HEADER(PFX, SNAME, FMOD, K, V) \
LINKEDQUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V)
#define LINKEDQUEUE_WRAPGEN_SOURCE(PFX, SNAME, FMOD, K, V) \
LINKEDQUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V)
/* HEADER ********************************************************************/
#define LINKEDQUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
\
/* Linked Queue Structure */ \
typedef struct SNAME##_s \
{ \
/* First node in the list */ \
struct SNAME##_node_s *head; \
\
/* Last node in the list */ \
struct SNAME##_node_s *tail; \
\
/* Current amount of elements in the list */ \
size_t count; \
\
/* Function that returns an iterator to the start of the list */ \
struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
\
} SNAME, *SNAME##_ptr; \
\
/* Singly-linked list node */ \
typedef struct SNAME##_node_s \
{ \
/* Node's data */ \
V data; \
\
/* Pointer to the next node on the linked list */ \
struct SNAME##_node_s *next; \
\
} SNAME##_node, *SNAME##_node_ptr; \
\
/* Linked Queue Iterator */ \
typedef struct SNAME##_iter_s \
{ \
/* Target Linked Queue */ \
struct SNAME##_s *target; \
\
/* Cursor's current node */ \
struct SNAME##_node_s *cursor; \
\
/* Keeps track of relative index to the iteration of elements */ \
size_t index; \
\
/* If the iterator is at the start of the iteration */ \
bool start; \
\
/* If the iterator has reached the end of the iteration */ \
bool end; \
\
} SNAME##_iter, *SNAME##_iter_ptr; \
\
/* Collection Functions */ \
/* Collection Allocation and Deallocation */ \
FMOD SNAME *PFX##_new(void); \
FMOD void PFX##_clear(SNAME *_lqueue_); \
FMOD void PFX##_free(SNAME *_lqueue_); \
/* Collection Input and Output */ \
FMOD bool PFX##_enqueue(SNAME *_lqueue_, V element); \
FMOD bool PFX##_dequeue(SNAME *_lqueue_); \
/* Conditional Input and Output */ \
FMOD bool PFX##_enqueue_if(SNAME *_lqueue_, V element, bool condition); \
FMOD bool PFX##_dequeue_if(SNAME *_lqueue_, bool condition); \
/* Element Access */ \
FMOD V PFX##_peek(SNAME *_lqueue_); \
/* Collection State */ \
FMOD bool PFX##_contains(SNAME *_lqueue_, V element, int (*comparator)(V, V)); \
FMOD bool PFX##_empty(SNAME *_lqueue_); \
FMOD size_t PFX##_count(SNAME *_lqueue_); \
\
/* Iterator Functions */ \
/* Iterator Allocation and Deallocation */ \
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \
FMOD void PFX##_iter_free(SNAME##_iter *iter); \
/* Iterator Initialization */ \
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \
/* Iterator State */ \
FMOD bool PFX##_iter_start(SNAME##_iter *iter); \
FMOD bool PFX##_iter_end(SNAME##_iter *iter); \
/* Iterator Movement */ \
FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \
FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \
FMOD bool PFX##_iter_next(SNAME##_iter *iter); \
/* Iterator Access */ \
FMOD V PFX##_iter_value(SNAME##_iter *iter); \
FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \
FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \
\
/* Default Value */ \
static inline V PFX##_impl_default_value(void) \
{ \
V _empty_value_; \
\
memset(&_empty_value_, 0, sizeof(V)); \
\
return _empty_value_; \
} \
\
/* SOURCE ********************************************************************/
#define LINKEDQUEUE_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \
\
/* Implementation Detail Functions */ \
FMOD SNAME##_node *PFX##_impl_new_node(V element); \
static SNAME##_iter PFX##_impl_it_start(SNAME *_lqueue_); \
\
FMOD SNAME *PFX##_new(void) \
{ \
SNAME *_lqueue_ = malloc(sizeof(SNAME)); \
\
if (!_lqueue_) \
return NULL; \
\
_lqueue_->count = 0; \
_lqueue_->head = NULL; \
_lqueue_->tail = NULL; \
\
_lqueue_->it_start = PFX##_impl_it_start; \
\
return _lqueue_; \
} \
\
FMOD void PFX##_clear(SNAME *_lqueue_) \
{ \
SNAME##_node *scan = _lqueue_->head; \
\
while (_lqueue_->head != NULL) \
{ \
_lqueue_->head = _lqueue_->head->next; \
free(scan); \
scan = _lqueue_->head; \
} \
\
_lqueue_->count = 0; \
_lqueue_->head = NULL; \
_lqueue_->tail = NULL; \
} \
\
FMOD void PFX##_free(SNAME *_lqueue_) \
{ \
PFX##_clear(_lqueue_); \
\
free(_lqueue_); \
} \
\
FMOD bool PFX##_enqueue(SNAME *_lqueue_, V element) \
{ \
SNAME##_node *_node_ = PFX##_impl_new_node(element); \
\
if (!_node_) \
return false; \
\
if (PFX##_empty(_lqueue_)) \
{ \
_lqueue_->head = _node_; \
_lqueue_->tail = _node_; \
} \
else \
{ \
_lqueue_->tail->next = _node_; \
_lqueue_->tail = _node_; \
} \
\
_lqueue_->count++; \
\
return true; \
} \
\
FMOD bool PFX##_dequeue(SNAME *_lqueue_) \
{ \
if (PFX##_empty(_lqueue_)) \
return false; \
\
SNAME##_node *_node_ = _lqueue_->head; \
_lqueue_->head = _lqueue_->head->next; \
\
free(_node_); \
\
if (_lqueue_->head == NULL) \
_lqueue_->tail = NULL; \
\
_lqueue_->count--; \
\
return true; \
} \
\
FMOD bool PFX##_enqueue_if(SNAME *_lqueue_, V element, bool condition) \
{ \
if (condition) \
return PFX##_enqueue(_lqueue_, element); \
\
return false; \
} \
\
FMOD bool PFX##_dequeue_if(SNAME *_lqueue_, bool condition) \
{ \
if (condition) \
return PFX##_dequeue(_lqueue_); \
\
return false; \
} \
\
FMOD V PFX##_peek(SNAME *_lqueue_) \
{ \
if (PFX##_empty(_lqueue_)) \
return PFX##_impl_default_value(); \
\
return _lqueue_->head->data; \
} \
\
FMOD bool PFX##_contains(SNAME *_lqueue_, V element, int (*comparator)(V, V)) \
{ \
SNAME##_node *scan = _lqueue_->head; \
\
while (scan != NULL) \
{ \
if (comparator(scan->data, element) == 0) \
return true; \
\
scan = scan->next; \
} \
\
return false; \
} \
\
FMOD bool PFX##_empty(SNAME *_lqueue_) \
{ \
return _lqueue_->count == 0; \
} \
\
FMOD size_t PFX##_count(SNAME *_lqueue_) \
{ \
return _lqueue_->count; \
} \
\
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \
{ \
SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \
\
if (!iter) \
return NULL; \
\
PFX##_iter_init(iter, target); \
\
return iter; \
} \
\
FMOD void PFX##_iter_free(SNAME##_iter *iter) \
{ \
free(iter); \
} \
\
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \
{ \
iter->target = target; \
iter->cursor = target->head; \
iter->index = 0; \
iter->start = true; \
iter->end = PFX##_empty(target); \
} \
\
FMOD bool PFX##_iter_start(SNAME##_iter *iter) \
{ \
return PFX##_empty(iter->target) || iter->start; \
} \
\
FMOD bool PFX##_iter_end(SNAME##_iter *iter) \
{ \
return PFX##_empty(iter->target) || iter->end; \
} \
\
FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \
{ \
iter->cursor = iter->target->head; \
iter->index = 0; \
iter->start = true; \
iter->end = PFX##_empty(iter->target); \
} \
\
FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \
{ \
iter->cursor = iter->target->tail; \
iter->index = iter->target->count - 1; \
iter->start = PFX##_empty(iter->target); \
iter->end = true; \
} \
\
FMOD bool PFX##_iter_next(SNAME##_iter *iter) \
{ \
if (iter->end) \
return false; \
\
iter->start = PFX##_empty(iter->target); \
\
if (iter->cursor->next == NULL) \
iter->end = true; \
else \
{ \
iter->cursor = iter->cursor->next; \
iter->index++; \
} \
\
return true; \
} \
\
FMOD V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return PFX##_impl_default_value(); \
\
return iter->cursor->data; \
} \
\
FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return NULL; \
\
return &(iter->cursor->data); \
} \
\
FMOD size_t PFX##_iter_index(SNAME##_iter *iter) \
{ \
return iter->index; \
} \
\
FMOD SNAME##_node *PFX##_impl_new_node(V element) \
{ \
SNAME##_node *_node_ = malloc(sizeof(SNAME##_node)); \
\
if (!_node_) \
return NULL; \
\
_node_->data = element; \
_node_->next = NULL; \
\
return _node_; \
} \
\
static SNAME##_iter PFX##_impl_it_start(SNAME *_lqueue_) \
{ \
SNAME##_iter iter; \
\
PFX##_iter_init(&iter, _lqueue_); \
PFX##_iter_to_start(&iter); \
\
return iter; \
}
#endif /* CMC_LINKEDQUEUE_H */
+1032 -829
View File
File diff suppressed because it is too large. Load diff
+1154 -983
View File
File diff suppressed because it is too large. Load diff
+690
View File
@@ -0,0 +1,690 @@
/**
* sortedlist.h
*
* Creation Date: 17/09/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
/**
* THIS IS ONLY A PREVIEW
*
* SortedList
*
* A sorted list is a dynamic array, meaning that you can store as many elements
* as you like and when its capacity is full, the buffer is reallocated. The
* elements are only sorted when a certain action requires that the array is
* sorted like accessing min() or max(). This prevents the array from being
* sorted after every insertion or removal of elements.
*/
#ifndef CMC_SORTEDLIST_H
#define CMC_SORTEDLIST_H
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../utl/cmc_string.h"
/* to_string format */
static const char *cmc_string_fmt_sortedlist = "%s at %p { buffer:%p, capacity:%" PRIuMAX ", count:%" PRIuMAX ", is_sorted:%s, cmp:%p }";
#define CMC_GENERATE_SORTEDLIST(PFX, SNAME, V) \
CMC_GENERATE_SORTEDLIST_HEADER(PFX, SNAME, V) \
CMC_GENERATE_SORTEDLIST_SOURCE(PFX, SNAME, V)
#define CMC_WRAPGEN_SORTEDLIST_HEADER(PFX, SNAME, K, V) \
CMC_GENERATE_SORTEDLIST_HEADER(PFX, SNAME, V)
#define CMC_WRAPGEN_SORTEDLIST_SOURCE(PFX, SNAME, K, V) \
CMC_GENERATE_SORTEDLIST_SOURCE(PFX, SNAME, V)
/* HEADER ********************************************************************/
#define CMC_GENERATE_SORTEDLIST_HEADER(PFX, SNAME, V) \
\
/* List Structure */ \
typedef struct SNAME##_s \
{ \
/* Dynamic array of elements */ \
V *buffer; \
\
/* Current array capacity */ \
size_t capacity; \
\
/* Current amount of elements */ \
size_t count; \
\
/* Flag if the list is sorted or not, used by lazy evaluation */ \
bool is_sorted; \
\
/* Element comparison function */ \
int (*cmp)(V, V); \
\
/* Function that returns an iterator to the start of the list */ \
struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
\
/* Function that returns an iterator to the end of the list */ \
struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
\
} SNAME, *SNAME##_ptr; \
\
/* List Iterator */ \
typedef struct SNAME##_iter_s \
{ \
/* Target list */ \
struct SNAME##_s *target; \
\
/* Cursor's position (index) */ \
size_t cursor; \
\
/* If the iterator has reached the start of the iteration */ \
bool start; \
\
/* If the iterator has reached the end of the iteration */ \
bool end; \
\
} SNAME##_iter, *SNAME##_iter_ptr; \
\
/* Collection Functions */ \
/* Collection Allocation and Deallocation */ \
SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)); \
void PFX##_clear(SNAME *_list_, void (*deallocator)(V)); \
void PFX##_free(SNAME *_list_, void (*deallocator)(V)); \
/* Collection Input and Output */ \
bool PFX##_insert(SNAME *_list_, V element); \
bool PFX##_remove(SNAME *_list_, size_t index); \
/* Element Access */ \
bool PFX##_max(SNAME *_list_, V *result); \
bool PFX##_min(SNAME *_list_, V *result); \
V PFX##_get(SNAME *_list_, size_t index); \
size_t PFX##_indexof(SNAME *_list_, V element, bool from_start); \
/* Collection State */ \
bool PFX##_contains(SNAME *_list_, V element); \
bool PFX##_empty(SNAME *_list_); \
bool PFX##_full(SNAME *_list_); \
size_t PFX##_count(SNAME *_list_); \
size_t PFX##_capacity(SNAME *_list_); \
/* Collection Utility */ \
bool PFX##_resize(SNAME *_list_, size_t capacity); \
void PFX##_sort(SNAME *_list_); \
SNAME *PFX##_copy_of(SNAME *_list_, V (*copy_func)(V)); \
bool PFX##_equals(SNAME *_list1_, SNAME *_list2_); \
cmc_string PFX##_to_string(SNAME *_list_); \
\
/* Iterator Functions */ \
/* Iterator Allocation and Deallocation */ \
SNAME##_iter *PFX##_iter_new(SNAME *target); \
void PFX##_iter_free(SNAME##_iter *iter); \
/* Iterator Initialization */ \
void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \
/* Iterator State */ \
bool PFX##_iter_start(SNAME##_iter *iter); \
bool PFX##_iter_end(SNAME##_iter *iter); \
/* Iterator Movement */ \
void PFX##_iter_to_start(SNAME##_iter *iter); \
void PFX##_iter_to_end(SNAME##_iter *iter); \
bool PFX##_iter_next(SNAME##_iter *iter); \
bool PFX##_iter_prev(SNAME##_iter *iter); \
bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \
bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \
bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \
/* Iterator Access */ \
V PFX##_iter_value(SNAME##_iter *iter); \
size_t PFX##_iter_index(SNAME##_iter *iter); \
\
/* SOURCE ********************************************************************/
#define CMC_GENERATE_SORTEDLIST_SOURCE(PFX, SNAME, V) \
\
/* Implementation Detail Functions */ \
static size_t PFX##_impl_binary_search_first(SNAME *_list_, V value); \
static size_t PFX##_impl_binary_search_last(SNAME *_list_, V value); \
void PFX##_impl_sort_quicksort(V *array, int (*cmp)(V, V), size_t low, size_t high); \
void PFX##_impl_sort_insertion(V *array, int (*cmp)(V, V), size_t low, size_t high); \
static SNAME##_iter PFX##_impl_it_start(SNAME *_list_); \
static SNAME##_iter PFX##_impl_it_end(SNAME *_list_); \
\
SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)) \
{ \
if (capacity < 1) \
return NULL; \
\
SNAME *_list_ = malloc(sizeof(SNAME)); \
\
if (!_list_) \
return NULL; \
\
_list_->buffer = calloc(capacity, sizeof(V)); \
\
if (!_list_->buffer) \
{ \
free(_list_); \
return NULL; \
} \
\
_list_->capacity = capacity; \
_list_->count = 0; \
_list_->cmp = compare; \
_list_->is_sorted = false; \
\
_list_->it_start = PFX##_impl_it_start; \
_list_->it_end = PFX##_impl_it_end; \
\
return _list_; \
} \
\
void PFX##_clear(SNAME *_list_, void (*deallocator)(V)) \
{ \
if (deallocator) \
{ \
for (size_t i = 0; i < _list_->count; i++) \
deallocator(_list_->buffer[i]); \
} \
\
memset(_list_->buffer, 0, sizeof(V) * _list_->capacity); \
\
_list_->count = 0; \
} \
\
void PFX##_free(SNAME *_list_, void (*deallocator)(V)) \
{ \
if (deallocator) \
{ \
for (size_t i = 0; i < _list_->count; i++) \
deallocator(_list_->buffer[i]); \
} \
\
free(_list_->buffer); \
free(_list_); \
} \
\
bool PFX##_insert(SNAME *_list_, V element) \
{ \
if (PFX##_full(_list_)) \
{ \
if (!PFX##_resize(_list_, PFX##_capacity(_list_) * 2)) \
return false; \
} \
\
_list_->buffer[_list_->count++] = element; \
\
_list_->is_sorted = false; \
\
return true; \
} \
\
bool PFX##_remove(SNAME *_list_, size_t index) \
{ \
if (index >= _list_->count) \
return false; \
\
memmove(_list_->buffer + index, _list_->buffer + index + 1, \
(_list_->count - index) * sizeof(V)); \
\
_list_->buffer[--_list_->count] = (V){0}; \
\
return true; \
} \
\
bool PFX##_min(SNAME *_list_, V *result) \
{ \
if (PFX##_empty(_list_)) \
return false; \
\
PFX##_sort(_list_); \
\
*result = _list_->buffer[0]; \
\
return true; \
} \
\
bool PFX##_max(SNAME *_list_, V *result) \
{ \
if (PFX##_empty(_list_)) \
return false; \
\
PFX##_sort(_list_); \
\
*result = _list_->buffer[_list_->count - 1]; \
\
return true; \
} \
\
V PFX##_get(SNAME *_list_, size_t index) \
{ \
if (index >= _list_->count) \
return (V){0}; \
\
PFX##_sort(_list_); \
\
return _list_->buffer[index]; \
} \
\
size_t PFX##_indexof(SNAME *_list_, V element, bool from_start) \
{ \
PFX##_sort(_list_); \
\
if (from_start) \
{ \
return PFX##_impl_binary_search_first(_list_, element); \
} \
\
return PFX##_impl_binary_search_last(_list_, element); \
} \
\
bool PFX##_contains(SNAME *_list_, V element) \
{ \
if (PFX##_empty(_list_)) \
return false; \
\
PFX##_sort(_list_); \
\
return PFX##_impl_binary_search_first(_list_, element) < PFX##_count(_list_); \
} \
\
bool PFX##_empty(SNAME *_list_) \
{ \
return _list_->count == 0; \
} \
\
bool PFX##_full(SNAME *_list_) \
{ \
return _list_->count >= _list_->capacity; \
} \
\
size_t PFX##_count(SNAME *_list_) \
{ \
return _list_->count; \
} \
\
size_t PFX##_capacity(SNAME *_list_) \
{ \
return _list_->capacity; \
} \
\
bool PFX##_resize(SNAME *_list_, size_t capacity) \
{ \
if (PFX##_capacity(_list_) == capacity) \
return true; \
\
if (capacity < PFX##_count(_list_)) \
return false; \
\
V *new_buffer = realloc(_list_->buffer, sizeof(V) * capacity); \
\
if (!new_buffer) \
return false; \
\
_list_->buffer = new_buffer; \
_list_->capacity = capacity; \
\
return true; \
} \
\
void PFX##_sort(SNAME *_list_) \
{ \
if (!_list_->is_sorted && _list_->count > 1) \
{ \
PFX##_impl_sort_quicksort(_list_->buffer, _list_->cmp, 0, _list_->count - 1); \
\
_list_->is_sorted = true; \
} \
} \
\
SNAME *PFX##_copy_of(SNAME *_list_, V (*copy_func)(V)) \
{ \
SNAME *result = PFX##_new(_list_->capacity, _list_->cmp); \
\
if (!result) \
return NULL; \
\
if (copy_func) \
{ \
for (size_t i = 0; i < _list_->count; i++) \
result->buffer[i] = copy_func(_list_->buffer[i]); \
} \
else \
memcpy(result->buffer, _list_->buffer, sizeof(V) * _list_->count); \
\
result->count = _list_->count; \
\
return result; \
} \
\
bool PFX##_equals(SNAME *_list1_, SNAME *_list2_) \
{ \
if (PFX##_count(_list1_) != PFX##_count(_list2_)) \
return false; \
\
for (size_t i = 0; i < PFX##_count(_list1_); i++) \
{ \
if (_list1_->cmp(_list1_->buffer[i], _list2_->buffer[i]) != 0) \
return false; \
} \
\
return false; \
} \
\
cmc_string PFX##_to_string(SNAME *_list_) \
{ \
cmc_string str; \
SNAME *l_ = _list_; \
const char *name = #SNAME; \
\
snprintf(str.s, cmc_string_len, cmc_string_fmt_sortedlist, \
name, l_, l_->buffer, l_->capacity, l_->count, \
l_->is_sorted ? "true" : "false", l_->cmp); \
\
return str; \
} \
\
SNAME##_iter *PFX##_iter_new(SNAME *target) \
{ \
SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \
\
if (!iter) \
return NULL; \
\
PFX##_iter_init(iter, target); \
\
return iter; \
} \
\
void PFX##_iter_free(SNAME##_iter *iter) \
{ \
free(iter); \
} \
\
void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \
{ \
PFX##_sort(target); \
\
iter->target = target; \
iter->cursor = 0; \
iter->start = true; \
iter->end = PFX##_empty(target); \
} \
\
bool PFX##_iter_start(SNAME##_iter *iter) \
{ \
return PFX##_empty(iter->target) || iter->start; \
} \
\
bool PFX##_iter_end(SNAME##_iter *iter) \
{ \
return PFX##_empty(iter->target) || iter->end; \
} \
\
void PFX##_iter_to_start(SNAME##_iter *iter) \
{ \
if (!PFX##_empty(iter->target)) \
{ \
iter->cursor = 0; \
iter->start = true; \
iter->end = PFX##_empty(iter->target); \
} \
} \
\
void PFX##_iter_to_end(SNAME##_iter *iter) \
{ \
if (!PFX##_empty(iter->target)) \
{ \
iter->start = PFX##_empty(iter->target); \
iter->cursor = PFX##_empty(iter->target) ? 0 : iter->target->count - 1; \
iter->end = true; \
} \
} \
\
bool PFX##_iter_next(SNAME##_iter *iter) \
{ \
if (iter->end) \
return false; \
\
if (iter->cursor + 1 == PFX##_count(iter->target)) \
{ \
iter->end = true; \
return false; \
} \
\
iter->start = PFX##_empty(iter->target); \
\
iter->cursor++; \
\
return true; \
} \
\
bool PFX##_iter_prev(SNAME##_iter *iter) \
{ \
if (iter->start) \
return false; \
\
if (iter->cursor == 0) \
{ \
iter->start = true; \
return false; \
} \
\
iter->end = PFX##_empty(iter->target); \
\
iter->cursor--; \
\
return true; \
} \
\
/* Returns true only if the iterator moved */ \
bool PFX##_iter_advance(SNAME##_iter *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 >= PFX##_count(iter->target)) \
return false; \
\
iter->start = PFX##_empty(iter->target); \
\
iter->cursor += steps; \
\
return true; \
} \
\
/* Returns true only if the iterator moved */ \
bool PFX##_iter_rewind(SNAME##_iter *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 = 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 PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \
{ \
if (index >= PFX##_count(iter->target)) \
return false; \
\
if (iter->cursor > index) \
return PFX##_iter_rewind(iter, iter->cursor - index); \
else if (iter->cursor < index) \
return PFX##_iter_advance(iter, index - iter->cursor); \
\
return true; \
} \
\
V PFX##_iter_value(SNAME##_iter *iter) \
{ \
if (PFX##_empty(iter->target)) \
return (V){0}; \
\
return iter->target->buffer[iter->cursor]; \
} \
\
size_t PFX##_iter_index(SNAME##_iter *iter) \
{ \
return iter->cursor; \
} \
\
static size_t PFX##_impl_binary_search_first(SNAME *_list_, V value) \
{ \
if (PFX##_empty(_list_)) \
return 1; \
\
size_t L = 0; \
size_t R = PFX##_count(_list_); \
\
while (L < R) \
{ \
size_t M = L + (R - L) / 2; \
\
if (_list_->cmp(_list_->buffer[M], value) < 0) \
L = M + 1; \
else \
R = M; \
} \
\
if (_list_->cmp(_list_->buffer[L], value) == 0) \
return L; \
\
/* Not found */ \
return PFX##_count(_list_); \
} \
\
static size_t PFX##_impl_binary_search_last(SNAME *_list_, V value) \
{ \
if (PFX##_empty(_list_)) \
return 1; \
\
size_t L = 0; \
size_t R = PFX##_count(_list_); \
\
while (L < R) \
{ \
size_t M = L + (R - L) / 2; \
\
if (_list_->cmp(_list_->buffer[M], value) > 0) \
R = M; \
else \
L = M + 1; \
} \
\
if (_list_->cmp(_list_->buffer[L - 1], value) == 0) \
return L - 1; \
\
/* Not found */ \
return PFX##_count(_list_); \
} \
\
/* Characteristics of this quicksort implementation: */ \
/* - Hybrid: uses insertion sort for small arrays */ \
/* - Partition: Lomuto's Method (can be optimized and use Hoare's Method) */ \
/* - Tail recursion: minimize recursion depth */ \
void PFX##_impl_sort_quicksort(V *array, int (*cmp)(V, V), size_t low, size_t high) \
{ \
while (low < high) \
{ \
/* Quicksort performs poorly for smaller arrays so let insertion */ \
/* sort do the job */ \
if (high - low < 10) \
{ \
PFX##_impl_sort_insertion(array, cmp, low, high); \
break; \
} \
else \
{ \
/* Partition */ \
V pivot = array[high]; \
\
size_t pindex = low; \
\
for (size_t i = low; i < high; i++) \
{ \
if (cmp(array[i], pivot) <= 0) \
{ \
V _tmp_ = array[i]; \
array[i] = array[pindex]; \
array[pindex] = _tmp_; \
\
pindex++; \
} \
} \
\
V _tmp_ = array[pindex]; \
array[pindex] = array[high]; \
array[high] = _tmp_; \
\
/* Tail recursion */ \
if (pindex - low < high - pindex) \
{ \
PFX##_impl_sort_quicksort(array, cmp, low, pindex - 1); \
\
low = pindex + 1; \
} \
else \
{ \
PFX##_impl_sort_quicksort(array, cmp, pindex + 1, high); \
\
high = pindex - 1; \
} \
} \
} \
} \
\
void PFX##_impl_sort_insertion(V *array, int (*cmp)(V, V), size_t low, size_t high) \
{ \
for (size_t i = low + 1; i <= high; i++) \
{ \
V _tmp_ = array[i]; \
size_t j = i; \
\
while (j > low && cmp(array[j - 1], _tmp_) > 0) \
{ \
array[j] = array[j - 1]; \
j--; \
} \
\
array[j] = _tmp_; \
} \
} \
\
static SNAME##_iter PFX##_impl_it_start(SNAME *_list_) \
{ \
SNAME##_iter iter; \
\
PFX##_iter_init(&iter, _list_); \
PFX##_iter_to_start(&iter); \
\
return iter; \
} \
\
static SNAME##_iter PFX##_impl_it_end(SNAME *_list_) \
{ \
SNAME##_iter iter; \
\
PFX##_iter_init(&iter, _list_); \
PFX##_iter_to_end(&iter); \
\
return iter; \
}
#endif /* CMC_SORTEDLIST_H */
+12 -15
View File
@@ -8,26 +8,24 @@
*
*/
#ifndef CMC_MACRO_COLLECTIONS
#define CMC_MACRO_COLLECTIONS
#ifndef CMC_MACRO_COLLECTIONS_H
#define CMC_MACRO_COLLECTIONS_H
#define CMC_CONCATH_(C) C##_WRAPGEN_HEADER
#define CMC_CONCATC_(C) C##_WRAPGEN_SOURCE
#define CMC_CONCATH_(C) CMC_WRAPGEN_##C##_HEADER
#define CMC_CONCATC_(C) CMC_WRAPGEN_##C##_SOURCE
#define CMC_CONCATH(C) CMC_CONCATH_(C)
#define CMC_CONCATC(C) CMC_CONCATC_(C)
#define COLLECTION_GENERATE(C, PFX, SNAME, FMOD, K, V) \
COLLECTION_GENERATE_HEADER(C, PFX, SNAME, FMOD, K, V) \
COLLECTION_GENERATE_SOURCE(C, PFX, SNAME, FMOD, K, V)
#define 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)
#define COLLECTION_GENERATE_HEADER(C, PFX, SNAME, FMOD, K, V) \
CMC_CONCATH(C) \
(PFX, SNAME, FMOD, K, V)
#define CMC_COLLECTION_GENERATE_HEADER(C, PFX, SNAME, K, V) \
CMC_CONCATH(C)(PFX, SNAME, K, V)
#define COLLECTION_GENERATE_SOURCE(C, PFX, SNAME, FMOD, K, V) \
CMC_CONCATC(C) \
(PFX, SNAME, FMOD, K, V)
#define CMC_COLLECTION_GENERATE_SOURCE(C, PFX, SNAME, K, V) \
CMC_CONCATC(C)(PFX, SNAME, K, V)
#include "cmc/deque.h"
#include "cmc/hashmap.h"
@@ -41,7 +39,6 @@
#include "cmc/treeset.h"
#include "ext/intervalheap.h"
#include "ext/linkedqueue.h"
#include "ext/multimap.h"
#include "ext/multiset.h"
@@ -54,4 +51,4 @@
#include "utl/test.h"
#include "utl/timer.h"
#endif /* CMC_MACRO_COLLECTIONS */
#endif /* CMC_MACRO_COLLECTIONS_H */
+1357 -902
View File
File diff suppressed because it is too large. Load diff
+1 -17
View File
@@ -13,8 +13,8 @@
#ifndef CMC_STRING_H
#define CMC_STRING_H
#include <stddef.h>
#include <inttypes.h>
#include <stddef.h>
static const size_t cmc_string_len = 200;
@@ -23,20 +23,4 @@ typedef struct cmc_string_s
char s[200];
} cmc_string;
/* to_string formats */
static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRIuMAX ", count:%" PRIuMAX ", front:%" PRIuMAX ", back:%" PRIuMAX " }";
static const char *cmc_string_fmt_hashmap = "%s at %p { buffer:%p, capacity:%" PRIuMAX ", count:%" PRIuMAX ", load:%lf, cmp:%p, hash:%p }";
static const char *cmc_string_fmt_hashset = "%s at %p { buffer:%p, capacity:%" PRIuMAX ", count:%" PRIuMAX ", load:%lf, cmp:%p, hash:%p }";
static const char *cmc_string_fmt_heap = "%s at %p { buffer:%p, capacity:%" PRIuMAX ", count:%" PRIuMAX ", type:%s, cmp:%p }";
static const char *cmc_string_fmt_linkedlist = "%s at %p { count:%" PRIuMAX ", head:%p, tail:%p }";
static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIuMAX ", count:%" PRIuMAX " }";
static const char *cmc_string_fmt_queue = "%s at %p { buffer:%p, capacity:%" PRIuMAX ", count:%" PRIuMAX ", front:%" PRIuMAX ", back:%" PRIuMAX " }";
static const char *cmc_string_fmt_stack = "%s at %p { buffer:%p, capacity:%" PRIuMAX ", count:%" PRIuMAX " }";
static const char *cmc_string_fmt_treemap = "%s at %p { root:%p, count:%" PRIuMAX ", cmp:%p }";
static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMAX ", cmp:%p }";
static const char *cmc_string_fmt_intervalheap = "%s at %p { buffer:%p, capacity:%" PRIuMAX ", size:%" PRIuMAX ", count:%" PRIuMAX ", cmp:%p }";
static const char *cmc_string_fmt_multimap = "%s at %p { buffer:%p, capacity:%" PRIuMAX ", count:%" PRIuMAX ", load:%lf, cmp:%p, hash:%p }";
static const char *cmc_string_fmt_multiset = "%s at %p { buffer:%p, capacity:%" PRIuMAX ", count:%" PRIuMAX ", cardinality:%" PRIuMAX ", load:%lf, cmp:%p, hash:%p }";;
#endif /* CMC_STRING_H */
+17 -23
View File
@@ -8,31 +8,25 @@
*
*/
/**
* ForEach utility
*
* Read Documentation.md for more information
*/
#ifndef CMC_FOR_EACH_H
#define CMC_FOR_EACH_H
#ifndef CMC_FOR_EACH
#define CMC_FOR_EACH
#define FOR_EACH(PFX, SNAME, TARGET, BODY) \
do \
{ \
for (SNAME##_iter iter = TARGET->it_start(TARGET); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
{ \
BODY; \
} \
#define CMC_FOR_EACH(PFX, SNAME, TARGET, BODY) \
do \
{ \
for (SNAME##_iter iter = (TARGET)->it_start(TARGET); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \
{ \
BODY; \
} \
} while (0)
#define FOR_EACH_REV(PFX, SNAME, TARGET, BODY) \
do \
{ \
for (SNAME##_iter iter = TARGET->it_end(TARGET); !PFX##_iter_start(&iter); PFX##_iter_prev(&iter)) \
{ \
BODY; \
} \
#define CMC_FOR_EACH_REV(PFX, SNAME, TARGET, BODY) \
do \
{ \
for (SNAME##_iter iter = (TARGET)->it_end(TARGET); !PFX##_iter_start(&iter); PFX##_iter_prev(&iter)) \
{ \
BODY; \
} \
} while (0)
#endif /* CMC_FOR_EACH */
#endif /* CMC_FOR_EACH_H */
+15 -15
View File
@@ -83,25 +83,25 @@ static struct
} cmc_log_config = {0, 0, true, true, NULL, true};
typedef enum cmc_log_type_e
enum cmc_log_type
{
LOG_TRACE = 1,
LOG_DEBUG = 2,
LOG_INFO = 3,
LOG_WARN = 4,
LOG_ERROR = 5,
LOG_FATAL = 6
CMC_LOG_TRACE = 1,
CMC_LOG_DEBUG = 2,
CMC_LOG_INFO = 3,
CMC_LOG_WARN = 4,
CMC_LOG_ERROR = 5,
CMC_LOG_FATAL = 6
} cmc_log_type;
};
#define log_trace(fmt, ...) cmc_log(LOG_TRACE, __FILE__, __func__, __LINE__, fmt, __VA_ARGS__)
#define log_debug(fmt, ...) cmc_log(LOG_DEBUG, __FILE__, __func__, __LINE__, fmt, __VA_ARGS__)
#define log_info(fmt, ...) cmc_log(LOG_INFO, __FILE__, __func__, __LINE__, fmt, __VA_ARGS__)
#define log_warn(fmt, ...) cmc_log(LOG_WARN, __FILE__, __func__, __LINE__, fmt, __VA_ARGS__)
#define log_error(fmt, ...) cmc_log(LOG_ERROR, __FILE__, __func__, __LINE__, fmt, __VA_ARGS__)
#define log_fatal(fmt, ...) cmc_log(LOG_FATAL, __FILE__, __func__, __LINE__, fmt, __VA_ARGS__)
#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(cmc_log_type log, const char *filename, const char *funcname, int line, const char *fmt, ...)
static void cmc_log(enum cmc_log_type log, const char *filename, const char *funcname, int line, const char *fmt, ...)
{
if (!cmc_log_config.enabled)
return;
+44 -47
View File
@@ -11,6 +11,10 @@
/**
* Simple Unit Test Utility
*
* Required imports:
* - assert.h (to integrate with the cmc_assert_state variable)
* - timer.h (to calculate the execution time for the unit test)
*
* CMC_CREATE_UNIT
* Create a UnitTest
* Parameters:
@@ -42,6 +46,7 @@
#ifndef CMC_TEST_H
#define CMC_TEST_H
#include "assert.h"
#include "timer.h"
#include <inttypes.h>
#include <stdbool.h>
@@ -54,14 +59,14 @@
static const char *cmc_test_color[] = {"\x1b[32m", "\x1b[31m", "\x1b[35m"};
#endif
typedef struct cmc_test_info_s
struct cmc_test_info
{
uintmax_t total;
uintmax_t passed;
uintmax_t failed;
bool aborted;
bool verbose;
} cmc_test_info;
};
/* Logging function */
static void cmc_test_log(const char *unit_name, const char *current_test, bool aborted, bool passed)
@@ -92,23 +97,25 @@ static void cmc_test_log(const char *unit_name, const char *current_test, bool a
}
#define CMC_CREATE_UNIT(UNAME, VERBOSE, BODY) \
void UNAME(void) \
uintmax_t UNAME(void) \
{ \
const char *unit_name = #UNAME; \
const char *current_test = NULL; \
\
cmc_test_info tinfo = {0}; \
struct cmc_test_info tinfo = {0}; \
cmc_timer timer = {0}; \
\
tinfo.verbose = VERBOSE; \
\
/* Tests */ \
timer_start(timer); \
BODY; \
timer_stop(timer); \
timer_calc(timer); \
cmc_timer_start(timer); \
\
unittest_abort: \
BODY; \
\
cmc_timer_stop(timer); \
cmc_timer_calc(timer); \
\
unittest_abort: \
if (tinfo.aborted) \
{ \
cmc_test_log(unit_name, current_test, true, false); \
@@ -122,51 +129,41 @@ static void cmc_test_log(const char *unit_name, const char *current_test, bool a
printf("| |\n"); \
printf("| Total Unit Test Runtime : %9.0f milliseconds |\n", timer.result); \
printf("+--------------------------------------------------+\n"); \
\
return tinfo.failed; \
}
#define CMC_CREATE_TEST(TNAME, BODY) \
do \
{ \
current_test = #TNAME; \
\
tinfo.total += 1; \
\
BODY; \
\
} while (0)
#define CMC_TEST_PASS() \
do \
{ \
tinfo.passed += 1; \
if (tinfo.verbose) \
cmc_test_log(unit_name, current_test, false, true); \
\
} while (0)
#define CMC_TEST_FAIL() \
do \
{ \
tinfo.failed += 1; \
if (tinfo.verbose) \
cmc_test_log(unit_name, current_test, false, false); \
\
} while (0)
#define CMC_TEST_PASS_ELSE_FAIL(EXPRESSION) \
do \
{ \
if (EXPRESSION) \
CMC_TEST_PASS(); \
else \
CMC_TEST_FAIL(); \
\
#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); \
} \
} \
\
} while (0)
#define CMC_TEST_ABORT() \
do \
{ \
\
tinfo.aborted = true; \
tinfo.total -= 1; \
goto unittest_abort; \
+8 -8
View File
@@ -22,7 +22,7 @@ typedef struct cmc_timer_s
double result;
} cmc_timer;
#define timer_start(timer) \
#define cmc_timer_start(timer) \
do \
{ \
cmc_timer *t = &(timer); \
@@ -30,15 +30,15 @@ typedef struct cmc_timer_s
\
} while (0)
#define timer_stop(timer) \
do \
{ \
cmc_timer *t = &(timer);\
t->stop = clock(); \
\
#define cmc_timer_stop(timer) \
do \
{ \
cmc_timer *t = &(timer); \
t->stop = clock(); \
\
} while (0)
#define timer_calc(timer) \
#define cmc_timer_calc(timer) \
do \
{ \
cmc_timer *t = &(timer); \
+20 -12
View File
@@ -1,17 +1,25 @@
CC = gcc
CFLAGS = -std=c11 -Wall -Wextra
CFLAGS += -Wno-unused-function -Wno-unused-paramter -Wno-unused-variable -Wno-unused-label
CFLAGS += -Wno-unused-function -Wno-unused-parameter -Wno-unused-variable -Wno-unused-label
main:
$(CC) foreach.c -o foreach $(CFLAGS)
./foreach
$(CC) iterators.c -o iterators $(CFLAGS)
./iterators
$(CC) contains.c -o contains $(CFLAGS)
./contains
$(CC) types.c -o types $(CFLAGS)
./types
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
$(CC) -c ./sep/sep.c -o ./sep/sep.o $(CFLAGS)
$(CC) -c ./sep/main.c -o ./sep/main.o $(CFLAGS)
$(CC) ./sep/sep.o ./sep/main.o -o ./sep/sep
./sep/sep
$(CC) ./sep/sep.o ./sep/main.o -o ./sep/sep.exe
./sep/sep.exe
dev: main
rm *.exe ./sep/*.o ./sep/*.exe
windev: main
del *.exe .\\sep\\*.o .\\sep\\*.exe
FORCE:
+2 -1
View File
@@ -1,6 +1,7 @@
# Tests
* `main` - Unit tests for the main C Macro Collections library with code coverage;
* `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;
+24
View File
@@ -0,0 +1,24 @@
CC = gcc
CFLAGS = -std=c11 -Wall -Wextra
CFLAGS += -Wno-unused-function -Wno-unused-parameter -Wno-unused-variable -Wno-unused-label
CVFLAGS = --coverage -O0
INCLUDE = ../../src/
main: FORCE
$(CC) main.c -o main $(CFLAGS) $(CVFLAGS) -I $(INCLUDE)
./main
gcov ./main.c
dev: FORCE
$(CC) main.c -o main $(CFLAGS) $(CVFLAGS) -I $(INCLUDE)
./main
gcov ./main.c -n
rm *.gcda *.gcno *.exe
windev: FORCE
$(CC) main.c -o main $(CFLAGS) $(CVFLAGS) -I $(INCLUDE)
./main
gcov ./main.c -n
del *.gcda *.gcno *.exe
FORCE:
+7
View File
@@ -0,0 +1,7 @@
# codecov
In order to provide a good code coverage, all macros have been expanded and added to `src/*.c`.
* `src` - Since gcov fails to detect code that was expanded by macro, all collections where manually expanded and dumped into their respective source files;
* `unt` - Unit Tests;
* `main.c` - Where all tests are compiled together and called by main().
+35
View File
@@ -0,0 +1,35 @@
#include "unt/deque.c"
#include "unt/hashmap.c"
#include "unt/hashset.c"
#include "unt/heap.c"
#include "unt/linkedlist.c"
#include "unt/list.c"
#include "unt/queue.c"
#include "unt/stack.c"
#include "unt/treemap.c"
#include "unt/treeset.c"
#include "unt/multimap.c"
#include "unt/multiset.c"
int main(void)
{
uintmax_t failed = 0;
failed += deque_test();
failed += hashmap_test();
failed += hashset_test();
failed += heap_test();
failed += linkedlist_test();
failed += list_test();
failed += queue_test();
failed += stack_test();
failed += treemap_test();
failed += treeset_test();
/* ext */
failed += multimap_test();
failed += multiset_test();
return failed;
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+61
View File
@@ -0,0 +1,61 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/deque.c"
CMC_CREATE_UNIT(deque_test, false, {
CMC_CREATE_TEST(new, {
deque *d = d_new(1000000);
cmc_assert_not_equals(ptr, NULL, d);
cmc_assert_not_equals(ptr, NULL, d->buffer);
cmc_assert_equals(size_t, 1000000, d->capacity);
cmc_assert_equals(size_t, 0, d_count(d));
d_free(d);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
deque *d = d_new(0);
cmc_assert_equals(ptr, NULL, d);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
deque *d = d_new(UINT64_MAX);
cmc_assert_equals(ptr, NULL, d);
});
CMC_CREATE_TEST(clear[count capacity], {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
for (size_t i = 0; i < 50; i++)
d_push_back(d, i);
cmc_assert_equals(size_t, 50, d_count(d));
d_clear(d);
cmc_assert_equals(size_t, 0, d_count(d));
cmc_assert_equals(size_t, 100, d_capacity(d));
d_free(d);
});
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
deque *d = d_new(1);
cmc_assert_not_equals(ptr, NULL, d);
for (size_t i = 0; i < 50; i++)
d_push_back(d, i);
cmc_assert_equals(size_t, 50, d_count(d));
cmc_assert_lesser_equals(size_t, d_capacity(d), d_count(d));
d_free(d);
});
});
+48
View File
@@ -0,0 +1,48 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/hashmap.c"
#include "utl.c"
CMC_CREATE_UNIT(hashmap_test, false, {
CMC_CREATE_TEST(new, {
hashmap *map = hm_new(943722, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_not_equals(ptr, NULL, map->buffer);
cmc_assert_equals(size_t, 0, hm_count(map));
cmc_assert_greater_equals(size_t, (943722 / 0.6), hm_capacity(map));
hm_free(map);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
hashmap *map = hm_new(0, 0.6, cmp, hash);
cmc_assert_equals(ptr, NULL, map);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
hashmap *map = hm_new(UINT64_MAX, 0.6, cmp, hash);
cmc_assert_equals(ptr, NULL, map);
});
CMC_CREATE_TEST(clear[count capacity], {
hashmap *map = hm_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 50; i++)
hm_insert(map, i, i);
cmc_assert_equals(size_t, 50, hm_count(map));
hm_clear(map);
cmc_assert_equals(size_t, 0, hm_count(map));
hm_free(map);
});
});
+48
View File
@@ -0,0 +1,48 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/hashset.c"
#include "utl.c"
CMC_CREATE_UNIT(hashset_test, false, {
CMC_CREATE_TEST(new, {
hashset *set = hs_new(943722, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
cmc_assert_not_equals(ptr, NULL, set->buffer);
cmc_assert_equals(size_t, 0, hs_count(set));
cmc_assert_greater_equals(size_t, (943722 / 0.6), hs_capacity(set));
hs_free(set);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
hashset *set = hs_new(0, 0.6, cmp, hash);
cmc_assert_equals(ptr, NULL, set);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
hashset *set = hs_new(UINT64_MAX, 0.6, cmp, hash);
cmc_assert_equals(ptr, NULL, set);
});
CMC_CREATE_TEST(clear[count capacity], {
hashset *set = hs_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
for (size_t i = 0; i < 50; i++)
hs_insert(set, i);
cmc_assert_equals(size_t, 50, hs_count(set));
hs_clear(set);
cmc_assert_equals(size_t, 0, hs_count(set));
hs_free(set);
});
});
+62
View File
@@ -0,0 +1,62 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/heap.c"
#include "utl.c"
CMC_CREATE_UNIT(heap_test, false, {
CMC_CREATE_TEST(new, {
heap *h = h_new(1000000, cmc_max_heap, cmp);
cmc_assert_not_equals(ptr, NULL, h);
cmc_assert_not_equals(ptr, NULL, h->buffer);
cmc_assert_equals(size_t, 1000000, h_capacity(h));
cmc_assert_equals(size_t, 0, h_count(h));
h_free(h);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
heap *h = h_new(0, cmc_max_heap, cmp);
cmc_assert_equals(ptr, NULL, h);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
heap *h = h_new(UINT64_MAX, cmc_max_heap, cmp);
cmc_assert_equals(ptr, NULL, h);
});
CMC_CREATE_TEST(clear[count capacity], {
heap *h = h_new(100, cmc_max_heap, cmp);
cmc_assert_not_equals(ptr, NULL, h);
for (size_t i = 0; i < 50; i++)
h_insert(h, i);
cmc_assert_equals(size_t, 50, h_count(h));
h_clear(h);
cmc_assert_equals(size_t, 0, h_count(h));
cmc_assert_equals(size_t, 100, h_capacity(h));
h_free(h);
});
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
heap *h = h_new(1, cmc_max_heap, cmp);
cmc_assert_not_equals(ptr, NULL, h);
for (size_t i = 0; i < 50; i++)
h_insert(h, i);
cmc_assert_equals(size_t, 50, h_count(h));
h_free(h);
});
});
+74
View File
@@ -0,0 +1,74 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/linkedlist.c"
CMC_CREATE_UNIT(linkedlist_test, false, {
CMC_CREATE_TEST(new, {
linkedlist *ll = ll_new();
cmc_assert_not_equals(ptr, NULL, ll);
cmc_assert_equals(size_t, 0, ll_count(ll));
cmc_assert_equals(ptr, NULL, ll->head);
cmc_assert_equals(ptr, NULL, ll->tail);
ll_free(ll);
});
CMC_CREATE_TEST(clear[count capacity], {
linkedlist *ll = ll_new();
cmc_assert_not_equals(ptr, NULL, ll);
for (size_t i = 0; i < 50; i++)
ll_push_back(ll, i);
cmc_assert_equals(size_t, 50, ll_count(ll));
ll_clear(ll);
cmc_assert_equals(size_t, 0, ll_count(ll));
ll_free(ll);
});
CMC_CREATE_TEST(clear[edge_case:count = 0], {
linkedlist *ll = ll_new();
cmc_assert_not_equals(ptr, NULL, ll);
ll_clear(ll);
cmc_assert_equals(size_t, 0, ll_count(ll));
ll_free(ll);
});
CMC_CREATE_TEST(push_front[count], {
linkedlist *ll = ll_new();
cmc_assert_not_equals(ptr, NULL, ll);
ll_push_front(ll, 1);
cmc_assert_not_equals(ptr, NULL, ll->head);
cmc_assert_not_equals(ptr, NULL, ll->tail);
cmc_assert_equals(size_t, 1, ll_count(ll));
ll_free(ll);
});
CMC_CREATE_TEST(push_front[item_preservation], {
linkedlist *ll = ll_new();
cmc_assert_not_equals(ptr, NULL, ll);
for (size_t i = 0; i < 200; i++)
ll_push_front(ll, i);
for (size_t i = 0; i < ll_count(ll); i++)
cmc_assert_equals(size_t, ll_get(ll, i), ll_count(ll) - i - 1);
ll_free(ll);
});
});
+335
View File
@@ -0,0 +1,335 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/list.c"
CMC_CREATE_UNIT(list_test, false, {
CMC_CREATE_TEST(new, {
list *l = l_new(1000000);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert_not_equals(ptr, NULL, l->buffer);
cmc_assert_equals(size_t, 1000000, l_capacity(l));
cmc_assert_equals(size_t, 0, l_count(l));
l_free(l);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
list *l = l_new(0);
cmc_assert_equals(ptr, NULL, l);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
list *l = l_new(UINT64_MAX);
cmc_assert_equals(ptr, NULL, l);
});
CMC_CREATE_TEST(new_from[count item_preservation], {
size_t v[5];
for (size_t i = 0; i < 5; i++)
{
v[i] = i;
}
list *l = l_new_from(v, 5);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 5; i++)
cmc_assert_equals(size_t, i, l_get(l, i));
l_free(l);
});
CMC_CREATE_TEST(new_from[edge_case:size = 1], {
size_t a = 10;
size_t *values = &a;
list *l = l_new_from(values, 1);
cmc_assert_not_equals(ptr, NULL, l);
l_free(l);
});
CMC_CREATE_TEST(clear[count capacity], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 50; i++)
l_push_back(l, i);
cmc_assert_equals(size_t, 50, l_count(l));
l_clear(l);
cmc_assert_equals(size_t, 0, l_count(l));
cmc_assert_equals(size_t, 100, l_capacity(l));
l_free(l);
});
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
list *l = l_new(1);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 100; i++)
l_push_back(l, i);
cmc_assert_equals(size_t, 100, l_count(l));
for (size_t i = 0; i < 100; i++)
cmc_assert_equals(size_t, i, l_get(l, i));
l_free(l);
});
CMC_CREATE_TEST(push_front[count], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 250; i++)
cmc_assert(l_push_front(l, i));
cmc_assert_equals(size_t, 250, l_count(l));
l_free(l);
});
CMC_CREATE_TEST(push_front[capacity], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 250; i++)
cmc_assert(l_push_front(l, i));
cmc_assert_lesser_equals(size_t, l_capacity(l), l_count(l));
l_free(l);
});
CMC_CREATE_TEST(push_front[item_preservation], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 250; i++)
cmc_assert(l_push_front(l, i));
for (size_t i = 0; i < l_count(l); i++)
cmc_assert_equals(size_t, l_get(l, i), l_count(l) - i - 1);
l_free(l);
});
CMC_CREATE_TEST(push[count], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(l_push_back(l, 0));
cmc_assert(l_push_back(l, 249));
for (size_t i = 1; i < 249; i++)
cmc_assert(l_push(l, i, l_count(l) - 1));
cmc_assert_equals(size_t, 250, l_count(l));
l_free(l);
});
CMC_CREATE_TEST(push[capacity], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(l_push_back(l, 0));
cmc_assert(l_push_back(l, 249));
for (size_t i = 1; i < 249; i++)
cmc_assert(l_push(l, i, l_count(l) - 1));
cmc_assert_lesser_equals(size_t, l_capacity(l), l_count(l));
l_free(l);
});
CMC_CREATE_TEST(push[item_preservation], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(l_push_back(l, 0));
cmc_assert(l_push_back(l, 249));
for (size_t i = 1; i < 249; i++)
cmc_assert(l_push(l, i, l_count(l) - 1));
for (size_t i = 0; i < l_count(l); i++)
cmc_assert_equals(size_t, l_get(l, i), i);
l_free(l);
});
CMC_CREATE_TEST(push_back[count], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 250; i++)
cmc_assert(l_push_back(l, i));
cmc_assert_equals(size_t, 250, l_count(l));
l_free(l);
});
CMC_CREATE_TEST(push_back[capacity], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 250; i++)
cmc_assert(l_push_back(l, i));
cmc_assert_lesser_equals(size_t, l_capacity(l), l_count(l));
l_free(l);
});
CMC_CREATE_TEST(push_back[item_preservation], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 250; i++)
cmc_assert(l_push_back(l, i));
for (size_t i = 0; i < l_count(l); i++)
cmc_assert_equals(size_t, l_get(l, i), i);
l_free(l);
});
CMC_CREATE_TEST(pop_front[count], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 250; i++)
l_push_back(l, i);
cmc_assert(l_pop_front(l));
l_free(l);
});
CMC_CREATE_TEST(pop_front[item_preservation], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
for (size_t i = 0; i < 250; i++)
l_push_back(l, i);
cmc_assert(l_pop_front(l));
for (size_t i = 0; i < l_count(l); i++)
cmc_assert_equals(size_t, l_get(l, i), i + 1);
l_free(l);
});
CMC_CREATE_TEST(pop_front[edge_case:count = 0], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(!l_pop_front(l));
l_free(l);
});
CMC_CREATE_TEST(pop_front[edge_case:count = 1], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(l_push_back(l, 10));
cmc_assert(l_pop_front(l));
l_free(l);
});
CMC_CREATE_TEST(pop_front[buffer_clear], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(l_push_back(l, 1));
cmc_assert(l_push_front(l, 2));
cmc_assert(l_pop_front(l));
cmc_assert_equals(size_t, 0, l->buffer[1]);
l_free(l);
});
CMC_CREATE_TEST(pop[edge_case:count = 0], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(!l_pop(l, 1));
l_free(l);
});
CMC_CREATE_TEST(pop[edge_case:count = 1], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(l_push_back(l, 1));
cmc_assert(l_pop(l, 0));
cmc_assert_equals(size_t, 0, l->buffer[0]);
l_free(l);
});
CMC_CREATE_TEST(pop[buffer_clear], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(l_push_back(l, 1));
cmc_assert(l_push_back(l, 2));
cmc_assert(l_push_back(l, 3));
cmc_assert(l_pop(l, 1));
l_free(l);
});
CMC_CREATE_TEST(pop_back[edge_case:count = 0], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(!l_pop_back(l));
l_free(l);
});
CMC_CREATE_TEST(pop_back[edge_case:count = 1], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(l_push_back(l, 10));
cmc_assert(l_pop_back(l));
l_free(l);
});
})
+151
View File
@@ -0,0 +1,151 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/multimap.c"
#include "utl.c"
CMC_CREATE_UNIT(multimap_test, false, {
CMC_CREATE_TEST(new, {
multimap *map = mm_new(943722, 0.8, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_not_equals(ptr, NULL, map->buffer);
cmc_assert_equals(size_t, 0, mm_count(map));
cmc_assert_greater_equals(size_t, (943722 / 0.8), mm_capacity(map));
mm_free(map);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
multimap *map = mm_new(0, 0.8, cmp, hash);
cmc_assert_equals(ptr, NULL, map);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
multimap *map = mm_new(UINT64_MAX, 0.8, cmp, hash);
cmc_assert_equals(ptr, NULL, map);
});
CMC_CREATE_TEST(clear[count capacity], {
multimap *map = mm_new(100, 0.8, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 50; i++)
cmc_assert(mm_insert(map, i, i));
cmc_assert_equals(size_t, 50, mm_count(map));
mm_clear(map);
cmc_assert_equals(size_t, 0, mm_count(map));
mm_free(map);
});
CMC_CREATE_TEST(insert[count], {
multimap *map = mm_new(100, 0.8, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 200; i++)
cmc_assert(mm_insert(map, i % 20, i % 20));
cmc_assert_equals(size_t, 200, mm_count(map));
mm_free(map);
});
CMC_CREATE_TEST(remove[count], {
multimap *map = mm_new(100, 0.8, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 200; i++)
cmc_assert(mm_insert(map, i % 20, i % 20));
size_t r;
for (size_t i = 0; i < 60; i++)
cmc_assert(mm_remove(map, i % 20, &r));
cmc_assert_equals(size_t, 140, mm_count(map));
mm_free(map);
});
CMC_CREATE_TEST(remove[edge_case:count = 0], {
multimap *map = mm_new(100, 0.8, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
size_t r;
cmc_assert(!mm_remove(map, 10, &r));
mm_free(map);
});
CMC_CREATE_TEST(remove[edge_case:count = 1], {
multimap *map = mm_new(100, 0.8, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
size_t r;
cmc_assert(mm_insert(map, 10, 11));
cmc_assert(mm_remove(map, 10, &r));
mm_free(map);
});
CMC_CREATE_TEST(insert_if, {
multimap *map = mm_new(100, 0.8, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 1; i <= 100; i++)
cmc_assert(mm_insert_if(map, i % 20, i, i % 2 == 0) || i % 2 != 0);
cmc_assert_equals(size_t, 50, mm_count(map));
mm_free(map);
});
CMC_CREATE_TEST(remove_if, {
multimap *map = mm_new(100, 0.8, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 1; i <= 100; i++)
cmc_assert(mm_insert(map, i % 20, i));
size_t r;
for (size_t i = 1; i <= 100; i++)
cmc_assert(mm_remove_if(map, i % 20, &r, i % 2 == 0) || i % 2 != 0);
cmc_assert_equals(size_t, 50, mm_count(map));
mm_free(map);
});
CMC_CREATE_TEST(get[key_ordering], {
multimap *map = mm_new(100, 0.8, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
/* Assert that the value 100 is accessed before the value 101 for the
* same key */
cmc_assert(mm_insert(map, 10, 100));
cmc_assert(mm_insert(map, 20, 102));
cmc_assert(mm_insert(map, 10, 101));
cmc_assert_equals(size_t, 100, mm_get(map, 10));
mm_free(map);
});
});
+86
View File
@@ -0,0 +1,86 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/multiset.c"
#include "utl.c"
CMC_CREATE_UNIT(multiset_test, false, {
CMC_CREATE_TEST(new, {
multiset *set = ms_new(943722, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
cmc_assert_not_equals(ptr, NULL, set->buffer);
cmc_assert_equals(size_t, 0, ms_count(set));
cmc_assert_greater_equals(size_t, ((size_t)(943722 / 0.6)), ms_capacity(set));
ms_free(set);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
multiset *set = ms_new(0, 0.6, cmp, hash);
cmc_assert_equals(ptr, NULL, set);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINTMAX_MAX], {
multiset *set = ms_new(UINTMAX_MAX, 0.99, cmp, hash);
cmc_assert_equals(ptr, NULL, set);
});
CMC_CREATE_TEST(clear[count capacity], {
multiset *set = ms_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
for (size_t i = 0; i < 50; i++)
cmc_assert(ms_insert(set, i));
cmc_assert_equals(size_t, 50, ms_count(set));
ms_clear(set);
cmc_assert_equals(size_t, 0, ms_count(set));
ms_free(set);
});
CMC_CREATE_TEST(insert[count cardinality multiplicity], {
multiset *set = ms_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
cmc_assert(ms_insert(set, 1));
cmc_assert(ms_insert(set, 2));
cmc_assert(ms_insert(set, 2));
cmc_assert(ms_insert(set, 3));
cmc_assert(ms_insert(set, 3));
cmc_assert(ms_insert(set, 3));
cmc_assert_equals(size_t, 3, ms_count(set));
cmc_assert_equals(size_t, 6, ms_cardinality(set));
for (size_t i = 0; i <= 3; i++)
cmc_assert_equals(size_t, i, ms_multiplicity_of(set, i));
ms_free(set);
});
CMC_CREATE_TEST(multiplicity, {
multiset *set = ms_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
for (size_t i = 0; i < 100; i++)
cmc_assert(ms_insert(set, i % 20));
cmc_assert_equals(size_t, 20, ms_count(set));
cmc_assert_equals(size_t, 100, ms_cardinality(set));
for (size_t i = 0; i < 20; i++)
cmc_assert_equals(size_t, 5, ms_multiplicity_of(set, i));
ms_free(set);
});
});
+61
View File
@@ -0,0 +1,61 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/queue.c"
CMC_CREATE_UNIT(queue_test, false, {
CMC_CREATE_TEST(new, {
queue *q = q_new(1000000);
cmc_assert_not_equals(ptr, NULL, q);
cmc_assert_not_equals(ptr, NULL, q->buffer);
cmc_assert_equals(size_t, 1000000, q_capacity(q));
cmc_assert_equals(size_t, 0, q_count(q));
cmc_assert_not_equals(ptr, NULL, q->buffer);
q_free(q);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
queue *q = q_new(0);
cmc_assert_equals(ptr, NULL, q);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
queue *q = q_new(UINT64_MAX);
cmc_assert_equals(ptr, NULL, q);
});
CMC_CREATE_TEST(clear[count capacity], {
queue *q = q_new(100);
cmc_assert_not_equals(ptr, NULL, q);
for (size_t i = 0; i < 50; i++)
cmc_assert(q_enqueue(q, i));
cmc_assert_equals(size_t, 50, q_count(q));
q_clear(q);
cmc_assert_equals(size_t, 0, q_count(q));
cmc_assert_equals(size_t, 100, q_capacity(q));
q_free(q);
});
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
queue *q = q_new(1);
cmc_assert_not_equals(ptr, NULL, q);
for (size_t i = 0; i < 50; i++)
cmc_assert(q_enqueue(q, i));
cmc_assert_equals(size_t, 50, q_count(q));
q_free(q);
});
});
+628
View File
@@ -0,0 +1,628 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/stack.c"
#include "utl.c"
CMC_CREATE_UNIT(stack_test, false, {
CMC_CREATE_TEST(new, {
stack *s = s_new(1000000);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert_not_equals(ptr, NULL, s->buffer);
cmc_assert_equals(size_t, 1000000, s_capacity(s));
cmc_assert_equals(size_t, 0, s_count(s));
cmc_assert_not_equals(ptr, NULL, s->buffer);
s_free(s);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
stack *s = s_new(0);
cmc_assert_equals(ptr, NULL, s);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
stack *s = s_new(UINT64_MAX);
cmc_assert_equals(ptr, NULL, s);
});
CMC_CREATE_TEST(clear[count capacity], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 50; i++)
cmc_assert(s_push(s, i));
cmc_assert_equals(size_t, 50, s_count(s));
s_clear(s);
cmc_assert_equals(size_t, 0, s_count(s));
cmc_assert_equals(size_t, 100, s_capacity(s));
s_free(s);
});
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
stack *s = s_new(1);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 50; i++)
cmc_assert(s_push(s, i));
cmc_assert_equals(size_t, 50, s_count(s));
cmc_assert_lesser_equals(size_t, s_capacity(s), s_count(s));
s_free(s);
});
CMC_CREATE_TEST(push[count], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
cmc_assert_equals(size_t, 250, s_count(s));
s_free(s);
});
CMC_CREATE_TEST(push[capacity], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
cmc_assert_lesser_equals(size_t, s_capacity(s), s_count(s));
s_free(s);
});
CMC_CREATE_TEST(push[item_preservation], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
for (size_t i = 0; i < s_count(s); i++)
cmc_assert_equals(size_t, i, s->buffer[i]);
s_free(s);
});
CMC_CREATE_TEST(pop[count], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
cmc_assert(s_pop(s));
cmc_assert_equals(size_t, 249, s_count(s));
s_free(s);
});
CMC_CREATE_TEST(pop[capacity], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
cmc_assert(s_pop(s));
cmc_assert_lesser_equals(size_t, s_capacity(s), s_count(s));
s_free(s);
});
CMC_CREATE_TEST(pop[item_preservation], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
cmc_assert(s_pop(s));
cmc_assert(s_pop(s));
for (size_t i = 0; i < s_count(s); i++)
cmc_assert_equals(size_t, i, s->buffer[i]);
s_free(s);
});
CMC_CREATE_TEST(pop[edge_case:count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert_equals(bool, false, s_pop(s));
s_free(s);
});
CMC_CREATE_TEST(push_if, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
s_push_if(s, i, i % 2 == 0);
for (size_t i = 0; i < s_count(s); i++)
cmc_assert(s->buffer[i] % 2 == 0);
s_free(s);
});
CMC_CREATE_TEST(pop_if, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
{
s_push(s, i);
s_pop_if(s, s_top(s) % 2 == 0);
}
for (size_t i = 0; i < s_count(s); i++)
cmc_assert_not_equals(uint32_t, 0, s->buffer[i] % 2);
s_free(s);
});
CMC_CREATE_TEST(top, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
cmc_assert(s_pop(s));
cmc_assert(s_pop(s));
cmc_assert_equals(size_t, 247, s_top(s));
s_free(s);
});
CMC_CREATE_TEST(top[edge_case:count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert(s_push(s, 1));
cmc_assert(s_pop(s));
cmc_assert_equals(size_t, s_impl_default_value(), s_top(s));
s_free(s);
});
CMC_CREATE_TEST(top[edge_case:count = 1], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert(s_push(s, 10));
cmc_assert_equals(size_t, 1, s_count(s));
cmc_assert_equals(size_t, 10, s_top(s));
s_free(s);
});
CMC_CREATE_TEST(contains, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 150; i++)
cmc_assert(s_push(s, i));
for (size_t i = 0; i < 150; i++)
cmc_assert(s_contains(s, i, cmp));
s_free(s);
});
CMC_CREATE_TEST(contains[edge_case:count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert_equals(bool, false, s_contains(s, 10, cmp));
s_free(s);
});
CMC_CREATE_TEST(empty, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert(s_empty(s));
s_free(s);
});
CMC_CREATE_TEST(empty[after_io], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert(s_push(s, 10));
cmc_assert(s_pop(s));
cmc_assert(s_empty(s));
s_free(s);
});
CMC_CREATE_TEST(full, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < s_capacity(s); i++)
cmc_assert(s_push(s, i));
cmc_assert(s_full(s));
s_free(s);
});
CMC_CREATE_TEST(full[edge_case:capacity = 1], {
stack *s = s_new(1);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert(s_push(s, 10));
cmc_assert(s_full(s));
s_free(s);
});
CMC_CREATE_TEST(iter_alloc, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
stack_iter *iter = s_iter_new(s);
cmc_assert_not_equals(ptr, NULL, iter);
s_iter_free(iter);
s_free(s);
});
CMC_CREATE_TEST(iter_init[edge_case:count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
stack_iter iter;
s_iter_init(&iter, s);
cmc_assert_equals(ptr, iter.target, s);
cmc_assert_equals(size_t, iter.cursor, 0);
cmc_assert(iter.start);
cmc_assert(iter.end);
s_free(s);
});
CMC_CREATE_TEST(iter_start[edge_case:count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
stack_iter iter;
s_iter_init(&iter, s);
cmc_assert(s_iter_start(&iter));
s_free(s);
});
CMC_CREATE_TEST(iter_end[edge_case:count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
stack_iter iter;
s_iter_init(&iter, s);
cmc_assert(s_iter_end(&iter));
s_free(s);
});
CMC_CREATE_TEST(iteration, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 1; i <= 200; i++)
cmc_assert(s_push(s, i));
size_t total = 0;
for (stack_iter it = s->it_start(s); !s_iter_end(&it); s_iter_next(&it))
{
total += s_iter_value(&it);
}
cmc_assert_equals(size_t, 20100, total);
for (stack_iter it = s->it_end(s); !s_iter_start(&it); s_iter_prev(&it))
{
total += s_iter_value(&it);
}
cmc_assert_equals(size_t, 40200, total);
s_free(s);
});
CMC_CREATE_TEST(iteration[while loop], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 1; i <= 200; i++)
cmc_assert(s_push(s, i));
size_t total = 0;
stack_iter it = s->it_start(s);
do
{
total += s_iter_value(&it);
} while (s_iter_next(&it));
cmc_assert_equals(size_t, 20100, total);
it = s->it_end(s);
do
{
total += s_iter_value(&it);
} while (s_iter_prev(&it));
cmc_assert_equals(size_t, 40200, total);
s_free(s);
});
CMC_CREATE_TEST(iteration[edge_case:count = 1], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert(s_push(s, 10));
size_t total = 0;
for (stack_iter it = s->it_start(s); !s_iter_end(&it); s_iter_next(&it))
{
total += s_iter_value(&it);
}
for (stack_iter it = s->it_end(s); !s_iter_start(&it); s_iter_prev(&it))
{
total += s_iter_value(&it);
}
cmc_assert_equals(size_t, 20, total);
s_free(s);
});
CMC_CREATE_TEST(iteration[edge_case:count = capacity], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
while (!s_full(s))
cmc_assert(s_push(s, 10));
cmc_assert_equals(size_t, s_capacity(s), s_count(s));
size_t total = 0;
for (stack_iter it = s->it_start(s); !s_iter_end(&it); s_iter_next(&it))
{
total += s_iter_value(&it);
}
cmc_assert_equals(size_t, 1000, total);
for (stack_iter it = s->it_end(s); !s_iter_start(&it); s_iter_prev(&it))
{
total += *s_iter_rvalue(&it);
}
cmc_assert_equals(size_t, 2000, total);
s_free(s);
});
CMC_CREATE_TEST(iteration[to_start = it_start and to_end = it_end], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 50; i++)
cmc_assert(s_push(s, i));
stack_iter it1;
stack_iter it2;
memset(&it1, 0, sizeof(stack_iter));
memset(&it2, 0, sizeof(stack_iter));
s_iter_init(&it2, s);
it1 = s->it_start(s);
s_iter_to_start(&it2);
cmc_assert_equals(ptr, it1.target, it2.target);
cmc_assert_equals(size_t, it1.cursor, it2.cursor);
cmc_assert_equals(bool, it1.start, it2.start);
cmc_assert_equals(bool, it1.end, it2.end);
it1 = s->it_end(s);
s_iter_to_end(&it2);
cmc_assert_equals(ptr, it1.target, it2.target);
cmc_assert_equals(size_t, it1.cursor, it2.cursor);
cmc_assert_equals(bool, it1.start, it2.start);
cmc_assert_equals(bool, it1.end, it2.end);
s_free(s);
});
CMC_CREATE_TEST(iteration[boundaries:count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
stack_iter iter;
s_iter_init(&iter, s);
s_iter_to_end(&iter);
cmc_assert_equals(bool, false, s_iter_next(&iter));
s_iter_to_start(&iter);
cmc_assert_equals(bool, false, s_iter_prev(&iter));
s_free(s);
});
CMC_CREATE_TEST(iteration[boundaries:count > 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 200; i++)
cmc_assert(s_push(s, i));
stack_iter iter;
s_iter_init(&iter, s);
s_iter_to_end(&iter);
cmc_assert_equals(bool, false, s_iter_next(&iter));
s_iter_to_start(&iter);
cmc_assert_equals(bool, false, s_iter_prev(&iter));
s_free(s);
});
CMC_CREATE_TEST(iter_value[edge_case:count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
stack_iter iter;
s_iter_init(&iter, s);
cmc_assert_equals(size_t, s_impl_default_value(), s_iter_value(&iter));
s_free(s);
});
CMC_CREATE_TEST(iter_rvalue[edge_case:count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
stack_iter iter;
s_iter_init(&iter, s);
cmc_assert_equals(ptr, NULL, s_iter_rvalue(&iter));
s_free(s);
});
CMC_CREATE_TEST(index, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 10; i++)
cmc_assert(s_push(s, i));
cmc_assert_equals(size_t, 10, s_count(s));
size_t total = 0;
for (stack_iter it = s->it_start(s); false; )
{
cmc_assert_equals(size_t, 0, s_iter_index(&it));
}
for (stack_iter it = s->it_start(s); false; )
{
cmc_assert_equals(size_t, s_count(s) - 1, s_iter_index(&it));
}
for (stack_iter it = s->it_start(s); !s_iter_end(&it); s_iter_next(&it))
{
total += s_iter_index(&it);
}
cmc_assert_equals(size_t, 45, total);
for (stack_iter it = s->it_end(s); !s_iter_start(&it); s_iter_prev(&it))
{
total += s_iter_index(&it);
}
cmc_assert_equals(size_t, 90, total);
s_free(s);
});
CMC_CREATE_TEST(index[edge_case:count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
stack_iter iter;
s_iter_init(&iter, s);
cmc_assert_equals(size_t, 0, s_iter_index(&iter));
s_free(s);
});
});
+34
View File
@@ -0,0 +1,34 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/treemap.c"
#include "utl.c"
CMC_CREATE_UNIT(treemap_test, false, {
CMC_CREATE_TEST(new, {
treemap *map = tm_new(cmp);
cmc_assert_not_equals(ptr, NULL, map);
tm_free(map);
});
CMC_CREATE_TEST(clear[count], {
treemap *map = tm_new(cmp);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 50; i++)
tm_insert(map, i, i);
cmc_assert_equals(size_t, 50, tm_count(map));
tm_clear(map);
cmc_assert_equals(size_t, 0, tm_count(map));
cmc_assert_equals(ptr, NULL, map->root);
tm_free(map);
});
});
+34
View File
@@ -0,0 +1,34 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/treeset.c"
#include "utl.c"
CMC_CREATE_UNIT(treeset_test, false, {
CMC_CREATE_TEST(new, {
treeset *set = ts_new(cmp);
cmc_assert_not_equals(ptr, NULL, set);
ts_free(set);
});
CMC_CREATE_TEST(clear[count], {
treeset *set = ts_new(cmp);
cmc_assert_not_equals(ptr, NULL, set);
for (size_t i = 0; i < 50; i++)
ts_insert(set, i);
cmc_assert_equals(size_t, 50, ts_count(set));
ts_clear(set);
cmc_assert_equals(size_t, 0, ts_count(set));
cmc_assert_equals(ptr, NULL, set->root);
ts_free(set);
});
});
+23
View File
@@ -0,0 +1,23 @@
/* Utility file to be included in the unit tests */
#ifndef CMC_UNIT_TEST_UTL__
#define CMC_UNIT_TEST_UTL__
#include <stdlib.h>
int cmp(size_t a, size_t b)
{
return (a > b) - (a < b);
}
size_t hash(size_t a)
{
a += ~(a << 15);
a ^= (a >> 10);
a += (a << 3);
a ^= (a >> 6);
a += ~(a << 11);
a ^= (a >> 16);
return a;
}
#endif /* CMC_UNIT_TEST_UTL__ */
+109 -55
View File
@@ -20,16 +20,20 @@ size_t inthash(int t)
return a;
}
COLLECTION_GENERATE(LIST, l, list, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(STACK, s, stack, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(QUEUE, q, queue, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(DEQUE, d, deque, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(LINKEDLIST, ll, linked, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(HEAP, h, heap, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(TREESET, ts, tset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(TREEMAP, tm, tmap, /* FMOD */, int, int)
COLLECTION_GENERATE(HASHSET, hs, hset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(HASHMAP, hm, hmap, /* FMOD */, int, int)
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)
{
@@ -41,12 +45,16 @@ int main(void)
heap *h = h_new(1000, cmc_max_heap, intcmp);
tset *ts = ts_new(intcmp);
tmap *tm = tm_new(intcmp);
hset *hs = hs_new(1000, 0.9, intcmp, inthash);
hmap *hm = hm_new(1000, 0.9, intcmp, inthash);
hset *hs = hs_new(1000, 0.6, intcmp, inthash);
hmap *hm = hm_new(1000, 0.6, intcmp, inthash);
bool a[10] = {false, false, false, false, false, false, false, false, false, false},
b[10] = {false, false, false, false, false, false, false, false, false, false},
c[10] = {true, true, true, true, true, true, true, true, true, true};
iheap *ih = ih_new(1000, intcmp);
mmap *mm = mm_new(1000, 0.8, intcmp, inthash);
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);
@@ -59,6 +67,10 @@ int main(void)
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)
@@ -81,6 +93,10 @@ int main(void)
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++)
@@ -95,6 +111,10 @@ int main(void)
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++)
@@ -109,6 +129,10 @@ int main(void)
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++)
@@ -123,18 +147,26 @@ int main(void)
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);
hm_clear(hm);
hs_clear(hs);
h_clear(h);
ll_clear(ll);
l_clear(l);
q_clear(q);
s_clear(s);
tm_clear(tm);
ts_clear(ts);
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);
@@ -147,58 +179,80 @@ int main(void)
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("%10s PASSED\n", "DEQUE");
printf("%12s PASSED\n", "DEQUE");
else
printf("%10s FAILED\n", "DEQUE");
printf("%12s FAILED\n", "DEQUE");
if (c[1] && !a[1] && !b[1])
printf("%10s PASSED\n", "HASHMAP");
printf("%12s PASSED\n", "HASHMAP");
else
printf("%10s FAILED\n", "HASHMAP");
printf("%12s FAILED\n", "HASHMAP");
if (c[2] && !a[2] && !b[2])
printf("%10s PASSED\n", "HASHSET");
printf("%12s PASSED\n", "HASHSET");
else
printf("%10s FAILED\n", "HASHSET");
printf("%12s FAILED\n", "HASHSET");
if (c[3] && !a[3] && !b[3])
printf("%10s PASSED\n", "HEAP");
printf("%12s PASSED\n", "HEAP");
else
printf("%10s FAILED\n", "HEAP");
printf("%12s FAILED\n", "HEAP");
if (c[4] && !a[4] && !b[4])
printf("%10s PASSED\n", "LINKEDLIST");
printf("%12s PASSED\n", "LINKEDLIST");
else
printf("%10s FAILED\n", "LINKEDLIST");
printf("%12s FAILED\n", "LINKEDLIST");
if (c[5] && !a[5] && !b[5])
printf("%10s PASSED\n", "LIST");
printf("%12s PASSED\n", "LIST");
else
printf("%10s FAILED\n", "LIST");
printf("%12s FAILED\n", "LIST");
if (c[6] && !a[6] && !b[6])
printf("%10s PASSED\n", "QUEUE");
printf("%12s PASSED\n", "QUEUE");
else
printf("%10s FAILED\n", "QUEUE");
printf("%12s FAILED\n", "QUEUE");
if (c[7] && !a[7] && !b[7])
printf("%10s PASSED\n", "STACK");
printf("%12s PASSED\n", "STACK");
else
printf("%10s FAILED\n", "STACK");
printf("%12s FAILED\n", "STACK");
if (c[8] && !a[8] && !b[8])
printf("%10s PASSED\n", "TREEMAP");
printf("%12s PASSED\n", "TREEMAP");
else
printf("%10s FAILED\n", "TREEMAP");
printf("%12s FAILED\n", "TREEMAP");
if (c[9] && !a[9] && !b[9])
printf("%10s PASSED\n", "TREESET");
printf("%12s PASSED\n", "TREESET");
else
printf("%10s FAILED\n", "TREESET");
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");
l_free(l);
ll_free(ll);
s_free(s);
q_free(q);
d_free(d);
h_free(h);
ts_free(ts);
tm_free(tm);
hs_free(hs);
hm_free(hm);
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;
}
+224 -155
View File
@@ -1,5 +1,6 @@
#include "../src/macro_collections.h"
#include <stdio.h>
#include <string.h>
#include <assert.h>
int intcmp(int a, int b)
@@ -19,16 +20,20 @@ size_t inthash(int t)
return a;
}
COLLECTION_GENERATE(LIST, l, list, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(STACK, s, stack, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(QUEUE, q, queue, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(DEQUE, d, deque, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(LINKEDLIST, ll, linked, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(HEAP, h, heap, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(TREESET, ts, tset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(TREEMAP, tm, tmap, /* FMOD */, int, int)
COLLECTION_GENERATE(HASHSET, hs, hset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(HASHMAP, hm, hmap, /* FMOD */, int, int)
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)
{
@@ -40,219 +45,283 @@ int main(void)
heap *h = h_new(1000, cmc_max_heap, intcmp);
tset *ts = ts_new(intcmp);
tmap *tm = tm_new(intcmp);
hset *hs = hs_new(1000, 0.9, intcmp, inthash);
hmap *hm = hm_new(1000, 0.9, intcmp, inthash);
hset *hs = hs_new(1000, 0.6, intcmp, inthash);
hmap *hm = hm_new(1000, 0.6, intcmp, inthash);
iheap *ih = ih_new(1000, intcmp);
mmap *mm = mm_new(1000, 0.8, intcmp, inthash);
mset *ms = ms_new(1000, 0.6, intcmp, inthash);
bool p = true;
for (int i = 1; i < 10001; i++)
{
if (i % 2 == 0)
{
d_push_front(d, i);
l_push_front(l, i);
ll_push_front(ll, i);
assert(d_push_front(d, i));
assert(l_push_front(l, i));
assert(ll_push_front(ll, i));
}
else
{
d_push_back(d, i);
l_push_back(l, i);
ll_push_back(ll, i);
assert(d_push_back(d, i));
assert(l_push_back(l, i));
assert(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);
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 sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0, sum5 = 0, sum6 = 0,
sum7 = 0, sum8 = 0, sum9 = 0, sum10 = 0, sum11 = 0;
int sums[16] = {0};
FOR_EACH(d, deque, d, {
sum3 += d_iter_value(&iter);
CMC_FOR_EACH(d, deque, d, {
sums[0] += d_iter_value(&iter);
});
FOR_EACH(hm, hmap, hm, {
sum10 += hm_iter_key(&iter);
sum11 += hm_iter_value(&iter);
CMC_FOR_EACH(hm, hmap, hm, {
sums[1] += hm_iter_key(&iter);
sums[2] += hm_iter_value(&iter);
});
FOR_EACH(hs, hset, hs, {
sum9 += hs_iter_value(&iter);
CMC_FOR_EACH(hs, hset, hs, {
sums[3] += hs_iter_value(&iter);
});
FOR_EACH(h, heap, h, {
sum5 += h_iter_value(&iter);
CMC_FOR_EACH(h, heap, h, {
sums[4] += h_iter_value(&iter);
});
FOR_EACH(ll, linked, ll, {
sum4 += ll_iter_value(&iter);
CMC_FOR_EACH(ll, linked, ll, {
sums[5] += ll_iter_value(&iter);
});
FOR_EACH(l, list, l, {
sum0 += l_iter_value(&iter);
CMC_FOR_EACH(l, list, l, {
sums[6] += l_iter_value(&iter);
});
FOR_EACH(q, queue, q, {
sum2 += q_iter_value(&iter);
CMC_FOR_EACH(q, queue, q, {
sums[7] += q_iter_value(&iter);
});
FOR_EACH(s, stack, s, {
sum1 += s_iter_value(&iter);
CMC_FOR_EACH(s, stack, s, {
sums[8] += s_iter_value(&iter);
});
FOR_EACH(tm, tmap, tm, {
sum7 += tm_iter_key(&iter);
sum8 += tm_iter_value(&iter);
CMC_FOR_EACH(tm, tmap, tm, {
sums[9] += tm_iter_key(&iter);
sums[10] += tm_iter_value(&iter);
});
FOR_EACH(ts, tset, ts, {
sum6 += ts_iter_value(&iter);
CMC_FOR_EACH(ts, tset, ts, {
sums[11] += ts_iter_value(&iter);
});
printf("\n-------------------- FOR_EACH --------------------\n");
if (sum3 == 50005000)
printf("%10s PASSED\n", "DEQUE");
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("%10s FAILED\n", "DEQUE");
if (sum9 == 50005000)
printf("%10s PASSED\n", "HASHSET");
printf("%12s FAILED\n", "DEQUE");
if (sums[1] == 50005000 && sums[2] == 50005000)
printf("%12s PASSED\n", "HASHMAP");
else
printf("%10s FAILED\n", "HASHSET");
if (sum10 == 50005000 && sum11 == 50005000)
printf("%10s PASSED\n", "HASHMAP");
printf("%12s FAILED\n", "HASHMAP");
if (sums[3] == 50005000)
printf("%12s PASSED\n", "HASHSET");
else
printf("%10s FAILED\n", "HASHMAP");
if (sum5 == 50005000)
printf("%10s PASSED\n", "HEAP");
printf("%12s FAILED\n", "HASHSET");
if (sums[4] == 50005000)
printf("%12s PASSED\n", "HEAP");
else
printf("%10s FAILED\n", "HEAP");
if (sum4 == 50005000)
printf("%10s PASSED\n", "LINKEDLIST");
printf("%12s FAILED\n", "HEAP");
if (sums[5] == 50005000)
printf("%12s PASSED\n", "LINKEDLIST");
else
printf("%10s FAILED\n", "LINKEDLIST");
if (sum0 == 50005000)
printf("%10s PASSED\n", "LIST");
printf("%12s FAILED\n", "LINKEDLIST");
if (sums[6] == 50005000)
printf("%12s PASSED\n", "LIST");
else
printf("%10s FAILED\n", "LIST");
if (sum2 == 50005000)
printf("%10s PASSED\n", "QUEUE");
printf("%12s FAILED\n", "LIST");
if (sums[7] == 50005000)
printf("%12s PASSED\n", "QUEUE");
else
printf("%10s FAILED\n", "QUEUE");
if (sum1 == 50005000)
printf("%10s PASSED\n", "STACK");
printf("%12s FAILED\n", "QUEUE");
if (sums[8] == 50005000)
printf("%12s PASSED\n", "STACK");
else
printf("%10s FAILED\n", "STACK");
if (sum7 == 50005000 && sum8 == 50005000)
printf("%10s PASSED\n", "TREEMAP");
printf("%12s FAILED\n", "STACK");
if (sums[9] == 50005000 && sums[10] == 50005000)
printf("%12s PASSED\n", "TREEMAP");
else
printf("%10s FAILED\n", "TREEMAP");
if (sum6 == 50005000)
printf("%10s PASSED\n", "TREESET");
printf("%12s FAILED\n", "TREEMAP");
if (sums[11] == 50005000)
printf("%12s PASSED\n", "TREESET");
else
printf("%10s FAILED\n", "TREESET");
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");
sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0, sum5 = 0, sum6 = 0,
sum7 = 0, sum8 = 0, sum9 = 0, sum10 = 0, sum11 = 0;
memset(sums, 0, sizeof sums);
FOR_EACH_REV(d, deque, d, {
sum3 += d_iter_value(&iter);
CMC_FOR_EACH_REV(d, deque, d, {
sums[0] += d_iter_value(&iter);
});
FOR_EACH_REV(hm, hmap, hm, {
sum10 += hm_iter_key(&iter);
sum11 += hm_iter_value(&iter);
CMC_FOR_EACH_REV(hm, hmap, hm, {
sums[1] += hm_iter_key(&iter);
sums[2] += hm_iter_value(&iter);
});
FOR_EACH_REV(hs, hset, hs, {
sum9 += hs_iter_value(&iter);
CMC_FOR_EACH_REV(hs, hset, hs, {
sums[3] += hs_iter_value(&iter);
});
FOR_EACH_REV(h, heap, h, {
sum5 += h_iter_value(&iter);
CMC_FOR_EACH_REV(h, heap, h, {
sums[4] += h_iter_value(&iter);
});
FOR_EACH_REV(ll, linked, ll, {
sum4 += ll_iter_value(&iter);
CMC_FOR_EACH_REV(ll, linked, ll, {
sums[5] += ll_iter_value(&iter);
});
FOR_EACH_REV(l, list, l, {
sum0 += l_iter_value(&iter);
CMC_FOR_EACH_REV(l, list, l, {
sums[6] += l_iter_value(&iter);
});
FOR_EACH_REV(q, queue, q, {
sum2 += q_iter_value(&iter);
CMC_FOR_EACH_REV(q, queue, q, {
sums[7] += q_iter_value(&iter);
});
FOR_EACH_REV(s, stack, s, {
sum1 += s_iter_value(&iter);
CMC_FOR_EACH_REV(s, stack, s, {
sums[8] += s_iter_value(&iter);
});
FOR_EACH_REV(tm, tmap, tm, {
sum7 += tm_iter_key(&iter);
sum8 += tm_iter_value(&iter);
CMC_FOR_EACH_REV(tm, tmap, tm, {
sums[9] += tm_iter_key(&iter);
sums[10] += tm_iter_value(&iter);
});
FOR_EACH_REV(ts, tset, ts, {
sum6 += ts_iter_value(&iter);
CMC_FOR_EACH_REV(ts, tset, ts, {
sums[11] += ts_iter_value(&iter);
});
printf("-------------------- FOR_EACH_REV --------------------\n");
if (sum3 == 50005000)
printf("%10s PASSED\n", "DEQUE");
else
printf("%10s FAILED\n", "DEQUE");
if (sum10 == 50005000 && sum11 == 50005000)
printf("%10s PASSED\n", "HASHMAP");
else
printf("%10s FAILED\n", "HASHMAP");
if (sum9 == 50005000)
printf("%10s PASSED\n", "HASHSET");
else
printf("%10s FAILED\n", "HASHSET");
if (sum5 == 50005000)
printf("%10s PASSED\n", "HEAP");
else
printf("%10s FAILED\n", "HEAP");
if (sum4 == 50005000)
printf("%10s PASSED\n", "LINKEDLIST");
else
printf("%10s FAILED\n", "LINKEDLIST");
if (sum0 == 50005000)
printf("%10s PASSED\n", "LIST");
else
printf("%10s FAILED\n", "LIST");
if (sum2 == 50005000)
printf("%10s PASSED\n", "QUEUE");
else
printf("%10s FAILED\n", "QUEUE");
if (sum1 == 50005000)
printf("%10s PASSED\n", "STACK");
else
printf("%10s FAILED\n", "STACK");
if (sum7 == 50005000 && sum8 == 50005000)
printf("%10s PASSED\n", "TREEMAP");
else
printf("%10s FAILED\n", "TREEMAP");
if (sum6 == 50005000)
printf("%10s PASSED\n", "TREESET");
else
printf("%10s FAILED\n", "TREESET");
CMC_FOR_EACH_REV(ih, iheap, ih, {
sums[12] += ih_iter_value(&iter);
});
l_free(l);
ll_free(ll);
s_free(s);
q_free(q);
d_free(d);
h_free(h);
ts_free(ts);
tm_free(tm);
hs_free(hs);
hm_free(hm);
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;
}
+29 -17
View File
@@ -1,6 +1,5 @@
#include "../src/macro_collections.h"
#include <stdio.h>
#include <assert.h>
int intcmp(int a, int b)
{
@@ -19,16 +18,20 @@ size_t inthash(int t)
return a;
}
COLLECTION_GENERATE(LIST, l, list, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(STACK, s, stack, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(QUEUE, q, queue, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(DEQUE, d, deque, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(LINKEDLIST, ll, linked, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(HEAP, h, heap, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(TREESET, ts, tset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(TREEMAP, tm, tmap, /* FMOD */, int, double)
COLLECTION_GENERATE(HASHSET, hs, hset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE(HASHMAP, hm, hmap, /* FMOD */, int, double)
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) \
@@ -69,24 +72,27 @@ COLLECTION_GENERATE(HASHMAP, hm, hmap, /* FMOD */, int, double)
sumbody; \
} \
\
PFX##_free(coll); \
PFX##_free(coll, NULL); \
\
if (validation1 && validation2) \
printf("%10s PASSED\n", #NAME); \
if ((validation1) && (validation2)) \
printf("%12s PASSED\n", #NAME); \
else \
printf("%10s FAILED\n", #NAME); \
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, sum2 == 45.0)
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, sum2 == 45.0)
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)
{
@@ -102,5 +108,11 @@ int main(void)
TREEMAP_iterator_test();
TREESET_iterator_test();
INTERVALHEAP_iterator_test();
MULTIMAP_iterator_test();
MULTISET_iterator_test();
printf("\n\n");
return 0;
}
+13 -8
View File
@@ -1,16 +1,21 @@
CC = gcc
CFLAGS = -std=c11 -Wall -Wextra
CFLAGS += -Wno-unused-function -Wno-unused-parameter -Wno-unused-variable -Wno-unused-label
CVFLAGS = --coverage -O0
CFLAGS += -DCMC_TEST_COLOR
INCLUDE = ../../src/
main:
$(CC) main.c -o main $(CFLAGS) $(CVFLAGS) -I $(INCLUDE)
main: FORCE
$(CC) main.c -o main $(CFLAGS) -I $(INCLUDE)
./main
gcov ./main.c
dev:
$(CC) main.c -o main $(CFLAGS) $(CVFLAGS) -I $(INCLUDE)
dev: FORCE
$(CC) main.c -o main.exe $(CFLAGS) -I $(INCLUDE)
./main.exe
rm *.exe
windev: FORCE
$(CC) main.c -o main $(CFLAGS) -I $(INCLUDE)
./main
gcov ./main.c -n
rm *.gcda *.gcno *.exe
del *.exe
FORCE:
+2 -4
View File
@@ -1,7 +1,5 @@
# main
Tests for the main C Macro Collections library. In order to provide a good code coverage, all macros have been expanded and added to `src/*.c`.
This folder hosts the main tests for the C Macro Collections Library. While this library is under development with breaking changes the old unit tests were moved to codecov to keep track of code coverage without breaking the test.
* `src` - Since gcov fails to detect code that was expanded by macro, all collections where manually expanded and dumped into their respective source files;
* `unt` - Unit Tests;
* `main.c` - Where all tests are compiled together and called by main().
This new folder however will contain up-to-date changes and tests in order to have any modifications done to the library tracked and where they were broken.
+33 -15
View File
@@ -1,3 +1,5 @@
#include <utl/timer.h>
#include "unt/deque.c"
#include "unt/hashmap.c"
#include "unt/hashset.c"
@@ -9,27 +11,43 @@
#include "unt/treemap.c"
#include "unt/treeset.c"
#include "unt/linkedqueue.c"
#include "unt/bidimap.c"
#include "unt/intervalheap.c"
#include "unt/multimap.c"
#include "unt/multiset.c"
#include "unt/sortedlist.c"
int main(void)
{
deque_test();
hashmap_test();
hashset_test();
heap_test();
linkedlist_test();
list_test();
queue_test();
stack_test();
treemap_test();
treeset_test();
cmc_timer timer;
cmc_timer_start(timer);
uintmax_t failed = 0;
failed += deque_test();
failed += hashmap_test();
failed += hashset_test();
failed += heap_test();
failed += linkedlist_test();
failed += list_test();
failed += queue_test();
failed += stack_test();
failed += treemap_test();
failed += treeset_test();
/* ext */
linkedqueue_test();
multimap_test();
multiset_test();
failed += bidimap_test();
failed += intervalheap_test();
failed += multimap_test();
failed += multiset_test();
failed += sortedlist_test();
return 0;
cmc_timer_stop(timer);
cmc_timer_calc(timer);
printf("+--------------------------------------------------+\n");
printf("| Total running time : %14.0lf milliseconds |\n", timer.result);
printf("+--------------------------------------------------+\n");
return failed;
}
-220
View File
@@ -1,220 +0,0 @@
#include "ext/linkedqueue.h"
//LINKEDQUEUE_GENERATE(lq, linkedqueue, , size_t)
typedef struct linkedqueue_s
{
struct linkedqueue_node_s *head;
struct linkedqueue_node_s *tail;
size_t count;
struct linkedqueue_iter_s (*it_start)(struct linkedqueue_s *);
} linkedqueue, *linkedqueue_ptr;
typedef struct linkedqueue_node_s
{
size_t data;
struct linkedqueue_node_s *next;
} linkedqueue_node, *linkedqueue_node_ptr;
typedef struct linkedqueue_iter_s
{
struct linkedqueue_s *target;
struct linkedqueue_node_s *cursor;
size_t index;
bool start;
bool end;
} linkedqueue_iter, *linkedqueue_iter_ptr;
linkedqueue *lq_new(void);
void lq_clear(linkedqueue *_lqueue_);
void lq_free(linkedqueue *_lqueue_);
bool lq_enqueue(linkedqueue *_lqueue_, size_t element);
bool lq_dequeue(linkedqueue *_lqueue_);
bool lq_enqueue_if(linkedqueue *_lqueue_, size_t element, bool condition);
bool lq_dequeue_if(linkedqueue *_lqueue_, bool condition);
size_t lq_peek(linkedqueue *_lqueue_);
bool lq_contains(linkedqueue *_lqueue_, size_t element, int (*comparator)(size_t, size_t));
bool lq_empty(linkedqueue *_lqueue_);
size_t lq_count(linkedqueue *_lqueue_);
linkedqueue_iter *lq_iter_new(linkedqueue *target);
void lq_iter_free(linkedqueue_iter *iter);
void lq_iter_init(linkedqueue_iter *iter, linkedqueue *target);
bool lq_iter_start(linkedqueue_iter *iter);
bool lq_iter_end(linkedqueue_iter *iter);
void lq_iter_to_start(linkedqueue_iter *iter);
void lq_iter_to_end(linkedqueue_iter *iter);
bool lq_iter_next(linkedqueue_iter *iter);
size_t lq_iter_value(linkedqueue_iter *iter);
size_t *lq_iter_rvalue(linkedqueue_iter *iter);
size_t lq_iter_index(linkedqueue_iter *iter);
static inline size_t lq_impl_default_value(void)
{
size_t _empty_value_;
memset(&_empty_value_, 0, sizeof(size_t));
return _empty_value_;
}
linkedqueue_node *lq_impl_new_node(size_t element);
static linkedqueue_iter lq_impl_it_start(linkedqueue *_lqueue_);
linkedqueue *lq_new(void)
{
linkedqueue *_lqueue_ = malloc(sizeof(linkedqueue));
if (!_lqueue_)
return NULL;
_lqueue_->count = 0;
_lqueue_->head = NULL;
_lqueue_->tail = NULL;
_lqueue_->it_start = lq_impl_it_start;
return _lqueue_;
}
void lq_clear(linkedqueue *_lqueue_)
{
linkedqueue_node *scan = _lqueue_->head;
while (_lqueue_->head != NULL)
{
_lqueue_->head = _lqueue_->head->next;
free(scan);
scan = _lqueue_->head;
}
_lqueue_->count = 0;
_lqueue_->head = NULL;
_lqueue_->tail = NULL;
}
void lq_free(linkedqueue *_lqueue_)
{
lq_clear(_lqueue_);
free(_lqueue_);
}
bool lq_enqueue(linkedqueue *_lqueue_, size_t element)
{
linkedqueue_node *_node_ = lq_impl_new_node(element);
if (!_node_)
return false;
if (lq_empty(_lqueue_))
{
_lqueue_->head = _node_;
_lqueue_->tail = _node_;
}
else
{
_lqueue_->tail->next = _node_;
_lqueue_->tail = _node_;
}
_lqueue_->count++;
return true;
}
bool lq_dequeue(linkedqueue *_lqueue_)
{
if (lq_empty(_lqueue_))
return false;
linkedqueue_node *_node_ = _lqueue_->head;
_lqueue_->head = _lqueue_->head->next;
free(_node_);
if (_lqueue_->head == NULL)
_lqueue_->tail = NULL;
_lqueue_->count--;
return true;
}
bool lq_enqueue_if(linkedqueue *_lqueue_, size_t element, bool condition)
{
if (condition)
return lq_enqueue(_lqueue_, element);
return false;
}
bool lq_dequeue_if(linkedqueue *_lqueue_, bool condition)
{
if (condition)
return lq_dequeue(_lqueue_);
return false;
}
size_t lq_peek(linkedqueue *_lqueue_)
{
if (lq_empty(_lqueue_))
return lq_impl_default_value();
return _lqueue_->head->data;
}
bool lq_contains(linkedqueue *_lqueue_, size_t element, int (*comparator)(size_t, size_t))
{
linkedqueue_node *scan = _lqueue_->head;
while (scan != NULL)
{
if (comparator(scan->data, element) == 0)
return true;
scan = scan->next;
}
return false;
}
bool lq_empty(linkedqueue *_lqueue_) { return _lqueue_->count == 0; }
size_t lq_count(linkedqueue *_lqueue_) { return _lqueue_->count; }
linkedqueue_iter *lq_iter_new(linkedqueue *target)
{
linkedqueue_iter *iter = malloc(sizeof(linkedqueue_iter));
if (!iter)
return NULL;
lq_iter_init(iter, target);
return iter;
}
void lq_iter_free(linkedqueue_iter *iter) { free(iter); }
void lq_iter_init(linkedqueue_iter *iter, linkedqueue *target)
{
iter->target = target;
iter->cursor = target->head;
iter->index = 0;
iter->start = true;
iter->end = lq_empty(target);
}
bool lq_iter_start(linkedqueue_iter *iter) { return lq_empty(iter->target) || iter->start; }
bool lq_iter_end(linkedqueue_iter *iter) { return lq_empty(iter->target) || iter->end; }
void lq_iter_to_start(linkedqueue_iter *iter)
{
iter->cursor = iter->target->head;
iter->index = 0;
iter->start = true;
iter->end = lq_empty(iter->target);
}
void lq_iter_to_end(linkedqueue_iter *iter)
{
iter->cursor = iter->target->tail;
iter->index = iter->target->count - 1;
iter->start = lq_empty(iter->target);
iter->end = true;
}
bool lq_iter_next(linkedqueue_iter *iter)
{
if (iter->end)
return false;
iter->start = lq_empty(iter->target);
if (iter->cursor->next == NULL)
iter->end = true;
else
{
iter->cursor = iter->cursor->next;
iter->index++;
}
return true;
}
size_t lq_iter_value(linkedqueue_iter *iter)
{
if (lq_empty(iter->target))
return lq_impl_default_value();
return iter->cursor->data;
}
size_t *lq_iter_rvalue(linkedqueue_iter *iter)
{
if (lq_empty(iter->target))
return NULL;
return &(iter->cursor->data);
}
size_t lq_iter_index(linkedqueue_iter *iter) { return iter->index; }
linkedqueue_node *lq_impl_new_node(size_t element)
{
linkedqueue_node *_node_ = malloc(sizeof(linkedqueue_node));
if (!_node_)
return NULL;
_node_->data = element;
_node_->next = NULL;
return _node_;
}
static linkedqueue_iter lq_impl_it_start(linkedqueue *_lqueue_)
{
linkedqueue_iter iter;
lq_iter_init(&iter, _lqueue_);
lq_iter_to_start(&iter);
return iter;
}
+35
View File
@@ -0,0 +1,35 @@
#include "utl.c"
#include <utl/assert.h>
#include <utl/log.h>
#include <utl/test.h>
#include <ext/bidimap.h>
CMC_GENERATE_BIDIMAP(bm, bidimap, size_t, size_t)
CMC_CREATE_UNIT(bidimap_test, true, {
CMC_CREATE_TEST(new, {
bidimap *map = bm_new(100, 0.6, cmp, hash, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
bm_free(map, NULL);
});
CMC_CREATE_TEST(clear[count], {
bidimap *map = bm_new(100, 0.6, cmp, hash, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 50; i++)
cmc_assert(bm_insert(map, i, i));
cmc_assert_equals(size_t, 50, bm_count(map));
bm_clear(map, NULL);
cmc_assert_equals(size_t, 0, bm_count(map));
bm_free(map, NULL);
});
});
+583 -24
View File
@@ -1,38 +1,34 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/deque.c"
#include "utl.c"
#include <utl/assert.h>
#include <utl/log.h>
#include <utl/test.h>
#include <cmc/deque.h>
CMC_GENERATE_DEQUE(d, deque, size_t)
CMC_CREATE_UNIT(deque_test, true, {
CMC_CREATE_TEST(new, {
deque *d = d_new(1000000);
cmc_assert_not_equals(ptr, NULL, d);
bool passed = d->capacity == 1000000 && d->count == 0 && d->buffer;
cmc_assert_not_equals(ptr, NULL, d->buffer);
cmc_assert_equals(size_t, 1000000, d->capacity);
cmc_assert_equals(size_t, 0, d_count(d));
cmc_assert_not_equals(ptr, NULL, d->buffer);
CMC_TEST_PASS_ELSE_FAIL(passed);
d_free(d);
d_free(d, NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
CMC_CREATE_TEST(new[capacity = 0], {
deque *d = d_new(0);
cmc_assert_equals(ptr, NULL, d);
CMC_TEST_PASS_ELSE_FAIL(d == NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
CMC_CREATE_TEST(new[capacity = UINT64_MAX], {
deque *d = d_new(UINT64_MAX);
cmc_assert_equals(ptr, NULL, d);
CMC_TEST_PASS_ELSE_FAIL(d == NULL);
});
CMC_CREATE_TEST(clear[count capacity], {
@@ -45,17 +41,15 @@ CMC_CREATE_UNIT(deque_test, true, {
cmc_assert_equals(size_t, 50, d_count(d));
d_clear(d);
d_clear(d, NULL);
cmc_assert_equals(size_t, 0, d_count(d));
cmc_assert_equals(size_t, 100, d_capacity(d));
CMC_TEST_PASS_ELSE_FAIL(d_count(d) == 0 && d_capacity(d) == 100);
d_free(d);
d_free(d, NULL);
});
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
CMC_CREATE_TEST(buffer_growth[capacity = 1], {
deque *d = d_new(1);
cmc_assert_not_equals(ptr, NULL, d);
@@ -66,9 +60,574 @@ CMC_CREATE_UNIT(deque_test, true, {
cmc_assert_equals(size_t, 50, d_count(d));
cmc_assert_lesser_equals(size_t, d_capacity(d), d_count(d));
CMC_TEST_PASS_ELSE_FAIL(d_count(d) == 50 && d_count(d) <= d_capacity(d));
d_free(d);
d_free(d, NULL);
});
CMC_CREATE_TEST(buffer_growth[item preservation], {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
for (size_t i = 1; i <= 1200; i++)
{
if (i % 2 == 0)
d_push_front(d, i);
else
d_push_back(d, i);
}
size_t sum = 0;
for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++)
sum += d->buffer[i];
cmc_assert_equals(size_t, 1200, d_count(d));
cmc_assert_equals(size_t, 720600, sum);
d_free(d, NULL);
});
CMC_CREATE_TEST(push_front[count capacity], {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
for (size_t i = 0; i < 150; i++)
cmc_assert(d_push_front(d, i));
cmc_assert_equals(size_t, 150, d_count(d));
cmc_assert_greater(size_t, 100, d_capacity(d));
d_free(d, NULL);
});
CMC_CREATE_TEST(push_front[item preservation], {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
for (size_t i = 1; i <= 100; i++)
cmc_assert(d_push_front(d, i));
size_t sum = 0;
for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++)
{
sum += d->buffer[i];
}
cmc_assert_equals(size_t, 5050, sum);
d_free(d, NULL);
});
CMC_CREATE_TEST(push_back[count capacity], {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
for (size_t i = 0; i < 150; i++)
cmc_assert(d_push_back(d, i));
cmc_assert_equals(size_t, 150, d_count(d));
cmc_assert_greater(size_t, 100, d_capacity(d));
d_free(d, NULL);
});
CMC_CREATE_TEST(push_back[item preservation], {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
for (size_t i = 1; i <= 100; i++)
cmc_assert(d_push_back(d, i));
size_t sum = 0;
for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++)
{
sum += d->buffer[i];
}
cmc_assert_equals(size_t, 5050, sum);
d_free(d, NULL);
});
CMC_CREATE_TEST(pop_front[count capacity], {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
cmc_assert(d_push_front(d, 10));
cmc_assert(d_pop_front(d));
cmc_assert_equals(size_t, 0, d_count(d));
cmc_assert(d_push_back(d, 10));
cmc_assert(d_pop_front(d));
cmc_assert_equals(size_t, 0, d_count(d));
d_free(d, NULL);
});
CMC_CREATE_TEST(pop_front[item preservation], {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
for (size_t i = 1; i <= 200; i++)
cmc_assert(d_push_front(d, i));
for (size_t i = 0; i < 100; i++)
cmc_assert(d_pop_front(d));
size_t sum = 0;
for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++)
{
sum += d->buffer[i];
}
cmc_assert_equals(size_t, 5050, sum);
d_free(d, NULL);
});
CMC_CREATE_TEST(pop_back[count capacity], {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
cmc_assert(d_push_front(d, 10));
cmc_assert(d_pop_back(d));
cmc_assert_equals(size_t, 0, d_count(d));
cmc_assert(d_push_back(d, 10));
cmc_assert(d_pop_back(d));
cmc_assert_equals(size_t, 0, d_count(d));
d_free(d, NULL);
});
CMC_CREATE_TEST(pop_back[item preservation], {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
for (size_t i = 1; i <= 200; i++)
cmc_assert(d_push_back(d, i));
for (size_t i = 0; i < 100; i++)
cmc_assert(d_pop_back(d));
size_t sum = 0;
for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++)
{
sum += d->buffer[i];
}
cmc_assert_equals(size_t, 5050, sum);
d_free(d, NULL);
});
CMC_CREATE_TEST(Mixed IO, {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
cmc_assert(d_push_front(d, 10));
cmc_assert(d_push_front(d, 10));
cmc_assert(d_pop_back(d));
cmc_assert(d_pop_back(d));
cmc_assert_equals(size_t, 0, d_count(d));
cmc_assert(d_push_back(d, 10));
cmc_assert(d_push_back(d, 10));
cmc_assert(d_pop_back(d));
cmc_assert(d_pop_back(d));
cmc_assert_equals(size_t, 0, d_count(d));
cmc_assert(d_push_front(d, 10));
cmc_assert(d_push_front(d, 10));
cmc_assert(d_pop_front(d));
cmc_assert(d_pop_front(d));
cmc_assert_equals(size_t, 0, d_count(d));
cmc_assert(d_push_back(d, 10));
cmc_assert(d_push_back(d, 10));
cmc_assert(d_pop_front(d));
cmc_assert(d_pop_front(d));
cmc_assert_equals(size_t, 0, d_count(d));
// ----------
cmc_assert(d_push_back(d, 10));
cmc_assert(d_push_front(d, 10));
cmc_assert(d_pop_back(d));
cmc_assert(d_pop_front(d));
cmc_assert_equals(size_t, 0, d_count(d));
cmc_assert(d_push_back(d, 10));
cmc_assert(d_push_front(d, 10));
cmc_assert(d_pop_front(d));
cmc_assert(d_pop_back(d));
cmc_assert_equals(size_t, 0, d_count(d));
cmc_assert(d_push_front(d, 10));
cmc_assert(d_push_back(d, 10));
cmc_assert(d_pop_back(d));
cmc_assert(d_pop_front(d));
cmc_assert_equals(size_t, 0, d_count(d));
cmc_assert(d_push_front(d, 10));
cmc_assert(d_push_back(d, 10));
cmc_assert(d_pop_front(d));
cmc_assert(d_pop_back(d));
cmc_assert_equals(size_t, 0, d_count(d));
d_free(d, NULL);
});
CMC_CREATE_TEST(front[count = 0], {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
size_t r = d_front(d);
cmc_assert_equals(size_t, (size_t){0}, r);
d_free(d, NULL);
});
CMC_CREATE_TEST(front[sum], {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
size_t sum = 0;
for (size_t i = 0; i <= 100; i++)
{
if (i % 2 == 0)
cmc_assert(d_push_back(d, i));
else
cmc_assert(d_push_front(d, i));
}
while (!d_empty(d))
{
size_t r = d_front(d);
sum += r;
cmc_assert(d_pop_front(d));
}
cmc_assert_equals(size_t, 5050, sum);
d_free(d, NULL);
});
CMC_CREATE_TEST(back[count = 0], {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
size_t r = d_back(d);
cmc_assert_equals(size_t, (size_t){0}, r);
d_free(d, NULL);
});
CMC_CREATE_TEST(back[sum], {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
size_t sum = 0;
for (size_t i = 0; i <= 100; i++)
{
if (i % 2 == 0)
cmc_assert(d_push_back(d, i));
else
cmc_assert(d_push_front(d, i));
}
while (!d_empty(d))
{
size_t r = d_back(d);
sum += r;
cmc_assert(d_pop_back(d));
}
cmc_assert_equals(size_t, 5050, sum);
d_free(d, NULL);
});
CMC_CREATE_TEST(contains, {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
for (size_t i = 1; i <= 20; i++)
cmc_assert(d_push_back(d, i));
for (size_t i = 1; i <= 20; i++)
cmc_assert(d_contains(d, i, cmp));
d_clear(d, NULL);
for (size_t i = 1; i <= 20; i++)
cmc_assert(d_push_front(d, i));
for (size_t i = 1; i <= 20; i++)
cmc_assert(d_contains(d, i, cmp));
d_free(d, NULL);
});
CMC_CREATE_TEST(contains[count = 0], {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
cmc_assert(!d_contains(d, 10, cmp));
d_free(d, NULL);
});
CMC_CREATE_TEST(contains[count = 1], {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
cmc_assert(!d_contains(d, 10, cmp));
cmc_assert(d_push_back(d, 100));
cmc_assert(d_contains(d, 100, cmp));
cmc_assert(!d_contains(d, 101, cmp));
cmc_assert(d_pop_front(d));
cmc_assert(d_push_front(d, 100));
cmc_assert(d_contains(d, 100, cmp));
cmc_assert(!d_contains(d, 101, cmp));
d_free(d, NULL);
});
CMC_CREATE_TEST(empty, {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
cmc_assert(d_empty(d));
cmc_assert(d_push_front(d, 1));
cmc_assert(!d_empty(d));
d_free(d, NULL);
});
CMC_CREATE_TEST(full, {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
cmc_assert(!d_full(d));
for (size_t i = 0; i != d_capacity(d); i++)
cmc_assert(d_push_front(d, i));
cmc_assert(d_full(d));
d_free(d, NULL);
});
CMC_CREATE_TEST(count, {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
cmc_assert_equals(size_t, 0, d_count(d));
for (size_t i = 0; i < 100; i++)
cmc_assert(d_push_back(d, i));
cmc_assert_equals(size_t, 100, d_count(d));
d_free(d, NULL);
});
CMC_CREATE_TEST(capacity, {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
cmc_assert_equals(size_t, 100, d_capacity(d));
d_free(d, NULL);
});
CMC_CREATE_TEST(resize, {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
for (size_t i = 0; i < 150; i++)
{
if (i % 2 == 0)
cmc_assert(d_push_back(d, i));
else
cmc_assert(d_push_front(d, i));
}
cmc_assert_equals(size_t, 150, d_count(d));
cmc_assert(d_resize(d, d_count(d)));
cmc_assert_equals(size_t, 150, d_capacity(d));
d_free(d, NULL);
});
CMC_CREATE_TEST(resize[item preservation], {
deque *d = d_new(100);
cmc_assert_not_equals(ptr, NULL, d);
for (size_t i = 1; i <= 150; i++)
{
if (i % 2 != 0)
cmc_assert(d_push_back(d, i));
else
cmc_assert(d_push_front(d, i));
}
cmc_assert(d_resize(d, d_count(d)));
size_t sum = 0;
for (size_t i = d->front, j = 0; j < d->count; i = (i + 1) % d->capacity, j++)
{
sum += d->buffer[i];
}
cmc_assert_equals(size_t, 11325, sum);
d_free(d, NULL);
});
CMC_CREATE_TEST(copy_of, {
deque *d1 = d_new(100);
cmc_assert_not_equals(ptr, NULL, d1);
for (size_t i = 1; i <= 150; i++)
{
if (i % 2 != 0)
cmc_assert(d_push_back(d1, i));
else
cmc_assert(d_push_front(d1, i));
}
deque *d2 = d_copy_of(d1, NULL);
cmc_assert_not_equals(ptr, NULL, d2);
cmc_assert_equals(size_t, d_count(d1), d_count(d2));
for (size_t i1 = d1->front, i2 = d2->front, j = 0; j < d1->count; j++)
{
cmc_assert_equals(size_t, d1->buffer[i1], d2->buffer[i2]);
i1 = (i1 + 1) % d1->capacity;
i2 = (i2 + 1) % d2->capacity;
}
d_free(d1, NULL);
d_free(d2, NULL);
});
CMC_CREATE_TEST(equals, {
deque *d1 = d_new(100);
deque *d2 = d_new(100);
cmc_assert_not_equals(ptr, NULL, d1);
cmc_assert_not_equals(ptr, NULL, d2);
for (size_t i = 1; i <= 150; i++)
{
if (i % 2 != 0)
{
cmc_assert(d_push_back(d1, i));
cmc_assert(d_push_back(d2, i));
}
else
{
cmc_assert(d_push_front(d1, i));
cmc_assert(d_push_front(d2, i));
}
}
cmc_assert(d_equals(d1, d2, cmp));
d_free(d1, NULL);
d_free(d2, NULL);
});
CMC_CREATE_TEST(equals[from copy], {
deque *d1 = d_new(100);
cmc_assert_not_equals(ptr, NULL, d1);
for (size_t i = 1; i <= 150; i++)
{
if (i % 2 != 0)
cmc_assert(d_push_back(d1, i));
else
cmc_assert(d_push_front(d1, i));
}
deque *d2 = d_copy_of(d1, NULL);
cmc_assert_not_equals(ptr, NULL, d2);
cmc_assert(d_equals(d1, d2, cmp));
d_free(d1, NULL);
d_free(d2, NULL);
});
CMC_CREATE_TEST(equals[count = 0], {
deque *d1 = d_new(100);
cmc_assert_not_equals(ptr, NULL, d1);
deque *d2 = d_copy_of(d1, NULL);
cmc_assert_not_equals(ptr, NULL, d2);
cmc_assert(d_equals(d1, d2, cmp));
d_free(d1, NULL);
d_free(d2, NULL);
});
});
+419 -20
View File
@@ -1,37 +1,34 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/hashmap.c"
#include "utl.c"
#include <utl/assert.h>
#include <utl/log.h>
#include <utl/test.h>
#include <cmc/hashmap.h>
CMC_GENERATE_HASHMAP(hm, hashmap, size_t, size_t)
CMC_CREATE_UNIT(hashmap_test, true, {
CMC_CREATE_TEST(new, {
hashmap *map = hm_new(943722, 0.6, cmp, hash);
bool passed = (map->capacity >= (943722 / 0.6)) && map->count == 0 && map->buffer;
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_not_equals(ptr, NULL, map->buffer);
cmc_assert_equals(size_t, 0, hm_count(map));
cmc_assert_greater_equals(size_t, (943722 / 0.6), hm_capacity(map));
CMC_TEST_PASS_ELSE_FAIL(passed);
hm_free(map);
hm_free(map, NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
CMC_CREATE_TEST(new[capacity = 0], {
hashmap *map = hm_new(0, 0.6, cmp, hash);
cmc_assert_equals(ptr, NULL, map);
CMC_TEST_PASS_ELSE_FAIL(map == NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
hashmap *map = hm_new(UINT64_MAX, 0.6, cmp, hash);
CMC_CREATE_TEST(new[capacity = UINT64_MAX], {
hashmap *map = hm_new(UINT64_MAX, 0.99, cmp, hash);
cmc_assert_equals(ptr, NULL, map);
CMC_TEST_PASS_ELSE_FAIL(map == NULL);
});
CMC_CREATE_TEST(clear[count capacity], {
@@ -44,13 +41,415 @@ CMC_CREATE_UNIT(hashmap_test, true, {
cmc_assert_equals(size_t, 50, hm_count(map));
hm_clear(map);
hm_clear(map, NULL);
cmc_assert_equals(size_t, 0, hm_count(map));
CMC_TEST_PASS_ELSE_FAIL(hm_count(map) == 0);
hm_free(map);
hm_free(map, NULL);
});
CMC_CREATE_TEST(insert, {
hashmap *map = hm_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert(hm_insert(map, 1, 1));
cmc_assert_equals(size_t, 1, hm_count(map));
hm_free(map, NULL);
});
CMC_CREATE_TEST(insert[smallest capacity], {
hashmap *map = hm_new(1, 0.99, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_equals(size_t, cmc_hashtable_primes[0], hm_capacity(map));
cmc_assert(hm_insert(map, 1, 1));
hm_free(map, NULL);
});
CMC_CREATE_TEST(insert[element position], {
// Using the numhash the key is the hash itself
hashmap *map = hm_new(1, 0.99, cmp, numhash);
cmc_assert_not_equals(ptr, NULL, map);
size_t capacity = hm_capacity(map);
cmc_assert_greater(size_t, 0, capacity);
cmc_assert(hm_insert(map, capacity - 1, capacity - 1));
cmc_assert(hm_insert(map, capacity, capacity));
cmc_assert_equals(size_t, capacity - 1, map->buffer[capacity - 1].key);
cmc_assert_equals(size_t, capacity, map->buffer[0].key);
hm_free(map, NULL);
});
CMC_CREATE_TEST(insert[distance], {
hashmap *map = hm_new(500, 0.6, cmp, hash0);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 200; i++)
cmc_assert(hm_insert(map, i, i));
// Everything is hashed to 0 so key 0 should have dist 0, key 1 dist 1, etc
for (size_t i = 0; i < 200; i++)
cmc_assert_equals(size_t, i, map->buffer[i].dist);
hm_free(map, NULL);
});
CMC_CREATE_TEST(insert[distance wrap], {
hashmap *map = hm_new(1, 0.99, cmp, hashcapminus1);
cmc_assert_not_equals(ptr, NULL, map);
size_t capacity = hm_capacity(map);
// Just to be sure, not part of the test
cmc_assert_equals(size_t, cmc_hashtable_primes[0] - 1, hashcapminus1(0));
cmc_assert_equals(size_t, capacity - 1, hashcapminus1(0));
cmc_assert(hm_insert(map, 0, 0));
cmc_assert(hm_insert(map, 1, 1));
cmc_assert_equals(size_t, 0, map->buffer[capacity - 1].dist);
cmc_assert_equals(size_t, 1, map->buffer[0].dist);
hm_free(map, NULL);
});
CMC_CREATE_TEST(insert[distances], {
hashmap *map = hm_new(1, 0.99, cmp, hashcapminus4);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_equals(size_t, cmc_hashtable_primes[0], hm_capacity(map));
for (size_t i = 0; i < 6; i++)
cmc_assert(hm_insert(map, i, i));
for (size_t i = 0; i < 6; i++)
cmc_assert_equals(size_t, i, hm_impl_get_entry(map, i)->dist);
hm_free(map, NULL);
});
CMC_CREATE_TEST(insert[buffer growth and item preservation], {
hashmap *map = hm_new(1, 0.99, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_equals(size_t, cmc_hashtable_primes[0], hm_capacity(map));
size_t p = 0;
for (size_t i = 0; i < 100000; i++)
{
if (hm_full(map))
p++;
cmc_assert(hm_insert(map, i, i));
}
cmc_assert_equals(size_t, cmc_hashtable_primes[p], hm_capacity(map));
for (size_t i = 0; i < 100000; i++)
cmc_assert(hm_contains(map, i));
hm_free(map, NULL);
});
CMC_CREATE_TEST(update, {
hashmap *map = hm_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert(hm_insert(map, 1, 1));
size_t old;
cmc_assert(hm_update(map, 1, 2, &old));
cmc_assert_equals(size_t, 1, old);
hm_free(map, NULL);
});
CMC_CREATE_TEST(update[key not found], {
hashmap *map = hm_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 100; i++)
cmc_assert(hm_insert(map, i, i));
cmc_assert(!hm_update(map, 120, 120, NULL));
hm_free(map, NULL);
});
CMC_CREATE_TEST(remove, {
hashmap *map = hm_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 100; i++)
cmc_assert(hm_insert(map, i, i));
for (size_t i = 0; i < 100; i++)
cmc_assert(hm_remove(map, i, NULL));
hm_free(map, NULL);
});
CMC_CREATE_TEST(remove[count = 0], {
hashmap *map = hm_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 100; i < 200; i++)
cmc_assert(!hm_remove(map, i, NULL));
hm_free(map, NULL);
});
CMC_CREATE_TEST(remove[key not found], {
hashmap *map = hm_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 100; i++)
cmc_assert(hm_insert(map, i, i));
for (size_t i = 100; i < 200; i++)
cmc_assert(!hm_remove(map, i, NULL));
hm_free(map, NULL);
});
CMC_CREATE_TEST(max, {
hashmap *map = hm_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 1; i <= 100; i++)
cmc_assert(hm_insert(map, i, i));
size_t key;
size_t val;
cmc_assert(hm_max(map, &key, &val));
cmc_assert_equals(size_t, 100, key);
cmc_assert_equals(size_t, 100, val);
hm_free(map, NULL);
});
CMC_CREATE_TEST(max[count = 0], {
hashmap *map = hm_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert(!hm_min(map, NULL, NULL));
hm_free(map, NULL);
});
CMC_CREATE_TEST(min, {
hashmap *map = hm_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 1; i <= 100; i++)
cmc_assert(hm_insert(map, i, i));
size_t key;
size_t val;
cmc_assert(hm_min(map, &key, &val));
cmc_assert_equals(size_t, 1, key);
cmc_assert_equals(size_t, 1, val);
hm_free(map, NULL);
});
CMC_CREATE_TEST(min[count = 0], {
hashmap *map = hm_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert(!hm_min(map, NULL, NULL));
hm_free(map, NULL);
});
CMC_CREATE_TEST(get, {
hashmap *map = hm_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert(hm_insert(map, 4321, 1234));
cmc_assert_equals(size_t, 1234, hm_get(map, 4321));
hm_free(map, NULL);
});
CMC_CREATE_TEST(get[count = 0], {
hashmap *map = hm_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_equals(size_t, (size_t){0}, hm_get(map, 4321));
hm_free(map, NULL);
});
CMC_CREATE_TEST(get_ref, {
hashmap *map = hm_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert(hm_insert(map, 4321, 1234));
size_t *result = hm_get_ref(map, 4321);
cmc_assert_not_equals(ptr, NULL, result);
cmc_assert_equals(size_t, 1234, *result);
hm_free(map, NULL);
});
CMC_CREATE_TEST(get_ref[count = 0], {
hashmap *map = hm_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_equals(ptr, NULL, hm_get_ref(map, 4321));
hm_free(map, NULL);
});
CMC_CREATE_TEST(contains, {
hashmap *map = hm_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert(hm_insert(map, 987654321, 1));
cmc_assert(hm_contains(map, 987654321));
hm_free(map, NULL);
});
CMC_CREATE_TEST(contains[count = 0], {
hashmap *map = hm_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert(!hm_contains(map, 987654321));
hm_free(map, NULL);
});
CMC_CREATE_TEST(contains[sum], {
hashmap *map = hm_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 101; i <= 200; i++)
cmc_assert(hm_insert(map, i, i));
size_t sum = 0;
for (size_t i = 1; i <= 300; i++)
if (hm_contains(map, i))
sum += i;
cmc_assert_equals(size_t, 15050, sum);
hm_free(map, NULL);
});
CMC_CREATE_TEST(empty, {
hashmap *map = hm_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert(hm_empty(map));
cmc_assert(hm_insert(map, 1, 1));
cmc_assert(!hm_empty(map));
hm_free(map, NULL);
});
CMC_CREATE_TEST(full, {
hashmap *map = hm_new(cmc_hashtable_primes[0], 0.99999, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_equals(size_t, cmc_hashtable_primes[0], hm_capacity(map));
for (size_t i = 0; i < hm_capacity(map); i++)
cmc_assert(hm_insert(map, i, i));
cmc_assert(hm_full(map));
cmc_assert(hm_insert(map, 10000, 10000));
cmc_assert_equals(size_t, cmc_hashtable_primes[1], hm_capacity(map));
cmc_assert(!hm_full(map));
hm_free(map, NULL);
});
CMC_CREATE_TEST(count, {
hashmap *map = hm_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 1; i < 100; i++)
{
cmc_assert(hm_insert(map, i, i));
cmc_assert_equals(size_t, i, hm_count(map));
}
hm_free(map, NULL);
});
CMC_CREATE_TEST(capacity, {
hashmap *map = hm_new(2500, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_greater_equals(size_t, (size_t)(2500 / 0.6), hm_capacity(map));
hm_free(map, NULL);
});
CMC_CREATE_TEST(capacity[small], {
hashmap *map = hm_new(1, 0.99, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_equals(size_t, cmc_hashtable_primes[0], hm_capacity(map));
hm_free(map, NULL);
});
CMC_CREATE_TEST(load, {
hashmap *map = hm_new(1, 0.99, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_in_range(double, 0.99 - 0.0001, 0.99 + 0.0001, hm_load(map));
hm_free(map, NULL);
});
});
+325 -21
View File
@@ -1,37 +1,34 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/hashset.c"
#include "utl.c"
#include <utl/assert.h>
#include <utl/log.h>
#include <utl/test.h>
#include <cmc/hashset.h>
CMC_GENERATE_HASHSET(hs, hashset, size_t)
CMC_CREATE_UNIT(hashset_test, true, {
CMC_CREATE_TEST(new, {
hashset *set = hs_new(943722, 0.6, cmp, hash);
bool passed = (set->capacity >= (943722 / 0.6)) && set->count == 0 && set->buffer;
cmc_assert_not_equals(ptr, NULL, set);
cmc_assert(hs_capacity(set) > (943722 / 0.6));
cmc_assert_not_equals(ptr, NULL, set->buffer);
cmc_assert_equals(size_t, 0, hs_count(set));
cmc_assert_greater_equals(size_t, (943722 / 0.6), hs_capacity(set));
CMC_TEST_PASS_ELSE_FAIL(passed);
hs_free(set);
hs_free(set, NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
CMC_CREATE_TEST(new[capacity = 0], {
hashset *set = hs_new(0, 0.6, cmp, hash);
cmc_assert_equals(ptr, NULL, set);
CMC_TEST_PASS_ELSE_FAIL(set == NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
hashset *set = hs_new(UINT64_MAX, 0.6, cmp, hash);
CMC_CREATE_TEST(new[capacity = UINT64_MAX], {
hashset *set = hs_new(UINT64_MAX, 0.99, cmp, hash);
cmc_assert_equals(ptr, NULL, set);
CMC_TEST_PASS_ELSE_FAIL(set == NULL);
});
CMC_CREATE_TEST(clear[count capacity], {
@@ -44,13 +41,320 @@ CMC_CREATE_UNIT(hashset_test, true, {
cmc_assert_equals(size_t, 50, hs_count(set));
hs_clear(set);
hs_clear(set, NULL);
cmc_assert_equals(size_t, 0, hs_count(set));
CMC_TEST_PASS_ELSE_FAIL(hs_count(set) == 0);
hs_free(set);
hs_free(set, NULL);
});
CMC_CREATE_TEST(insert, {
hashset *set = hs_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
cmc_assert(hs_insert(set, 1));
cmc_assert_equals(size_t, 1, hs_count(set));
hs_free(set, NULL);
});
CMC_CREATE_TEST(insert[smallest capacity], {
hashset *set = hs_new(1, 0.99, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
cmc_assert_equals(size_t, cmc_hashtable_primes[0], hs_capacity(set));
cmc_assert(hs_insert(set, 1));
hs_free(set, NULL);
});
CMC_CREATE_TEST(insert[element position], {
// Using the numhash the key is the hash itself
hashset *set = hs_new(1, 0.99, cmp, numhash);
cmc_assert_not_equals(ptr, NULL, set);
size_t capacity = hs_capacity(set);
cmc_assert_greater(size_t, 0, capacity);
cmc_assert(hs_insert(set, capacity - 1));
cmc_assert(hs_insert(set, capacity));
cmc_assert_equals(size_t, capacity - 1, set->buffer[capacity - 1].value);
cmc_assert_equals(size_t, capacity, set->buffer[0].value);
hs_free(set, NULL);
});
CMC_CREATE_TEST(insert[distance], {
hashset *set = hs_new(500, 0.6, cmp, hash0);
cmc_assert_not_equals(ptr, NULL, set);
for (size_t i = 0; i < 200; i++)
cmc_assert(hs_insert(set, i));
// Everything is hashed to 0 so key 0 should have dist 0, key 1 dist 1, etc
for (size_t i = 0; i < 200; i++)
cmc_assert_equals(size_t, i, set->buffer[i].dist);
hs_free(set, NULL);
});
CMC_CREATE_TEST(insert[distance wrap], {
hashset *set = hs_new(1, 0.99, cmp, hashcapminus1);
cmc_assert_not_equals(ptr, NULL, set);
size_t capacity = hs_capacity(set);
// Just to be sure, not part of the test
cmc_assert_equals(size_t, cmc_hashtable_primes[0] - 1, hashcapminus1(0));
cmc_assert_equals(size_t, capacity - 1, hashcapminus1(0));
cmc_assert(hs_insert(set, 0));
cmc_assert(hs_insert(set, 1));
cmc_assert_equals(size_t, 0, set->buffer[capacity - 1].dist);
cmc_assert_equals(size_t, 1, set->buffer[0].dist);
hs_free(set, NULL);
});
CMC_CREATE_TEST(insert[buffer growth and item preservation], {
hashset *set = hs_new(1, 0.99, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
cmc_assert_equals(size_t, cmc_hashtable_primes[0], hs_capacity(set));
size_t p = 0;
for (size_t i = 0; i < 100000; i++)
{
if (hs_full(set))
p++;
cmc_assert(hs_insert(set, i));
}
cmc_assert_equals(size_t, cmc_hashtable_primes[p], hs_capacity(set));
for (size_t i = 0; i < 100000; i++)
cmc_assert(hs_contains(set, i));
hs_free(set, NULL);
});
CMC_CREATE_TEST(remove, {
hashset *set = hs_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
for (size_t i = 0; i < 100; i++)
cmc_assert(hs_insert(set, i));
for (size_t i = 0; i < 100; i++)
cmc_assert(hs_remove(set, i));
hs_free(set, NULL);
});
CMC_CREATE_TEST(remove[count = 0], {
hashset *set = hs_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
for (size_t i = 100; i < 200; i++)
cmc_assert(!hs_remove(set, i));
hs_free(set, NULL);
});
CMC_CREATE_TEST(remove[key not found], {
hashset *set = hs_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
for (size_t i = 0; i < 100; i++)
cmc_assert(hs_insert(set, i));
for (size_t i = 100; i < 200; i++)
cmc_assert(!hs_remove(set, i));
hs_free(set, NULL);
});
CMC_CREATE_TEST(max, {
hashset *set = hs_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
for (size_t i = 1; i <= 100; i++)
cmc_assert(hs_insert(set, i));
size_t val;
cmc_assert(hs_max(set, &val));
cmc_assert_equals(size_t, 100, val);
hs_free(set, NULL);
});
CMC_CREATE_TEST(max[count = 0], {
hashset *set = hs_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
cmc_assert(!hs_min(set, NULL));
hs_free(set, NULL);
});
CMC_CREATE_TEST(min, {
hashset *set = hs_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
for (size_t i = 1; i <= 100; i++)
cmc_assert(hs_insert(set, i));
size_t val;
cmc_assert(hs_min(set, &val));
cmc_assert_equals(size_t, 1, val);
hs_free(set, NULL);
});
CMC_CREATE_TEST(min[count = 0], {
hashset *set = hs_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
cmc_assert(!hs_min(set, NULL));
hs_free(set, NULL);
});
CMC_CREATE_TEST(contains, {
hashset *set = hs_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
cmc_assert(hs_insert(set, 987654321));
cmc_assert(hs_contains(set, 987654321));
hs_free(set, NULL);
});
CMC_CREATE_TEST(contains[count = 0], {
hashset *set = hs_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
cmc_assert(!hs_contains(set, 987654321));
hs_free(set, NULL);
});
CMC_CREATE_TEST(contains[sum], {
hashset *set = hs_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
for (size_t i = 101; i <= 200; i++)
cmc_assert(hs_insert(set, i));
size_t sum = 0;
for (size_t i = 1; i <= 300; i++)
if (hs_contains(set, i))
sum += i;
cmc_assert_equals(size_t, 15050, sum);
hs_free(set, NULL);
});
CMC_CREATE_TEST(empty, {
hashset *set = hs_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
cmc_assert(hs_empty(set));
cmc_assert(hs_insert(set, 1));
cmc_assert(!hs_empty(set));
hs_free(set, NULL);
});
CMC_CREATE_TEST(full, {
hashset *set = hs_new(cmc_hashtable_primes[0], 0.99999, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
cmc_assert_equals(size_t, cmc_hashtable_primes[0], hs_capacity(set));
for (size_t i = 0; i < hs_capacity(set); i++)
cmc_assert(hs_insert(set, i));
cmc_assert(hs_full(set));
cmc_assert(hs_insert(set, 10000));
cmc_assert_equals(size_t, cmc_hashtable_primes[1], hs_capacity(set));
cmc_assert(!hs_full(set));
hs_free(set, NULL);
});
CMC_CREATE_TEST(count, {
hashset *set = hs_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
for (size_t i = 1; i < 100; i++)
{
cmc_assert(hs_insert(set, i));
cmc_assert_equals(size_t, i, hs_count(set));
}
hs_free(set, NULL);
});
CMC_CREATE_TEST(capacity, {
hashset *set = hs_new(2500, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
cmc_assert_greater_equals(size_t, (size_t)(2500 / 0.6), hs_capacity(set));
hs_free(set, NULL);
});
CMC_CREATE_TEST(capacity[small], {
hashset *set = hs_new(1, 0.99, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
cmc_assert_equals(size_t, cmc_hashtable_primes[0], hs_capacity(set));
hs_free(set, NULL);
});
CMC_CREATE_TEST(load, {
hashset *set = hs_new(1, 0.99, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
cmc_assert_in_range(double, 0.99 - 0.0001, 0.99 + 0.0001, hs_load(set));
hs_free(set, NULL);
});
});
+116 -27
View File
@@ -1,40 +1,34 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/heap.c"
#include "utl.c"
#include <utl/assert.h>
#include <utl/log.h>
#include <utl/test.h>
#include <cmc/heap.h>
CMC_GENERATE_HEAP(h, heap, size_t)
CMC_CREATE_UNIT(heap_test, true, {
CMC_CREATE_TEST(new, {
heap *h = h_new(1000000, cmc_max_heap, cmp);
cmc_assert_not_equals(ptr, NULL, h);
bool passed = h->capacity == 1000000 && h->count == 0 && h->buffer;
cmc_assert_equals(size_t, 1000000, h->capacity);
cmc_assert_equals(size_t, 0, h_count(h));
cmc_assert_not_equals(ptr, NULL, h->buffer);
cmc_assert_equals(size_t, 1000000, h_capacity(h));
cmc_assert_equals(size_t, 0, h_count(h));
CMC_TEST_PASS_ELSE_FAIL(passed);
h_free(h);
h_free(h, NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
CMC_CREATE_TEST(new[edge_case capacity = 0], {
heap *h = h_new(0, cmc_max_heap, cmp);
cmc_assert_equals(ptr, NULL, h);
CMC_TEST_PASS_ELSE_FAIL(h == NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
CMC_CREATE_TEST(new[edge_case capacity = UINT64_MAX], {
heap *h = h_new(UINT64_MAX, cmc_max_heap, cmp);
cmc_assert_equals(ptr, NULL, h);
CMC_TEST_PASS_ELSE_FAIL(h == NULL);
});
CMC_CREATE_TEST(clear[count capacity], {
@@ -47,29 +41,124 @@ CMC_CREATE_UNIT(heap_test, true, {
cmc_assert_equals(size_t, 50, h_count(h));
h_clear(h);
h_clear(h, NULL);
cmc_assert_equals(size_t, 0, h_count(h));
cmc_assert_equals(size_t, 100, h_capacity(h));
CMC_TEST_PASS_ELSE_FAIL(h_count(h) == 0 && h_capacity(h) == 100);
h_free(h);
h_free(h, NULL);
});
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
CMC_CREATE_TEST(buffer_growth[edge_case capacity = 1], {
heap *h = h_new(1, cmc_max_heap, cmp);
cmc_assert_not_equals(ptr, NULL, h);
for (size_t i = 0; i < 50; i++)
h_insert(h, i);
cmc_assert(h_insert(h, i));
cmc_assert_equals(size_t, 50, h_count(h));
CMC_TEST_PASS_ELSE_FAIL(h_count(h) == 50);
h_free(h);
h_free(h, NULL);
});
CMC_CREATE_TEST(insert, {
heap *h = h_new(100, cmc_max_heap, cmp);
cmc_assert_not_equals(ptr, NULL, h);
cmc_assert(h_insert(h, 10));
h_free(h, NULL);
});
CMC_CREATE_TEST(insert[item preservation], {
heap *h = h_new(50, cmc_max_heap, cmp);
cmc_assert_not_equals(ptr, NULL, h);
for (size_t i = 0; i <= 100; i++)
cmc_assert(h_insert(h, i));
size_t sum = 0;
for (size_t i = 0; i < h_count(h); i++)
sum += h->buffer[i];
cmc_assert_equals(size_t, 5050, sum);
h_free(h, NULL);
});
CMC_CREATE_TEST(remove, {
heap *h = h_new(50, cmc_max_heap, cmp);
cmc_assert_not_equals(ptr, NULL, h);
for (size_t i = 0; i <= 100; i++)
cmc_assert(h_insert(h, i));
size_t r;
cmc_assert(h_remove(h, &r));
cmc_assert_equals(size_t, 100, r);
h_free(h, NULL);
});
CMC_CREATE_TEST(remove[count = 0], {
heap *h = h_new(100, cmc_max_heap, cmp);
cmc_assert_not_equals(ptr, NULL, h);
size_t _;
cmc_assert(!h_remove(h, &_));
h_free(h, NULL);
});
CMC_CREATE_TEST(remove[sorted], {
heap *h = h_new(100, cmc_min_heap, cmp);
cmc_assert_not_equals(ptr, NULL, h);
for (size_t i = 1; i <= 100; i++)
cmc_assert(h_insert(h, i));
size_t r;
size_t i = 0;
size_t arr[100];
while (!h_empty(h))
{
cmc_assert(h_remove(h, &r));
arr[i++] = r;
}
cmc_assert_array_sorted_any(size_t, arr, cmp, 0, 99);
h_free(h, NULL);
});
CMC_CREATE_TEST(peek, {
heap *h = h_new(100, cmc_max_heap, cmp);
cmc_assert_not_equals(ptr, NULL, h);
for (size_t i = 1; i <= 100; i++)
cmc_assert(h_insert(h, i));
cmc_assert_equals(size_t, 100, h_peek(h));
h_free(h, NULL);
});
CMC_CREATE_TEST(peek[count = 0], {
heap *h = h_new(100, cmc_max_heap, cmp);
cmc_assert_not_equals(ptr, NULL, h);
cmc_assert_equals(size_t, (size_t){0}, h_peek(h));
h_free(h, NULL);
});
});
+134
View File
@@ -0,0 +1,134 @@
#include "utl.c"
#include <utl/assert.h>
#include <utl/log.h>
#include <utl/test.h>
#include <ext/intervalheap.h>
CMC_GENERATE_INTERVALHEAP(ih, intervalheap, size_t)
CMC_CREATE_UNIT(intervalheap_test, true, {
CMC_CREATE_TEST(new, {
intervalheap *ih = ih_new(1000000, cmp);
cmc_assert_not_equals(ptr, NULL, ih);
cmc_assert_not_equals(ptr, NULL, ih->buffer);
cmc_assert_equals(size_t, 500000, ih_capacity(ih));
cmc_assert_equals(size_t, 0, ih_count(ih));
ih_free(ih, NULL);
});
CMC_CREATE_TEST(new[capacity = 0], {
intervalheap *ih = ih_new(0, cmp);
cmc_assert_equals(ptr, NULL, ih);
if (ih)
ih_free(ih, NULL);
});
CMC_CREATE_TEST(new[capacity], {
intervalheap *ih = ih_new(1, cmp);
cmc_assert_not_equals(ptr, NULL, ih);
cmc_assert_equals(size_t, 1, ih_capacity(ih));
ih_free(ih, NULL);
ih = ih_new(2, cmp);
cmc_assert_not_equals(ptr, NULL, ih);
cmc_assert_equals(size_t, 1, ih_capacity(ih));
ih_free(ih, NULL);
ih = ih_new(3, cmp);
cmc_assert_not_equals(ptr, NULL, ih);
cmc_assert_equals(size_t, 2, ih_capacity(ih));
ih_free(ih, NULL);
ih = ih_new(4, cmp);
cmc_assert_not_equals(ptr, NULL, ih);
cmc_assert_equals(size_t, 2, ih_capacity(ih));
ih_free(ih, NULL);
});
CMC_CREATE_TEST(new[capacity = UINT64_MAX], {
intervalheap *ih = ih_new(UINT64_MAX, cmp);
cmc_assert_equals(ptr, NULL, ih);
if (ih)
ih_free(ih, NULL);
});
CMC_CREATE_TEST(clear[count capacity], {
intervalheap *ih = ih_new(100, cmp);
cmc_assert_not_equals(ptr, NULL, ih);
for (size_t i = 0; i < 50; i++)
cmc_assert(ih_insert(ih, i));
cmc_assert_equals(size_t, 50, ih_count(ih));
ih_clear(ih, NULL);
cmc_assert_equals(size_t, 0, ih_count(ih));
cmc_assert_equals(size_t, 50, ih_capacity(ih));
ih_free(ih, NULL);
});
CMC_CREATE_TEST(buffer_growth[capacity = 1], {
intervalheap *ih = ih_new(1, cmp);
cmc_assert_not_equals(ptr, NULL, ih);
for (size_t i = 0; i < 50; i++)
cmc_assert(ih_insert(ih, i));
cmc_assert_equals(size_t, 50, ih_count(ih));
cmc_assert_greater(size_t, 50, ih_capacity(ih) * 2);
ih_free(ih, NULL);
});
CMC_CREATE_TEST(insert[count], {
intervalheap *ih = ih_new(100, cmp);
cmc_assert_not_equals(ptr, NULL, ih);
cmc_assert(ih_insert(ih, 1));
cmc_assert(ih_insert(ih, 0));
cmc_assert_equals(size_t, 2, ih_count(ih));
ih_free(ih, NULL);
});
CMC_CREATE_TEST(insert[max min], {
intervalheap *ih = ih_new(1, cmp);
cmc_assert_not_equals(ptr, NULL, ih);
cmc_assert(ih_insert(ih, 1));
cmc_assert(ih_insert(ih, 0));
size_t min;
size_t max;
cmc_assert(ih_min(ih, &min));
cmc_assert(ih_max(ih, &max));
cmc_assert_equals(size_t, 0, min);
cmc_assert_equals(size_t, 1, max);
ih_free(ih, NULL);
});
});
+17 -32
View File
@@ -1,22 +1,22 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/linkedlist.c"
#include "utl.c"
#include <utl/assert.h>
#include <utl/log.h>
#include <utl/test.h>
#include <cmc/linkedlist.h>
CMC_GENERATE_LINKEDLIST(ll, linkedlist, size_t)
CMC_CREATE_UNIT(linkedlist_test, true, {
CMC_CREATE_TEST(new, {
linkedlist *ll = ll_new();
cmc_assert_not_equals(ptr, NULL, ll);
bool passed = ll->count == 0 && ll->head == NULL && ll->tail == NULL;
cmc_assert_equals(size_t, 0, ll_count(ll));
cmc_assert_equals(ptr, NULL, ll->head);
cmc_assert_equals(ptr, NULL, ll->tail);
CMC_TEST_PASS_ELSE_FAIL(passed);
ll_free(ll);
ll_free(ll, NULL);
});
CMC_CREATE_TEST(clear[count capacity], {
@@ -29,27 +29,23 @@ CMC_CREATE_UNIT(linkedlist_test, true, {
cmc_assert_equals(size_t, 50, ll_count(ll));
ll_clear(ll);
ll_clear(ll, NULL);
cmc_assert_equals(size_t, 0, ll_count(ll));
CMC_TEST_PASS_ELSE_FAIL(ll_count(ll) == 0);
ll_free(ll);
ll_free(ll, NULL);
});
CMC_CREATE_TEST(clear[edge_case:count = 0], {
CMC_CREATE_TEST(clear[count = 0], {
linkedlist *ll = ll_new();
cmc_assert_not_equals(ptr, NULL, ll);
ll_clear(ll);
ll_clear(ll, NULL);
cmc_assert_equals(size_t, 0, ll_count(ll));
CMC_TEST_PASS_ELSE_FAIL(ll_count(ll) == 0);
ll_free(ll);
ll_free(ll, NULL);
});
CMC_CREATE_TEST(push_front[count], {
@@ -63,12 +59,10 @@ CMC_CREATE_UNIT(linkedlist_test, true, {
cmc_assert_not_equals(ptr, NULL, ll->tail);
cmc_assert_equals(size_t, 1, ll_count(ll));
CMC_TEST_PASS_ELSE_FAIL(ll->head && ll->tail && ll_count(ll) == 1);
ll_free(ll);
ll_free(ll, NULL);
});
CMC_CREATE_TEST(push_front[item_preservation], {
CMC_CREATE_TEST(push_front[item preservation], {
linkedlist *ll = ll_new();
cmc_assert_not_equals(ptr, NULL, ll);
@@ -76,18 +70,9 @@ CMC_CREATE_UNIT(linkedlist_test, true, {
for (size_t i = 0; i < 200; i++)
ll_push_front(ll, i);
bool passed = true;
for (size_t i = 0; i < ll_count(ll); i++)
{
passed = passed && ll_get(ll, i) == (ll_count(ll) - i - 1);
cmc_assert_equals(size_t, ll_get(ll, i), ll_count(ll) - i - 1);
}
CMC_TEST_PASS_ELSE_FAIL(passed && ll_count(ll) == 200);
ll_free(ll);
ll_free(ll, NULL);
});
});
-41
View File
@@ -1,41 +0,0 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/linkedqueue.c"
CMC_CREATE_UNIT(linkedqueue_test, true, {
CMC_CREATE_TEST(new, {
linkedqueue *q = lq_new();
cmc_assert_not_equals(ptr, NULL, q);
bool passed = q->count == 0 && !q->head && !q->tail;
cmc_assert_equals(size_t, 0, lq_count(q));
cmc_assert_equals(ptr, NULL, q->head);
cmc_assert_equals(ptr, NULL, q->tail);
CMC_TEST_PASS_ELSE_FAIL(passed);
lq_free(q);
});
CMC_CREATE_TEST(clear[count], {
linkedqueue *q = lq_new();
cmc_assert_not_equals(ptr, NULL, q);
for (size_t i = 0; i < 50; i++)
lq_enqueue(q, i);
cmc_assert_equals(size_t, 50, lq_count(q));
lq_clear(q);
cmc_assert_equals(size_t, 0, lq_count(q));
CMC_TEST_PASS_ELSE_FAIL(lq_count(q) == 0);
lq_free(q);
});
});
+61 -141
View File
@@ -1,41 +1,37 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/list.c"
#include "utl.c"
#include <utl/assert.h>
#include <utl/log.h>
#include <utl/test.h>
#include <cmc/list.h>
CMC_GENERATE_LIST(l, list, size_t)
CMC_CREATE_UNIT(list_test, true, {
CMC_CREATE_TEST(new, {
list *l = l_new(1000000);
cmc_assert_not_equals(ptr, NULL, l);
bool passed = l->capacity == 1000000 && l->count == 0 && l->buffer;
cmc_assert_equals(size_t, 1000000, l->capacity);
cmc_assert_equals(size_t, 0, l_count(l));
cmc_assert_not_equals(ptr, NULL, l->buffer);
cmc_assert_equals(size_t, 1000000, l_capacity(l));
cmc_assert_equals(size_t, 0, l_count(l));
CMC_TEST_PASS_ELSE_FAIL(passed);
l_free(l);
l_free(l, NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
CMC_CREATE_TEST(new[capacity = 0], {
list *l = l_new(0);
cmc_assert_equals(ptr, NULL, l);
CMC_TEST_PASS_ELSE_FAIL(l == NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
CMC_CREATE_TEST(new[capacity = UINT64_MAX], {
list *l = l_new(UINT64_MAX);
cmc_assert_equals(ptr, NULL, l);
CMC_TEST_PASS_ELSE_FAIL(l == NULL);
});
CMC_CREATE_TEST(new_from[count item_preservation], {
CMC_CREATE_TEST(new_from[count and item preservation], {
size_t v[5];
for (size_t i = 0; i < 5; i++)
@@ -47,21 +43,13 @@ CMC_CREATE_UNIT(list_test, true, {
cmc_assert_not_equals(ptr, NULL, l);
bool passed = true;
for (size_t i = 0; i < 5; i++)
{
cmc_assert_equals(size_t, i, l_get(l, i));
passed = passed && l_get(l, i) == i;
}
CMC_TEST_PASS_ELSE_FAIL(passed && l_count(l) == 5);
l_free(l);
l_free(l, NULL);
});
CMC_CREATE_TEST(new_from[edge_case:size = 1], {
CMC_CREATE_TEST(new_from[size = 1], {
size_t a = 10;
size_t *values = &a;
@@ -70,9 +58,7 @@ CMC_CREATE_UNIT(list_test, true, {
cmc_assert_not_equals(ptr, NULL, l);
CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 1);
l_free(l);
l_free(l, NULL);
});
CMC_CREATE_TEST(clear[count capacity], {
@@ -85,17 +71,15 @@ CMC_CREATE_UNIT(list_test, true, {
cmc_assert_equals(size_t, 50, l_count(l));
l_clear(l);
l_clear(l, NULL);
cmc_assert_equals(size_t, 0, l_count(l));
cmc_assert_equals(size_t, 100, l_capacity(l));
CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 0 && l_capacity(l) == 100);
l_free(l);
l_free(l, NULL);
});
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
CMC_CREATE_TEST(buffer_growth[capacity = 1], {
list *l = l_new(1);
cmc_assert_not_equals(ptr, NULL, l);
@@ -105,17 +89,10 @@ CMC_CREATE_UNIT(list_test, true, {
cmc_assert_equals(size_t, 100, l_count(l));
bool passed = true;
for (size_t i = 0; i < 100; i++)
{
passed = passed && l_get(l, i) == i;
cmc_assert_equals(size_t, i, l_get(l, i));
}
CMC_TEST_PASS_ELSE_FAIL(passed);
l_free(l);
l_free(l, NULL);
});
CMC_CREATE_TEST(push_front[count], {
@@ -128,9 +105,7 @@ CMC_CREATE_UNIT(list_test, true, {
cmc_assert_equals(size_t, 250, l_count(l));
CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 250);
l_free(l);
l_free(l, NULL);
});
CMC_CREATE_TEST(push_front[capacity], {
@@ -143,12 +118,10 @@ CMC_CREATE_UNIT(list_test, true, {
cmc_assert_lesser_equals(size_t, l_capacity(l), l_count(l));
CMC_TEST_PASS_ELSE_FAIL(l_count(l) <= l_capacity(l));
l_free(l);
l_free(l, NULL);
});
CMC_CREATE_TEST(push_front[item_preservation], {
CMC_CREATE_TEST(push_front[item preservation], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
@@ -156,21 +129,13 @@ CMC_CREATE_UNIT(list_test, true, {
for (size_t i = 0; i < 250; i++)
cmc_assert(l_push_front(l, i));
bool passed = true;
for (size_t i = 0; i < l_count(l); i++)
{
passed = passed && l_get(l, i) == (l_count(l) - i - 1);
cmc_assert_equals(size_t, l_get(l, i), l_count(l) - i - 1);
}
CMC_TEST_PASS_ELSE_FAIL(passed);
l_free(l);
l_free(l, NULL);
});
CMC_CREATE_TEST(push[count], {
CMC_CREATE_TEST(push_at[count], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
@@ -179,16 +144,14 @@ CMC_CREATE_UNIT(list_test, true, {
cmc_assert(l_push_back(l, 249));
for (size_t i = 1; i < 249; i++)
cmc_assert(l_push(l, i, l_count(l) - 1));
cmc_assert(l_push_at(l, i, l_count(l) - 1));
cmc_assert_equals(size_t, 250, l_count(l));
CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 250);
l_free(l);
l_free(l, NULL);
});
CMC_CREATE_TEST(push[capacity], {
CMC_CREATE_TEST(push_at[capacity], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
@@ -197,16 +160,14 @@ CMC_CREATE_UNIT(list_test, true, {
cmc_assert(l_push_back(l, 249));
for (size_t i = 1; i < 249; i++)
cmc_assert(l_push(l, i, l_count(l) - 1));
cmc_assert(l_push_at(l, i, l_count(l) - 1));
cmc_assert_lesser_equals(size_t, l_capacity(l), l_count(l));
CMC_TEST_PASS_ELSE_FAIL(l_count(l) <= l_capacity(l));
l_free(l);
l_free(l, NULL);
});
CMC_CREATE_TEST(push[item_preservation], {
CMC_CREATE_TEST(push_at[item preservation], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
@@ -215,20 +176,12 @@ CMC_CREATE_UNIT(list_test, true, {
cmc_assert(l_push_back(l, 249));
for (size_t i = 1; i < 249; i++)
cmc_assert(l_push(l, i, l_count(l) - 1));
bool passed = true;
cmc_assert(l_push_at(l, i, l_count(l) - 1));
for (size_t i = 0; i < l_count(l); i++)
{
passed = passed && l_get(l, i) == i;
cmc_assert_equals(size_t, l_get(l, i), i);
}
CMC_TEST_PASS_ELSE_FAIL(passed);
l_free(l);
l_free(l, NULL);
});
CMC_CREATE_TEST(push_back[count], {
@@ -241,9 +194,7 @@ CMC_CREATE_UNIT(list_test, true, {
cmc_assert_equals(size_t, 250, l_count(l));
CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 250);
l_free(l);
l_free(l, NULL);
});
CMC_CREATE_TEST(push_back[capacity], {
@@ -256,12 +207,10 @@ CMC_CREATE_UNIT(list_test, true, {
cmc_assert_lesser_equals(size_t, l_capacity(l), l_count(l));
CMC_TEST_PASS_ELSE_FAIL(l_count(l) <= l_capacity(l));
l_free(l);
l_free(l, NULL);
});
CMC_CREATE_TEST(push_back[item_preservation], {
CMC_CREATE_TEST(push_back[item preservation], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
@@ -269,18 +218,10 @@ CMC_CREATE_UNIT(list_test, true, {
for (size_t i = 0; i < 250; i++)
cmc_assert(l_push_back(l, i));
bool passed = true;
for (size_t i = 0; i < l_count(l); i++)
{
passed = passed && l_get(l, i) == i;
cmc_assert_equals(size_t, l_get(l, i), i);
}
CMC_TEST_PASS_ELSE_FAIL(passed);
l_free(l);
l_free(l, NULL);
});
CMC_CREATE_TEST(pop_front[count], {
@@ -293,12 +234,10 @@ CMC_CREATE_UNIT(list_test, true, {
cmc_assert(l_pop_front(l));
CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 250 - 1);
l_free(l);
l_free(l, NULL);
});
CMC_CREATE_TEST(pop_front[item_preservation], {
CMC_CREATE_TEST(pop_front[item preservation], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
@@ -306,40 +245,31 @@ CMC_CREATE_UNIT(list_test, true, {
for (size_t i = 0; i < 250; i++)
l_push_back(l, i);
bool passed = l_pop_front(l);
cmc_assert(l_pop_front(l));
for (size_t i = 0; i < l_count(l); i++)
{
passed = passed && l_get(l, i) == i + 1;
cmc_assert_equals(size_t, l_get(l, i), i + 1);
}
CMC_TEST_PASS_ELSE_FAIL(passed);
l_free(l);
l_free(l, NULL);
});
CMC_CREATE_TEST(pop_front[edge_case:count = 0], {
CMC_CREATE_TEST(pop_front[count = 0], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(!l_pop_front(l));
CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 0);
l_free(l);
l_free(l, NULL);
});
CMC_CREATE_TEST(pop_front[edge_case:count = 1], {
CMC_CREATE_TEST(pop_front[count = 1], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(l_push_back(l, 10));
cmc_assert(l_pop_front(l));
CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 0);
l_free(l);
l_free(l, NULL);
});
CMC_CREATE_TEST(pop_front[buffer_clear], {
@@ -349,72 +279,62 @@ CMC_CREATE_UNIT(list_test, true, {
cmc_assert(l_push_back(l, 1));
cmc_assert(l_push_front(l, 2));
bool passed = l_pop_front(l) && l->buffer[1] == 0;
cmc_assert(l_pop_front(l));
cmc_assert_equals(size_t, 0, l->buffer[1]);
CMC_TEST_PASS_ELSE_FAIL(passed && l_count(l) == 1);
l_free(l);
l_free(l, NULL);
});
CMC_CREATE_TEST(pop[edge_case:count = 0], {
CMC_CREATE_TEST(pop_at[count = 0], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(!l_pop(l, 1));
cmc_assert(!l_pop_at(l, 1));
CMC_TEST_PASS_ELSE_FAIL(!l_pop(l, 1));
l_free(l);
l_free(l, NULL);
});
CMC_CREATE_TEST(pop[edge_case:count = 1], {
CMC_CREATE_TEST(pop_at[count = 1], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(l_push_back(l, 1));
CMC_TEST_PASS_ELSE_FAIL(l_pop(l, 0));
cmc_assert(l_pop_at(l, 0));
cmc_assert_equals(size_t, 0, l->buffer[0]);
l_free(l);
l_free(l, NULL);
});
CMC_CREATE_TEST(pop[buffer_clear], {
CMC_CREATE_TEST(pop_at[buffer_clear], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(l_push_back(l, 1));
cmc_assert(l_push_back(l, 2));
cmc_assert(l_push_back(l, 3));
cmc_assert(l_pop(l, 1));
cmc_assert(l_pop_at(l, 1));
CMC_TEST_PASS_ELSE_FAIL(0 == l->buffer[2]);
l_free(l);
l_free(l, NULL);
});
CMC_CREATE_TEST(pop_back[edge_case:count = 0], {
CMC_CREATE_TEST(pop_back[count = 0], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(!l_pop_back(l));
CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 0);
l_free(l);
l_free(l, NULL);
});
CMC_CREATE_TEST(pop_back[edge_case:count = 1], {
CMC_CREATE_TEST(pop_back[count = 1], {
list *l = l_new(100);
cmc_assert_not_equals(ptr, NULL, l);
cmc_assert(l_push_back(l, 10));
cmc_assert(l_pop_back(l));
CMC_TEST_PASS_ELSE_FAIL(l_count(l) == 0);
l_free(l);
l_free(l, NULL);
});
})
+40 -75
View File
@@ -1,37 +1,34 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/multimap.c"
#include "utl.c"
#include <utl/assert.h>
#include <utl/log.h>
#include <utl/test.h>
#include <ext/multimap.h>
CMC_GENERATE_MULTIMAP(mm, multimap, size_t, size_t)
CMC_CREATE_UNIT(multimap_test, true, {
CMC_CREATE_TEST(new, {
multimap *map = mm_new(943722, 0.8, cmp, hash);
bool passed = (map->capacity >= (943722 / 0.8)) && map->count == 0 && map->buffer;
cmc_assert_not_equals(ptr, NULL, map);
cmc_assert_not_equals(ptr, NULL, map->buffer);
cmc_assert_equals(size_t, 0, mm_count(map));
cmc_assert_greater_equals(size_t, (943722 / 0.8), mm_capacity(map));
CMC_TEST_PASS_ELSE_FAIL(passed);
mm_free(map);
mm_free(map, NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
CMC_CREATE_TEST(new[capacity = 0], {
multimap *map = mm_new(0, 0.8, cmp, hash);
cmc_assert_equals(ptr, NULL, map);
CMC_TEST_PASS_ELSE_FAIL(map == NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
multimap *map = mm_new(UINT64_MAX, 0.8, cmp, hash);
CMC_CREATE_TEST(new[capacity = UINT64_MAX], {
multimap *map = mm_new(UINT64_MAX, 0.99, cmp, hash);
cmc_assert_equals(ptr, NULL, map);
CMC_TEST_PASS_ELSE_FAIL(map == NULL);
});
CMC_CREATE_TEST(clear[count capacity], {
@@ -44,13 +41,11 @@ CMC_CREATE_UNIT(multimap_test, true, {
cmc_assert_equals(size_t, 50, mm_count(map));
mm_clear(map);
mm_clear(map, NULL);
cmc_assert_equals(size_t, 0, mm_count(map));
CMC_TEST_PASS_ELSE_FAIL(mm_count(map) == 0);
mm_free(map);
mm_free(map, NULL);
});
CMC_CREATE_TEST(insert[count], {
@@ -58,14 +53,12 @@ CMC_CREATE_UNIT(multimap_test, true, {
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 200; i++)
for (size_t i = 0; i < 100; i++)
cmc_assert(mm_insert(map, i % 20, i % 20));
cmc_assert_equals(size_t, 200, mm_count(map));
cmc_assert_equals(size_t, 100, mm_count(map));
CMC_TEST_PASS_ELSE_FAIL(mm_count(map) == 200);
mm_free(map);
mm_free(map, NULL);
});
CMC_CREATE_TEST(remove[count], {
@@ -83,12 +76,10 @@ CMC_CREATE_UNIT(multimap_test, true, {
cmc_assert_equals(size_t, 140, mm_count(map));
CMC_TEST_PASS_ELSE_FAIL(mm_count(map) == 140);
mm_free(map);
mm_free(map, NULL);
});
CMC_CREATE_TEST(remove[edge_case:count = 0], {
CMC_CREATE_TEST(remove[count = 0], {
multimap *map = mm_new(100, 0.8, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
@@ -97,12 +88,10 @@ CMC_CREATE_UNIT(multimap_test, true, {
cmc_assert(!mm_remove(map, 10, &r));
CMC_TEST_PASS_ELSE_FAIL(!mm_remove(map, 10, &r));
mm_free(map);
mm_free(map, NULL);
});
CMC_CREATE_TEST(remove[edge_case:count = 1], {
CMC_CREATE_TEST(remove[count = 1], {
multimap *map = mm_new(100, 0.8, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
@@ -112,47 +101,10 @@ CMC_CREATE_UNIT(multimap_test, true, {
cmc_assert(mm_insert(map, 10, 11));
cmc_assert(mm_remove(map, 10, &r));
CMC_TEST_PASS_ELSE_FAIL(mm_count(map) == 0);
mm_free(map);
mm_free(map, NULL);
});
CMC_CREATE_TEST(insert_if, {
multimap *map = mm_new(100, 0.8, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 1; i <= 100; i++)
cmc_assert(mm_insert_if(map, i % 20, i, i % 2 == 0) || i % 2 != 0);
cmc_assert_equals(size_t, 50, mm_count(map));
CMC_TEST_PASS_ELSE_FAIL(mm_count(map) == 50);
mm_free(map);
});
CMC_CREATE_TEST(remove_if, {
multimap *map = mm_new(100, 0.8, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 1; i <= 100; i++)
cmc_assert(mm_insert(map, i % 20, i));
size_t r;
for (size_t i = 1; i <= 100; i++)
cmc_assert(mm_remove_if(map, i % 20, &r, i % 2 == 0) || i % 2 != 0);
cmc_assert_equals(size_t, 50, mm_count(map));
CMC_TEST_PASS_ELSE_FAIL(mm_count(map) == 50);
mm_free(map);
});
CMC_CREATE_TEST(get[key_ordering], {
CMC_CREATE_TEST(get[key ordering], {
multimap *map = mm_new(100, 0.8, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
@@ -165,9 +117,22 @@ CMC_CREATE_UNIT(multimap_test, true, {
cmc_assert_equals(size_t, 100, mm_get(map, 10));
CMC_TEST_PASS_ELSE_FAIL(mm_get(map, 10) == 100);
mm_free(map);
mm_free(map, NULL);
});
CMC_CREATE_TEST(key_count, {
multimap *map = mm_new(50, 0.8, cmp, hash);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 1000; i++)
cmc_assert(mm_insert(map, i % 20, i % 20));
cmc_assert_equals(size_t, 1000, mm_count(map));
for (size_t i = 0; i < 20; i++)
cmc_assert_equals(size_t, 50, mm_key_count(map, i));
mm_free(map, NULL);
});
});
+88 -37
View File
@@ -1,37 +1,34 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/multiset.c"
#include "utl.c"
#include <utl/assert.h>
#include <utl/log.h>
#include <utl/test.h>
#include <ext/multiset.h>
CMC_GENERATE_MULTISET(ms, multiset, size_t)
CMC_CREATE_UNIT(multiset_test, true, {
CMC_CREATE_TEST(new, {
multiset *set = ms_new(943722, 0.6, cmp, hash);
bool passed = (set->capacity >= (943722 / 0.6)) && set->count == 0 && set->buffer;
cmc_assert_not_equals(ptr, NULL, set);
cmc_assert(ms_capacity(set) > (943722 / 0.6));
cmc_assert_not_equals(ptr, NULL, set->buffer);
cmc_assert_equals(size_t, 0, ms_count(set));
cmc_assert_greater_equals(size_t, ((size_t)(943722 / 0.6)), ms_capacity(set));
CMC_TEST_PASS_ELSE_FAIL(passed);
ms_free(set);
ms_free(set, NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
CMC_CREATE_TEST(new[capacity = 0], {
multiset *set = ms_new(0, 0.6, cmp, hash);
cmc_assert_equals(ptr, NULL, set);
CMC_TEST_PASS_ELSE_FAIL(set == NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINTMAX_MAX], {
multiset *set = ms_new(UINTMAX_MAX, 0.99, cmp, hash);
CMC_CREATE_TEST(new[capacity = UINT64_MAX], {
multiset *set = ms_new(UINT64_MAX, 0.99, cmp, hash);
cmc_assert_equals(ptr, NULL, set);
CMC_TEST_PASS_ELSE_FAIL(set == NULL);
});
CMC_CREATE_TEST(clear[count capacity], {
@@ -44,13 +41,11 @@ CMC_CREATE_UNIT(multiset_test, true, {
cmc_assert_equals(size_t, 50, ms_count(set));
ms_clear(set);
ms_clear(set, NULL);
cmc_assert_equals(size_t, 0, ms_count(set));
CMC_TEST_PASS_ELSE_FAIL(ms_count(set) == 0);
ms_free(set);
ms_free(set, NULL);
});
CMC_CREATE_TEST(insert[count cardinality multiplicity], {
@@ -68,35 +63,91 @@ CMC_CREATE_UNIT(multiset_test, true, {
cmc_assert_equals(size_t, 3, ms_count(set));
cmc_assert_equals(size_t, 6, ms_cardinality(set));
bool passed = ms_count(set) == 3 && ms_cardinality(set) == 6;
for (size_t i = 0; i <= 3; i++)
passed = passed && ms_multiplicity_of(set, i) == i;
cmc_assert_equals(size_t, i, ms_multiplicity_of(set, i));
CMC_TEST_PASS_ELSE_FAIL(passed);
ms_free(set);
ms_free(set, NULL);
});
CMC_CREATE_TEST(multiplicity, {
CMC_CREATE_TEST(remove[count cardinality multiplicity], {
multiset *set = ms_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
for (size_t i = 0; i < 100; i++)
cmc_assert(ms_insert(set, 1));
cmc_assert(ms_insert(set, 2));
cmc_assert(ms_insert(set, 2));
cmc_assert(ms_insert(set, 3));
cmc_assert(ms_insert(set, 3));
cmc_assert(ms_insert(set, 3));
cmc_assert_equals(size_t, 3, ms_count(set));
cmc_assert_equals(size_t, 6, ms_cardinality(set));
for (size_t i = 0; i <= 3; i++)
cmc_assert_equals(size_t, i, ms_multiplicity_of(set, i));
cmc_assert(ms_remove(set, 1));
cmc_assert(ms_remove(set, 2));
cmc_assert(ms_remove(set, 3));
cmc_assert_equals(size_t, 2, ms_count(set));
cmc_assert_equals(size_t, 3, ms_cardinality(set));
cmc_assert_equals(size_t, 0, ms_multiplicity_of(set, 0));
cmc_assert_equals(size_t, 0, ms_multiplicity_of(set, 1));
cmc_assert_equals(size_t, 1, ms_multiplicity_of(set, 2));
cmc_assert_equals(size_t, 2, ms_multiplicity_of(set, 3));
ms_free(set, NULL);
});
CMC_CREATE_TEST(remove_all[count cardinality multiplicity], {
multiset *set = ms_new(100, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
cmc_assert(ms_insert(set, 1));
cmc_assert(ms_insert(set, 2));
cmc_assert(ms_insert(set, 2));
cmc_assert(ms_insert(set, 3));
cmc_assert(ms_insert(set, 3));
cmc_assert(ms_insert(set, 3));
cmc_assert_equals(size_t, 3, ms_count(set));
cmc_assert_equals(size_t, 6, ms_cardinality(set));
for (size_t i = 0; i <= 3; i++)
cmc_assert_equals(size_t, i, ms_multiplicity_of(set, i));
cmc_assert(ms_remove_all(set, 1));
cmc_assert(ms_remove_all(set, 3));
cmc_assert_equals(size_t, 1, ms_count(set));
cmc_assert_equals(size_t, 2, ms_cardinality(set));
cmc_assert_equals(size_t, 0, ms_multiplicity_of(set, 0));
cmc_assert_equals(size_t, 0, ms_multiplicity_of(set, 1));
cmc_assert_equals(size_t, 2, ms_multiplicity_of(set, 2));
cmc_assert_equals(size_t, 0, ms_multiplicity_of(set, 3));
ms_free(set, NULL);
});
CMC_CREATE_TEST(multiplicity, {
multiset *set = ms_new(50, 0.6, cmp, hash);
cmc_assert_not_equals(ptr, NULL, set);
for (size_t i = 0; i < 1000; i++)
cmc_assert(ms_insert(set, i % 20));
cmc_assert_equals(size_t, 20, ms_count(set));
cmc_assert_equals(size_t, 100, ms_cardinality(set));
bool passed = ms_count(set) == 20 && ms_cardinality(set) == 100;
cmc_assert_equals(size_t, 1000, ms_cardinality(set));
for (size_t i = 0; i < 20; i++)
passed = passed && ms_multiplicity_of(set, i) == 5;
cmc_assert_equals(size_t, 50, ms_multiplicity_of(set, i));
CMC_TEST_PASS_ELSE_FAIL(passed);
ms_free(set);
ms_free(set, NULL);
});
});
+363 -26
View File
@@ -1,38 +1,35 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/queue.c"
#include "utl.c"
#include <utl/assert.h>
#include <utl/log.h>
#include <utl/test.h>
#include <cmc/queue.h>
CMC_GENERATE_QUEUE(q, queue, size_t)
CMC_CREATE_UNIT(queue_test, true, {
CMC_CREATE_TEST(new, {
queue *q = q_new(1000000);
cmc_assert_not_equals(ptr, NULL, q);
bool passed = q->capacity == 1000000 && q->count == 0 && q->buffer;
cmc_assert_equals(size_t, 1000000, q->capacity);
cmc_assert_not_equals(ptr, NULL, q->buffer);
cmc_assert_equals(size_t, 1000000, q_capacity(q));
cmc_assert_equals(size_t, 0, q_count(q));
cmc_assert_not_equals(ptr, NULL, q->buffer);
CMC_TEST_PASS_ELSE_FAIL(passed);
q_free(q);
q_free(q, NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
CMC_CREATE_TEST(new[capacity = 0], {
queue *q = q_new(0);
cmc_assert_equals(ptr, NULL, q);
CMC_TEST_PASS_ELSE_FAIL(q == NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
CMC_CREATE_TEST(new[capacity = UINT64_MAX], {
queue *q = q_new(UINT64_MAX);
cmc_assert_equals(ptr, NULL, q);
CMC_TEST_PASS_ELSE_FAIL(q == NULL);
});
CMC_CREATE_TEST(clear[count capacity], {
@@ -41,33 +38,373 @@ CMC_CREATE_UNIT(queue_test, true, {
cmc_assert_not_equals(ptr, NULL, q);
for (size_t i = 0; i < 50; i++)
q_enqueue(q, i);
cmc_assert(q_enqueue(q, i));
cmc_assert_equals(size_t, 50, q_count(q));
q_clear(q);
q_clear(q, NULL);
cmc_assert_equals(size_t, 0, q_count(q));
cmc_assert_equals(size_t, 100, q_capacity(q));
CMC_TEST_PASS_ELSE_FAIL(q_count(q) == 0 && q_capacity(q) == 100);
q_free(q);
q_free(q, NULL);
});
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
CMC_CREATE_TEST(buffer_growth[capacity = 1], {
queue *q = q_new(1);
cmc_assert_not_equals(ptr, NULL, q);
for (size_t i = 0; i < 50; i++)
q_enqueue(q, i);
cmc_assert(q_enqueue(q, i));
cmc_assert_equals(size_t, 50, q_count(q));
CMC_TEST_PASS_ELSE_FAIL(q_count(q) == 50);
q_free(q);
q_free(q, NULL);
});
CMC_CREATE_TEST(buffer_growth[item preservation], {
queue *q = q_new(100);
cmc_assert_not_equals(ptr, NULL, q);
for (size_t i = 1; i <= 1200; i++)
{
q_enqueue(q, i);
}
size_t sum = 0;
for (size_t i = q->front, j = 0; j < q->count; i = (i + 1) % q->capacity, j++)
sum += q->buffer[i];
cmc_assert_equals(size_t, 1200, q_count(q));
cmc_assert_equals(size_t, 720600, sum);
q_free(q, NULL);
});
CMC_CREATE_TEST(enqueue[count capacity], {
queue *q = q_new(100);
cmc_assert_not_equals(ptr, NULL, q);
for (size_t i = 0; i < 150; i++)
cmc_assert(q_enqueue(q, i));
cmc_assert_equals(size_t, 150, q_count(q));
cmc_assert_greater(size_t, 100, q_capacity(q));
q_free(q, NULL);
});
CMC_CREATE_TEST(enqueue[item preservation], {
queue *q = q_new(100);
cmc_assert_not_equals(ptr, NULL, q);
for (size_t i = 1; i <= 100; i++)
cmc_assert(q_enqueue(q, i));
size_t sum = 0;
for (size_t i = q->front, j = 0; j < q->count; i = (i + 1) % q->capacity, j++)
{
sum += q->buffer[i];
}
cmc_assert_equals(size_t, 5050, sum);
q_free(q, NULL);
});
CMC_CREATE_TEST(dequeue[count capacity], {
queue *q = q_new(100);
cmc_assert_not_equals(ptr, NULL, q);
cmc_assert(q_enqueue(q, 10));
cmc_assert(q_dequeue(q));
cmc_assert_equals(size_t, 0, q_count(q));
cmc_assert(q_enqueue(q, 10));
cmc_assert(q_dequeue(q));
cmc_assert_equals(size_t, 0, q_count(q));
q_free(q, NULL);
});
CMC_CREATE_TEST(dequeue[item preservation], {
queue *q = q_new(100);
cmc_assert_not_equals(ptr, NULL, q);
for (size_t i = 200; i > 0; i--)
cmc_assert(q_enqueue(q, i));
for (size_t i = 0; i < 100; i++)
cmc_assert(q_dequeue(q));
size_t sum = 0;
for (size_t i = q->front, j = 0; j < q->count; i = (i + 1) % q->capacity, j++)
{
sum += q->buffer[i];
}
cmc_assert_equals(size_t, 5050, sum);
q_free(q, NULL);
});
CMC_CREATE_TEST(peek[count = 0], {
queue *q = q_new(100);
cmc_assert_not_equals(ptr, NULL, q);
size_t r = q_peek(q);
cmc_assert_equals(size_t, (size_t){0}, r);
q_free(q, NULL);
});
CMC_CREATE_TEST(peek[sum], {
queue *q = q_new(100);
cmc_assert_not_equals(ptr, NULL, q);
size_t sum = 0;
for (size_t i = 0; i <= 100; i++)
cmc_assert(q_enqueue(q, i));
while (!q_empty(q))
{
size_t r = q_peek(q);
sum += r;
cmc_assert(q_dequeue(q));
}
cmc_assert_equals(size_t, 5050, sum);
q_free(q, NULL);
});
CMC_CREATE_TEST(contains, {
queue *q = q_new(100);
cmc_assert_not_equals(ptr, NULL, q);
for (size_t i = 1; i <= 20; i++)
cmc_assert(q_enqueue(q, i));
for (size_t i = 1; i <= 20; i++)
cmc_assert(q_contains(q, i, cmp));
q_clear(q, NULL);
for (size_t i = 1; i <= 20; i++)
cmc_assert(!q_contains(q, i, cmp));
q_free(q, NULL);
});
CMC_CREATE_TEST(contains[count = 0], {
queue *q = q_new(100);
cmc_assert_not_equals(ptr, NULL, q);
cmc_assert(!q_contains(q, 10, cmp));
q_free(q, NULL);
});
CMC_CREATE_TEST(contains[count = 1], {
queue *q = q_new(100);
cmc_assert_not_equals(ptr, NULL, q);
cmc_assert(!q_contains(q, 10, cmp));
cmc_assert(q_enqueue(q, 100));
cmc_assert(q_contains(q, 100, cmp));
cmc_assert(!q_contains(q, 101, cmp));
q_free(q, NULL);
});
CMC_CREATE_TEST(empty, {
queue *q = q_new(100);
cmc_assert_not_equals(ptr, NULL, q);
cmc_assert(q_empty(q));
cmc_assert(q_enqueue(q, 1));
cmc_assert(!q_empty(q));
q_free(q, NULL);
});
CMC_CREATE_TEST(full, {
queue *q = q_new(100);
cmc_assert_not_equals(ptr, NULL, q);
cmc_assert(!q_full(q));
for (size_t i = 0; i != q_capacity(q); i++)
cmc_assert(q_enqueue(q, i));
cmc_assert(q_full(q));
q_free(q, NULL);
});
CMC_CREATE_TEST(count, {
queue *q = q_new(100);
cmc_assert_not_equals(ptr, NULL, q);
cmc_assert_equals(size_t, 0, q_count(q));
for (size_t i = 0; i < 100; i++)
cmc_assert(q_enqueue(q, i));
cmc_assert_equals(size_t, 100, q_count(q));
q_free(q, NULL);
});
CMC_CREATE_TEST(capacity, {
queue *q = q_new(100);
cmc_assert_not_equals(ptr, NULL, q);
cmc_assert_equals(size_t, 100, q_capacity(q));
q_free(q, NULL);
});
CMC_CREATE_TEST(resize, {
queue *q = q_new(100);
cmc_assert_not_equals(ptr, NULL, q);
for (size_t i = 0; i < 150; i++)
cmc_assert(q_enqueue(q, i));
cmc_assert_equals(size_t, 150, q_count(q));
cmc_assert(q_resize(q, q_count(q)));
cmc_assert_equals(size_t, 150, q_capacity(q));
q_free(q, NULL);
});
CMC_CREATE_TEST(resize[item preservation], {
queue *q = q_new(100);
cmc_assert_not_equals(ptr, NULL, q);
for (size_t i = 1; i <= 150; i++)
cmc_assert(q_enqueue(q, i));
cmc_assert(q_resize(q, q_count(q)));
size_t sum = 0;
for (size_t i = q->front, j = 0; j < q->count; i = (i + 1) % q->capacity, j++)
{
sum += q->buffer[i];
}
cmc_assert_equals(size_t, 11325, sum);
q_free(q, NULL);
});
CMC_CREATE_TEST(copy_of, {
queue *d1 = q_new(100);
cmc_assert_not_equals(ptr, NULL, d1);
for (size_t i = 1; i <= 150; i++)
cmc_assert(q_enqueue(d1, i));
queue *d2 = q_copy_of(d1, NULL);
cmc_assert_not_equals(ptr, NULL, d2);
cmc_assert_equals(size_t, q_count(d1), q_count(d2));
for (size_t i1 = d1->front, i2 = d2->front, j = 0; j < d1->count; j++)
{
cmc_assert_equals(size_t, d1->buffer[i1], d2->buffer[i2]);
i1 = (i1 + 1) % d1->capacity;
i2 = (i2 + 1) % d2->capacity;
}
q_free(d1, NULL);
q_free(d2, NULL);
});
CMC_CREATE_TEST(equals, {
queue *d1 = q_new(100);
queue *d2 = q_new(100);
cmc_assert_not_equals(ptr, NULL, d1);
cmc_assert_not_equals(ptr, NULL, d2);
for (size_t i = 1; i <= 150; i++)
{
cmc_assert(q_enqueue(d1, i));
cmc_assert(q_enqueue(d2, i));
}
cmc_assert(q_equals(d1, d2, cmp));
q_free(d1, NULL);
q_free(d2, NULL);
});
CMC_CREATE_TEST(equals[from copy], {
queue *d1 = q_new(100);
cmc_assert_not_equals(ptr, NULL, d1);
for (size_t i = 1; i <= 150; i++)
{
cmc_assert(q_enqueue(d1, i));
}
queue *d2 = q_copy_of(d1, NULL);
cmc_assert_not_equals(ptr, NULL, d2);
cmc_assert(q_equals(d1, d2, cmp));
q_free(d1, NULL);
q_free(d2, NULL);
});
CMC_CREATE_TEST(equals[count = 0], {
queue *d1 = q_new(100);
cmc_assert_not_equals(ptr, NULL, d1);
queue *d2 = q_copy_of(d1, NULL);
cmc_assert_not_equals(ptr, NULL, d2);
cmc_assert(q_equals(d1, d2, cmp));
q_free(d1, NULL);
q_free(d2, NULL);
});
});
+140
View File
@@ -0,0 +1,140 @@
#include "utl.c"
#include <utl/assert.h>
#include <utl/log.h>
#include <utl/test.h>
#include <ext/sortedlist.h>
CMC_GENERATE_SORTEDLIST(sl, sortedlist, size_t)
CMC_CREATE_UNIT(sortedlist_test, true, {
CMC_CREATE_TEST(new, {
sortedlist *sl = sl_new(1000000, cmp);
cmc_assert_not_equals(ptr, NULL, sl);
cmc_assert_not_equals(ptr, NULL, sl->buffer);
cmc_assert_equals(size_t, 1000000, sl_capacity(sl));
cmc_assert_equals(size_t, 0, sl_count(sl));
cmc_assert_not_equals(ptr, NULL, sl->buffer);
sl_free(sl, NULL);
});
CMC_CREATE_TEST(new[capacity = 0], {
sortedlist *sl = sl_new(0, cmp);
cmc_assert_equals(ptr, NULL, sl);
});
CMC_CREATE_TEST(new[capacity = UINT64_MAX], {
sortedlist *sl = sl_new(UINT64_MAX, cmp);
cmc_assert_equals(ptr, NULL, sl);
});
CMC_CREATE_TEST(clear[count capacity], {
sortedlist *sl = sl_new(100, cmp);
cmc_assert_not_equals(ptr, NULL, sl);
for (size_t i = 0; i < 50; i++)
cmc_assert(sl_insert(sl, i));
cmc_assert_equals(size_t, 50, sl_count(sl));
sl_clear(sl, NULL);
cmc_assert_equals(size_t, 0, sl_count(sl));
cmc_assert_equals(size_t, 100, sl_capacity(sl));
sl_free(sl, NULL);
});
CMC_CREATE_TEST(buffer_growth[capacity = 1], {
sortedlist *sl = sl_new(1, cmp);
cmc_assert_not_equals(ptr, NULL, sl);
for (size_t i = 0; i < 50; i++)
cmc_assert(sl_insert(sl, i));
sl_sort(sl);
cmc_assert_equals(size_t, 50, sl_count(sl));
cmc_assert_array_sorted_any(size_t, sl->buffer, cmp, 0, sl->count - 1);
sl_free(sl, NULL);
});
CMC_CREATE_TEST(insert, {
sortedlist *sl = sl_new(100, cmp);
cmc_assert_not_equals(ptr, NULL, sl);
cmc_assert(sl_insert(sl, 1));
sl_free(sl, NULL);
});
CMC_CREATE_TEST(remove, {
sortedlist *sl = sl_new(100, cmp);
cmc_assert_not_equals(ptr, NULL, sl);
cmc_assert(sl_insert(sl, 32));
cmc_assert(sl_remove(sl, 0));
sl_free(sl, NULL);
});
CMC_CREATE_TEST(remove[count = 0], {
sortedlist *sl = sl_new(100, cmp);
cmc_assert_not_equals(ptr, NULL, sl);
cmc_assert(!sl_remove(sl, 0));
sl_free(sl, NULL);
});
CMC_CREATE_TEST(remove[out of range], {
sortedlist *sl = sl_new(100, cmp);
cmc_assert_not_equals(ptr, NULL, sl);
cmc_assert(sl_insert(sl, 32));
cmc_assert(!sl_remove(sl, 2));
sl_free(sl, NULL);
});
CMC_CREATE_TEST(indexof, {
sortedlist *sl = sl_new(1, cmp);
cmc_assert_not_equals(ptr, NULL, sl);
for (size_t i = 0; i < 20; i++)
cmc_assert(sl_insert(sl, i % 10));
/* 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9 */
cmc_assert_equals(size_t, 4, sl_indexof(sl, 2, true));
cmc_assert_equals(size_t, 5, sl_indexof(sl, 2, false));
cmc_assert_equals(size_t, 0, sl_indexof(sl, 0, true));
cmc_assert_equals(size_t, 1, sl_indexof(sl, 0, false));
cmc_assert(sl_remove(sl, 0));
cmc_assert_equals(size_t, 0, sl_indexof(sl, 0, true));
cmc_assert_equals(size_t, 0, sl_indexof(sl, 0, false));
cmc_assert(sl_remove(sl, 0));
cmc_assert_equals(size_t, sl_count(sl), sl_indexof(sl, 0, true));
cmc_assert_equals(size_t, sl_count(sl), sl_indexof(sl, 0, false));
sl_free(sl, NULL);
});
});
+71 -212
View File
@@ -1,40 +1,35 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/stack.c"
#include "utl.c"
#include <utl/assert.h>
#include <utl/log.h>
#include <utl/test.h>
#include <cmc/stack.h>
CMC_GENERATE_STACK(s, stack, size_t)
CMC_CREATE_UNIT(stack_test, true, {
CMC_CREATE_TEST(new, {
stack *s = s_new(1000000);
cmc_assert_not_equals(ptr, NULL, s);
bool passed = s->capacity == 1000000 && s->count == 0 && s->buffer;
cmc_assert_equals(size_t, 1000000, s->capacity);
cmc_assert_not_equals(ptr, NULL, s->buffer);
cmc_assert_equals(size_t, 1000000, s_capacity(s));
cmc_assert_equals(size_t, 0, s_count(s));
cmc_assert_not_equals(ptr, NULL, s->buffer);
CMC_TEST_PASS_ELSE_FAIL(passed);
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
CMC_CREATE_TEST(new[capacity = 0], {
stack *s = s_new(0);
cmc_assert_equals(ptr, NULL, s);
CMC_TEST_PASS_ELSE_FAIL(s == NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
CMC_CREATE_TEST(new[capacity = UINT64_MAX], {
stack *s = s_new(UINT64_MAX);
cmc_assert_equals(ptr, NULL, s);
CMC_TEST_PASS_ELSE_FAIL(s == NULL);
});
CMC_CREATE_TEST(clear[count capacity], {
@@ -47,17 +42,15 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert_equals(size_t, 50, s_count(s));
s_clear(s);
s_clear(s, NULL);
cmc_assert_equals(size_t, 0, s_count(s));
cmc_assert_equals(size_t, 100, s_capacity(s));
CMC_TEST_PASS_ELSE_FAIL(s_count(s) == 0 && s_capacity(s) == 100);
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
CMC_CREATE_TEST(buffer_growth[capacity = 1], {
stack *s = s_new(1);
cmc_assert_not_equals(ptr, NULL, s);
@@ -68,9 +61,7 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert_equals(size_t, 50, s_count(s));
cmc_assert_lesser_equals(size_t, s_capacity(s), s_count(s));
CMC_TEST_PASS_ELSE_FAIL(s_count(s) == 50 && s_count(s) <= s_capacity(s));
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(push[count], {
@@ -83,9 +74,7 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert_equals(size_t, 250, s_count(s));
CMC_TEST_PASS_ELSE_FAIL(s_count(s) == 250);
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(push[capacity], {
@@ -98,12 +87,10 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert_lesser_equals(size_t, s_capacity(s), s_count(s));
CMC_TEST_PASS_ELSE_FAIL(s_count(s) <= s_capacity(s));
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(push[item_preservation], {
CMC_CREATE_TEST(push[item preservation], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
@@ -111,18 +98,10 @@ CMC_CREATE_UNIT(stack_test, true, {
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
bool passed = true;
for (size_t i = 0; i < s_count(s); i++)
{
passed = s->buffer[i] == i;
cmc_assert_equals(size_t, i, s->buffer[i]);
}
CMC_TEST_PASS_ELSE_FAIL(passed);
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(pop[count], {
@@ -137,9 +116,7 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert_equals(size_t, 249, s_count(s));
CMC_TEST_PASS_ELSE_FAIL(s_count(s) == 249);
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(pop[capacity], {
@@ -154,12 +131,10 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert_lesser_equals(size_t, s_capacity(s), s_count(s));
CMC_TEST_PASS_ELSE_FAIL(s_count(s) <= s_capacity(s));
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(pop[item_preservation], {
CMC_CREATE_TEST(pop[item preservation], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
@@ -170,77 +145,20 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert(s_pop(s));
cmc_assert(s_pop(s));
bool passed = true;
for (size_t i = 0; i < s_count(s); i++)
{
passed = s->buffer[i] == i;
cmc_assert_equals(size_t, i, s->buffer[i]);
}
CMC_TEST_PASS_ELSE_FAIL(passed);
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(pop[edge_case:count = 0], {
CMC_CREATE_TEST(pop[count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert_equals(bool, false, s_pop(s));
CMC_TEST_PASS_ELSE_FAIL(!s_pop(s));
s_free(s);
});
CMC_CREATE_TEST(push_if, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
s_push_if(s, i, i % 2 == 0);
bool passed = true;
for (size_t i = 0; i < s_count(s); i++)
{
passed = passed && s->buffer[i] % 2 == 0;
cmc_assert(s->buffer[i] % 2 == 0);
}
CMC_TEST_PASS_ELSE_FAIL(passed);
s_free(s);
});
CMC_CREATE_TEST(pop_if, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
{
s_push(s, i);
s_pop_if(s, s_top(s) % 2 == 0);
}
bool passed = true;
for (size_t i = 0; i < s_count(s); i++)
{
passed = passed && !(s->buffer[i] % 2 == 0);
cmc_assert(!(s->buffer[i] % 2 == 0));
}
CMC_TEST_PASS_ELSE_FAIL(passed);
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(top, {
@@ -256,12 +174,10 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert_equals(size_t, 247, s_top(s));
CMC_TEST_PASS_ELSE_FAIL(247 == s_top(s));
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(top[edge_case:count = 0], {
CMC_CREATE_TEST(top[count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
@@ -270,14 +186,12 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert(s_pop(s));
cmc_assert_equals(size_t, s_impl_default_value(), s_top(s));
cmc_assert_equals(size_t, (size_t){0}, s_top(s));
CMC_TEST_PASS_ELSE_FAIL(s_impl_default_value() == s_top(s));
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(top[edge_case:count = 1], {
CMC_CREATE_TEST(top[count = 1], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
@@ -286,9 +200,7 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert_equals(size_t, 1, s_count(s));
cmc_assert_equals(size_t, 10, s_top(s));
CMC_TEST_PASS_ELSE_FAIL(10 == s_top(s));
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(contains, {
@@ -299,26 +211,20 @@ CMC_CREATE_UNIT(stack_test, true, {
for (size_t i = 0; i < 150; i++)
cmc_assert(s_push(s, i));
bool passed = true;
for (size_t i = 0; i < 150; i++)
passed = passed && s_contains(s, i, cmp);
cmc_assert(s_contains(s, i, cmp));
CMC_TEST_PASS_ELSE_FAIL(passed);
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(contains[edge_case:count = 0], {
CMC_CREATE_TEST(contains[count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert_equals(bool, false, s_contains(s, 10, cmp));
CMC_TEST_PASS_ELSE_FAIL(!s_contains(s, 10, cmp));
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(empty, {
@@ -328,9 +234,7 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert(s_empty(s));
CMC_TEST_PASS_ELSE_FAIL(s_empty(s));
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(empty[after_io], {
@@ -342,9 +246,7 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert(s_pop(s));
cmc_assert(s_empty(s));
CMC_TEST_PASS_ELSE_FAIL(s_empty(s));
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(full, {
@@ -357,12 +259,10 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert(s_full(s));
CMC_TEST_PASS_ELSE_FAIL(s_full(s));
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(full[edge_case:capacity = 1], {
CMC_CREATE_TEST(full[capacity = 1], {
stack *s = s_new(1);
cmc_assert_not_equals(ptr, NULL, s);
@@ -371,9 +271,7 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert(s_full(s));
CMC_TEST_PASS_ELSE_FAIL(s_full(s));
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(iter_alloc, {
@@ -385,13 +283,11 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert_not_equals(ptr, NULL, iter);
CMC_TEST_PASS_ELSE_FAIL(s && iter);
s_iter_free(iter);
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(iter_init[edge_case:count = 0], {
CMC_CREATE_TEST(iter_init[count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
@@ -405,14 +301,10 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert(iter.start);
cmc_assert(iter.end);
bool passed = iter.target == s && iter.cursor == 0 && iter.start && iter.end;
CMC_TEST_PASS_ELSE_FAIL(passed);
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(iter_start[edge_case:count = 0], {
CMC_CREATE_TEST(iter_start[count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
@@ -421,12 +313,12 @@ CMC_CREATE_UNIT(stack_test, true, {
s_iter_init(&iter, s);
CMC_TEST_PASS_ELSE_FAIL(s_iter_start(&iter));
cmc_assert(s_iter_start(&iter));
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(iter_end[edge_case:count = 0], {
CMC_CREATE_TEST(iter_end[count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
@@ -435,9 +327,9 @@ CMC_CREATE_UNIT(stack_test, true, {
s_iter_init(&iter, s);
CMC_TEST_PASS_ELSE_FAIL(s_iter_end(&iter));
cmc_assert(s_iter_end(&iter));
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(iteration, {
@@ -464,9 +356,7 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert_equals(size_t, 40200, total);
CMC_TEST_PASS_ELSE_FAIL(total == 40200);
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(iteration[while loop], {
@@ -496,12 +386,10 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert_equals(size_t, 40200, total);
CMC_TEST_PASS_ELSE_FAIL(total == 40200);
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(iteration[edge_case:count = 1], {
CMC_CREATE_TEST(iteration[count = 1], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
@@ -521,12 +409,10 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert_equals(size_t, 20, total);
CMC_TEST_PASS_ELSE_FAIL(total == 20);
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(iteration[edge_case:count = capacity], {
CMC_CREATE_TEST(iteration[count = capacity], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
@@ -552,9 +438,7 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert_equals(size_t, 2000, total);
CMC_TEST_PASS_ELSE_FAIL(total == 2000);
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(iteration[to_start = it_start and to_end = it_end], {
@@ -565,7 +449,6 @@ CMC_CREATE_UNIT(stack_test, true, {
for (size_t i = 0; i < 50; i++)
cmc_assert(s_push(s, i));
bool passed = true;
stack_iter it1;
stack_iter it2;
@@ -581,7 +464,6 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert_equals(size_t, it1.cursor, it2.cursor);
cmc_assert_equals(bool, it1.start, it2.start);
cmc_assert_equals(bool, it1.end, it2.end);
passed = passed && it1.target == it2.target && it1.cursor == it2.cursor && it1.start == it2.start && it1.end == it2.end;
it1 = s->it_end(s);
s_iter_to_end(&it2);
@@ -590,14 +472,11 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert_equals(size_t, it1.cursor, it2.cursor);
cmc_assert_equals(bool, it1.start, it2.start);
cmc_assert_equals(bool, it1.end, it2.end);
passed = passed && it1.target == it2.target && it1.cursor == it2.cursor && it1.start == it2.start && it1.end == it2.end;
CMC_TEST_PASS_ELSE_FAIL(passed);
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(iteration[boundaries:count = 0], {
CMC_CREATE_TEST(iteration[boundaries count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
@@ -608,19 +487,15 @@ CMC_CREATE_UNIT(stack_test, true, {
s_iter_to_end(&iter);
cmc_assert_equals(bool, false, s_iter_next(&iter));
bool passed = !s_iter_next(&iter);
s_iter_to_start(&iter);
cmc_assert_equals(bool, false, s_iter_prev(&iter));
passed = !s_iter_prev(&iter);
CMC_TEST_PASS_ELSE_FAIL(passed);
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(iteration[boundaries:count > 0], {
CMC_CREATE_TEST(iteration[boundaries count > 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
@@ -634,19 +509,15 @@ CMC_CREATE_UNIT(stack_test, true, {
s_iter_to_end(&iter);
cmc_assert_equals(bool, false, s_iter_next(&iter));
bool passed = !s_iter_next(&iter);
s_iter_to_start(&iter);
cmc_assert_equals(bool, false, s_iter_prev(&iter));
passed = !s_iter_prev(&iter);
CMC_TEST_PASS_ELSE_FAIL(passed);
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(iter_value[edge_case:count = 0], {
CMC_CREATE_TEST(iter_value[count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
@@ -655,14 +526,12 @@ CMC_CREATE_UNIT(stack_test, true, {
s_iter_init(&iter, s);
cmc_assert_equals(size_t, s_impl_default_value(), s_iter_value(&iter));
cmc_assert_equals(size_t, (size_t){0}, s_iter_value(&iter));
CMC_TEST_PASS_ELSE_FAIL(s_impl_default_value() == s_iter_value(&iter));
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(iter_rvalue[edge_case:count = 0], {
CMC_CREATE_TEST(iter_rvalue[count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
@@ -673,9 +542,7 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert_equals(ptr, NULL, s_iter_rvalue(&iter));
CMC_TEST_PASS_ELSE_FAIL(NULL == s_iter_rvalue(&iter));
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(index, {
@@ -688,18 +555,15 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert_equals(size_t, 10, s_count(s));
bool passed = true;
size_t total = 0;
for (stack_iter it = s->it_start(s); false; )
for (stack_iter it = s->it_start(s); false;)
{
passed = passed && s_iter_index(&it) == 0;
cmc_assert_equals(size_t, 0, s_iter_index(&it));
}
for (stack_iter it = s->it_start(s); false; )
for (stack_iter it = s->it_start(s); false;)
{
passed = passed && s_iter_index(&it) == s_count(s) - 1;
cmc_assert_equals(size_t, s_count(s) - 1, s_iter_index(&it));
}
@@ -717,12 +581,10 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert_equals(size_t, 90, total);
CMC_TEST_PASS_ELSE_FAIL(passed && total == 90);
s_free(s);
s_free(s, NULL);
});
CMC_CREATE_TEST(index[edge_case:count = 0], {
CMC_CREATE_TEST(index[count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
@@ -732,9 +594,6 @@ CMC_CREATE_UNIT(stack_test, true, {
cmc_assert_equals(size_t, 0, s_iter_index(&iter));
CMC_TEST_PASS_ELSE_FAIL(0 == s_iter_index(&iter));
s_free(s);
s_free(s, NULL);
});
});
+10 -12
View File
@@ -1,8 +1,11 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/treemap.c"
#include "utl.c"
#include <utl/assert.h>
#include <utl/log.h>
#include <utl/test.h>
#include <cmc/treemap.h>
CMC_GENERATE_TREEMAP(tm, treemap, size_t, size_t)
CMC_CREATE_UNIT(treemap_test, true, {
CMC_CREATE_TEST(new, {
@@ -10,9 +13,7 @@ CMC_CREATE_UNIT(treemap_test, true, {
cmc_assert_not_equals(ptr, NULL, map);
CMC_TEST_PASS_ELSE_FAIL(map);
tm_free(map);
tm_free(map, NULL);
});
CMC_CREATE_TEST(clear[count], {
@@ -25,14 +26,11 @@ CMC_CREATE_UNIT(treemap_test, true, {
cmc_assert_equals(size_t, 50, tm_count(map));
tm_clear(map);
tm_clear(map, NULL);
cmc_assert_equals(size_t, 0, tm_count(map));
cmc_assert_equals(ptr, NULL, map->root);
CMC_TEST_PASS_ELSE_FAIL(tm_count(map) == 0);
tm_free(map);
tm_free(map, NULL);
});
});
+10 -13
View File
@@ -1,8 +1,11 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/treeset.c"
#include "utl.c"
#include <utl/assert.h>
#include <utl/log.h>
#include <utl/test.h>
#include <cmc/treeset.h>
CMC_GENERATE_TREESET(ts, treeset, size_t)
CMC_CREATE_UNIT(treeset_test, true, {
CMC_CREATE_TEST(new, {
@@ -10,9 +13,7 @@ CMC_CREATE_UNIT(treeset_test, true, {
cmc_assert_not_equals(ptr, NULL, set);
CMC_TEST_PASS_ELSE_FAIL(set);
ts_free(set);
ts_free(set, NULL);
});
CMC_CREATE_TEST(clear[count], {
@@ -25,15 +26,11 @@ CMC_CREATE_UNIT(treeset_test, true, {
cmc_assert_equals(size_t, 50, ts_count(set));
ts_clear(set);
ts_clear(set, NULL);
cmc_assert_equals(size_t, 0, ts_count(set));
cmc_assert_equals(ptr, NULL, set->root);
CMC_TEST_PASS_ELSE_FAIL(ts_count(set) == 0);
ts_free(set);
ts_free(set, NULL);
});
});
+21
View File
@@ -3,6 +3,7 @@
#define CMC_UNIT_TEST_UTL__
#include <stdlib.h>
#include <cmc/hashmap.h>
int cmp(size_t a, size_t b)
{
@@ -20,4 +21,24 @@ size_t hash(size_t a)
return a;
}
size_t numhash(size_t a)
{
return a;
}
size_t hashcapminus1(size_t a)
{
return cmc_hashtable_primes[0] - 1;
}
size_t hashcapminus4(size_t a)
{
return cmc_hashtable_primes[0] - 1;
}
size_t hash0(size_t a)
{
return 0;
}
#endif /* CMC_UNIT_TEST_UTL__ */
+21 -13
View File
@@ -28,23 +28,31 @@ int main(void)
heap *h = h_new(1000, cmc_max_heap, intcmp);
tset *ts = ts_new(intcmp);
tmap *tm = tm_new(intcmp);
hset *hs = hs_new(1000, 0.9, intcmp, inthash);
hmap *hm = hm_new(1000, 0.9, intcmp, inthash);
hset *hs = hs_new(1000, 0.6, intcmp, inthash);
hmap *hm = hm_new(1000, 0.6, intcmp, inthash);
iheap *ih = ih_new(1000, intcmp);
mmap *mm = mm_new(1000, 0.8, intcmp, inthash);
mset *ms = ms_new(1000, 0.6, intcmp, inthash);
printf("+--------------------------------------------------+\n");
printf("| Separate Header and Source is Working |\n");
printf("+--------------------------------------------------+\n");
l_free(l);
ll_free(ll);
s_free(s);
q_free(q);
d_free(d);
h_free(h);
ts_free(ts);
tm_free(tm);
hs_free(hs);
hm_free(hm);
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;
}
}
+14 -10
View File
@@ -1,12 +1,16 @@
#include "sep.h"
COLLECTION_GENERATE_SOURCE(LIST, l, list, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_SOURCE(STACK, s, stack, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_SOURCE(QUEUE, q, queue, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_SOURCE(DEQUE, d, deque, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_SOURCE(LINKEDLIST, ll, linked, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_SOURCE(HEAP, h, heap, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_SOURCE(TREESET, ts, tset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_SOURCE(TREEMAP, tm, tmap, /* FMOD */, int, int)
COLLECTION_GENERATE_SOURCE(HASHSET, hs, hset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_SOURCE(HASHMAP, hm, hmap, /* FMOD */, int, int)
CMC_COLLECTION_GENERATE_SOURCE(LIST, l, list, /* K */, int)
CMC_COLLECTION_GENERATE_SOURCE(STACK, s, stack, /* K */, int)
CMC_COLLECTION_GENERATE_SOURCE(QUEUE, q, queue, /* K */, int)
CMC_COLLECTION_GENERATE_SOURCE(DEQUE, d, deque, /* K */, int)
CMC_COLLECTION_GENERATE_SOURCE(LINKEDLIST, ll, linked, /* K */, int)
CMC_COLLECTION_GENERATE_SOURCE(HEAP, h, heap, /* K */, int)
CMC_COLLECTION_GENERATE_SOURCE(TREESET, ts, tset, /* K */, int)
CMC_COLLECTION_GENERATE_SOURCE(TREEMAP, tm, tmap, int, int)
CMC_COLLECTION_GENERATE_SOURCE(HASHSET, hs, hset, /* K */, int)
CMC_COLLECTION_GENERATE_SOURCE(HASHMAP, hm, hmap, int, int)
CMC_COLLECTION_GENERATE_SOURCE(INTERVALHEAP, ih, iheap, , int)
CMC_COLLECTION_GENERATE_SOURCE(MULTIMAP, mm, mmap, int, int)
CMC_COLLECTION_GENERATE_SOURCE(MULTISET, ms, mset, , int)
+14 -10
View File
@@ -1,12 +1,16 @@
#include "../../src/macro_collections.h"
COLLECTION_GENERATE_HEADER(LIST, l, list, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_HEADER(STACK, s, stack, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_HEADER(QUEUE, q, queue, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_HEADER(DEQUE, d, deque, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_HEADER(LINKEDLIST, ll, linked, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_HEADER(HEAP, h, heap, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_HEADER(TREESET, ts, tset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_HEADER(TREEMAP, tm, tmap, /* FMOD */, int, int)
COLLECTION_GENERATE_HEADER(HASHSET, hs, hset, /* FMOD */, /* K */, int)
COLLECTION_GENERATE_HEADER(HASHMAP, hm, hmap, /* FMOD */, int, int)
CMC_COLLECTION_GENERATE_HEADER(LIST, l, list, /* K */, int)
CMC_COLLECTION_GENERATE_HEADER(STACK, s, stack, /* K */, int)
CMC_COLLECTION_GENERATE_HEADER(QUEUE, q, queue, /* K */, int)
CMC_COLLECTION_GENERATE_HEADER(DEQUE, d, deque, /* K */, int)
CMC_COLLECTION_GENERATE_HEADER(LINKEDLIST, ll, linked, /* K */, int)
CMC_COLLECTION_GENERATE_HEADER(HEAP, h, heap, /* K */, int)
CMC_COLLECTION_GENERATE_HEADER(TREESET, ts, tset, /* K */, int)
CMC_COLLECTION_GENERATE_HEADER(TREEMAP, tm, tmap, int, int)
CMC_COLLECTION_GENERATE_HEADER(HASHSET, hs, hset, /* K */, int)
CMC_COLLECTION_GENERATE_HEADER(HASHMAP, hm, hmap, int, int)
CMC_COLLECTION_GENERATE_HEADER(INTERVALHEAP, ih, iheap, , int)
CMC_COLLECTION_GENERATE_HEADER(MULTIMAP, mm, mmap, int, int)
CMC_COLLECTION_GENERATE_HEADER(MULTISET, ms, mset, , int)
+127 -100
View File
@@ -26,115 +26,142 @@ typedef union union_u {
typedef int (*func_t)(int, double, char *);
COLLECTION_GENERATE(LIST, l0, list0, static, /* K */, struct_t *)
COLLECTION_GENERATE(STACK, s0, stack0, static, /* K */, struct_t *)
COLLECTION_GENERATE(QUEUE, q0, queue0, static, /* K */, struct_t *)
COLLECTION_GENERATE(DEQUE, d0, deque0, static, /* K */, struct_t *)
COLLECTION_GENERATE(LINKEDLIST, ll0, linked0, static, /* K */, struct_t *)
COLLECTION_GENERATE(HEAP, h0, heap0, static, /* K */, struct_t *)
COLLECTION_GENERATE(TREESET, ts0, tset0, static, /* K */, struct_t *)
COLLECTION_GENERATE(TREEMAP, tm0, tmap0, static, struct_t *, struct_t *)
COLLECTION_GENERATE(HASHSET, hs0, hset0, static, /* K */, struct_t *)
COLLECTION_GENERATE(HASHMAP, hm0, hmap0, static, struct_t *, struct_t *)
CMC_COLLECTION_GENERATE(LIST, l0, list0, /* K */, struct_t *)
CMC_COLLECTION_GENERATE(STACK, s0, stack0, /* K */, struct_t *)
CMC_COLLECTION_GENERATE(QUEUE, q0, queue0, /* K */, struct_t *)
CMC_COLLECTION_GENERATE(DEQUE, d0, deque0, /* K */, struct_t *)
CMC_COLLECTION_GENERATE(LINKEDLIST, ll0, linked0, /* K */, struct_t *)
CMC_COLLECTION_GENERATE(HEAP, h0, heap0, /* K */, struct_t *)
CMC_COLLECTION_GENERATE(TREESET, ts0, tset0, /* K */, struct_t *)
CMC_COLLECTION_GENERATE(TREEMAP, tm0, tmap0, struct_t *, struct_t *)
CMC_COLLECTION_GENERATE(HASHSET, hs0, hset0, /* K */, struct_t *)
CMC_COLLECTION_GENERATE(HASHMAP, hm0, hmap0, struct_t *, struct_t *)
CMC_COLLECTION_GENERATE(INTERVALHEAP, ih0, iheap0, struct_t *, struct_t *)
CMC_COLLECTION_GENERATE(MULTIMAP, mm0, mmap0, struct_t *, struct_t *)
CMC_COLLECTION_GENERATE(MULTISET, ms0, mset0, struct_t *, struct_t *)
COLLECTION_GENERATE(LIST, l1, list1, static, /* K */, struct_t)
COLLECTION_GENERATE(STACK, s1, stack1, static, /* K */, struct_t)
COLLECTION_GENERATE(QUEUE, q1, queue1, static, /* K */, struct_t)
COLLECTION_GENERATE(DEQUE, d1, deque1, static, /* K */, struct_t)
COLLECTION_GENERATE(LINKEDLIST, ll1, linked1, static, /* K */, struct_t)
COLLECTION_GENERATE(HEAP, h1, heap1, static, /* K */, struct_t)
COLLECTION_GENERATE(TREESET, ts1, tset1, static, /* K */, struct_t)
COLLECTION_GENERATE(TREEMAP, tm1, tmap1, static, struct_t, struct_t)
COLLECTION_GENERATE(HASHSET, hs1, hset1, static, /* K */, struct_t)
COLLECTION_GENERATE(HASHMAP, hm1, hmap1, static, struct_t, struct_t)
CMC_COLLECTION_GENERATE(LIST, l1, list1, /* K */, struct_t)
CMC_COLLECTION_GENERATE(STACK, s1, stack1, /* K */, struct_t)
CMC_COLLECTION_GENERATE(QUEUE, q1, queue1, /* K */, struct_t)
CMC_COLLECTION_GENERATE(DEQUE, d1, deque1, /* K */, struct_t)
CMC_COLLECTION_GENERATE(LINKEDLIST, ll1, linked1, /* K */, struct_t)
CMC_COLLECTION_GENERATE(HEAP, h1, heap1, /* K */, struct_t)
CMC_COLLECTION_GENERATE(TREESET, ts1, tset1, /* K */, struct_t)
CMC_COLLECTION_GENERATE(TREEMAP, tm1, tmap1, struct_t, struct_t)
CMC_COLLECTION_GENERATE(HASHSET, hs1, hset1, /* K */, struct_t)
CMC_COLLECTION_GENERATE(HASHMAP, hm1, hmap1, struct_t, struct_t)
CMC_COLLECTION_GENERATE(INTERVALHEAP, ih1, iheap1, struct_t, struct_t)
CMC_COLLECTION_GENERATE(MULTIMAP, mm1, mmap1, struct_t, struct_t)
CMC_COLLECTION_GENERATE(MULTISET, ms1, mset1, struct_t, struct_t)
COLLECTION_GENERATE(LIST, l2, list2, static, /* K */, int)
COLLECTION_GENERATE(STACK, s2, stack2, static, /* K */, int)
COLLECTION_GENERATE(QUEUE, q2, queue2, static, /* K */, int)
COLLECTION_GENERATE(DEQUE, d2, deque2, static, /* K */, int)
COLLECTION_GENERATE(LINKEDLIST, ll2, linked2, static, /* K */, int)
COLLECTION_GENERATE(HEAP, h2, heap2, static, /* K */, int)
COLLECTION_GENERATE(TREESET, ts2, tset2, static, /* K */, int)
COLLECTION_GENERATE(TREEMAP, tm2, tmap2, static, int, int)
COLLECTION_GENERATE(HASHSET, hs2, hset2, static, /* K */, int)
COLLECTION_GENERATE(HASHMAP, hm2, hmap2, static, int, int)
CMC_COLLECTION_GENERATE(LIST, l2, list2, /* K */, int)
CMC_COLLECTION_GENERATE(STACK, s2, stack2, /* K */, int)
CMC_COLLECTION_GENERATE(QUEUE, q2, queue2, /* K */, int)
CMC_COLLECTION_GENERATE(DEQUE, d2, deque2, /* K */, int)
CMC_COLLECTION_GENERATE(LINKEDLIST, ll2, linked2, /* K */, int)
CMC_COLLECTION_GENERATE(HEAP, h2, heap2, /* K */, int)
CMC_COLLECTION_GENERATE(TREESET, ts2, tset2, /* K */, int)
CMC_COLLECTION_GENERATE(TREEMAP, tm2, tmap2, int, int)
CMC_COLLECTION_GENERATE(HASHSET, hs2, hset2, /* K */, int)
CMC_COLLECTION_GENERATE(HASHMAP, hm2, hmap2, int, int)
CMC_COLLECTION_GENERATE(INTERVALHEAP, ih2, iheap2, /* K */, int)
CMC_COLLECTION_GENERATE(MULTIMAP, mm2, mmap2, int, int)
CMC_COLLECTION_GENERATE(MULTISET, ms2, mset2, /* K */, int)
COLLECTION_GENERATE(LIST, l3, list3, static, /* K */, int *)
COLLECTION_GENERATE(STACK, s3, stack3, static, /* K */, int *)
COLLECTION_GENERATE(QUEUE, q3, queue3, static, /* K */, int *)
COLLECTION_GENERATE(DEQUE, d3, deque3, static, /* K */, int *)
COLLECTION_GENERATE(LINKEDLIST, ll3, linked3, static, /* K */, int *)
COLLECTION_GENERATE(HEAP, h3, heap3, static, /* K */, int *)
COLLECTION_GENERATE(TREESET, ts3, tset3, static, /* K */, int *)
COLLECTION_GENERATE(TREEMAP, tm3, tmap3, static, int *, int *)
COLLECTION_GENERATE(HASHSET, hs3, hset3, static, /* K */, int *)
COLLECTION_GENERATE(HASHMAP, hm3, hmap3, static, int *, int *)
CMC_COLLECTION_GENERATE(LIST, l3, list3, /* K */, int *)
CMC_COLLECTION_GENERATE(STACK, s3, stack3, /* K */, int *)
CMC_COLLECTION_GENERATE(QUEUE, q3, queue3, /* K */, int *)
CMC_COLLECTION_GENERATE(DEQUE, d3, deque3, /* K */, int *)
CMC_COLLECTION_GENERATE(LINKEDLIST, ll3, linked3, /* K */, int *)
CMC_COLLECTION_GENERATE(HEAP, h3, heap3, /* K */, int *)
CMC_COLLECTION_GENERATE(TREESET, ts3, tset3, /* K */, int *)
CMC_COLLECTION_GENERATE(TREEMAP, tm3, tmap3, int *, int *)
CMC_COLLECTION_GENERATE(HASHSET, hs3, hset3, /* K */, int *)
CMC_COLLECTION_GENERATE(HASHMAP, hm3, hmap3, int *, int *)
CMC_COLLECTION_GENERATE(INTERVALHEAP, ih3, iheap3, /* K */, int *)
CMC_COLLECTION_GENERATE(MULTIMAP, mm3, mmap3, int *, int *)
CMC_COLLECTION_GENERATE(MULTISET, ms3, mset3, /* K */, int *)
COLLECTION_GENERATE(LIST, l4, list4, static, /* K */, enum_t *)
COLLECTION_GENERATE(STACK, s4, stack4, static, /* K */, enum_t *)
COLLECTION_GENERATE(QUEUE, q4, queue4, static, /* K */, enum_t *)
COLLECTION_GENERATE(DEQUE, d4, deque4, static, /* K */, enum_t *)
COLLECTION_GENERATE(LINKEDLIST, ll4, linked4, static, /* K */, enum_t *)
COLLECTION_GENERATE(HEAP, h4, heap4, static, /* K */, enum_t *)
COLLECTION_GENERATE(TREESET, ts4, tset4, static, /* K */, enum_t *)
COLLECTION_GENERATE(TREEMAP, tm4, tmap4, static, enum_t *, enum_t *)
COLLECTION_GENERATE(HASHSET, hs4, hset4, static, /* K */, enum_t *)
COLLECTION_GENERATE(HASHMAP, hm4, hmap4, static, enum_t *, enum_t *)
CMC_COLLECTION_GENERATE(LIST, l4, list4, /* K */, enum_t *)
CMC_COLLECTION_GENERATE(STACK, s4, stack4, /* K */, enum_t *)
CMC_COLLECTION_GENERATE(QUEUE, q4, queue4, /* K */, enum_t *)
CMC_COLLECTION_GENERATE(DEQUE, d4, deque4, /* K */, enum_t *)
CMC_COLLECTION_GENERATE(LINKEDLIST, ll4, linked4, /* K */, enum_t *)
CMC_COLLECTION_GENERATE(HEAP, h4, heap4, /* K */, enum_t *)
CMC_COLLECTION_GENERATE(TREESET, ts4, tset4, /* K */, enum_t *)
CMC_COLLECTION_GENERATE(TREEMAP, tm4, tmap4, enum_t *, enum_t *)
CMC_COLLECTION_GENERATE(HASHSET, hs4, hset4, /* K */, enum_t *)
CMC_COLLECTION_GENERATE(HASHMAP, hm4, hmap4, enum_t *, enum_t *)
CMC_COLLECTION_GENERATE(INTERVALHEAP, ih4, iheap4, /* K */, enum_t *)
CMC_COLLECTION_GENERATE(MULTIMAP, mm4, mmap4, enum_t *, enum_t *)
CMC_COLLECTION_GENERATE(MULTISET, ms4, mset4, /* K */, enum_t *)
COLLECTION_GENERATE(LIST, l5, list5, static, /* K */, enum_t)
COLLECTION_GENERATE(STACK, s5, stack5, static, /* K */, enum_t)
COLLECTION_GENERATE(QUEUE, q5, queue5, static, /* K */, enum_t)
COLLECTION_GENERATE(DEQUE, d5, deque5, static, /* K */, enum_t)
COLLECTION_GENERATE(LINKEDLIST, ll5, linked5, static, /* K */, enum_t)
COLLECTION_GENERATE(HEAP, h5, heap5, static, /* K */, enum_t)
COLLECTION_GENERATE(TREESET, ts5, tset5, static, /* K */, enum_t)
COLLECTION_GENERATE(TREEMAP, tm5, tmap5, static, enum_t, enum_t)
COLLECTION_GENERATE(HASHSET, hs5, hset5, static, /* K */, enum_t)
COLLECTION_GENERATE(HASHMAP, hm5, hmap5, static, enum_t, enum_t)
CMC_COLLECTION_GENERATE(LIST, l5, list5, /* K */, enum_t)
CMC_COLLECTION_GENERATE(STACK, s5, stack5, /* K */, enum_t)
CMC_COLLECTION_GENERATE(QUEUE, q5, queue5, /* K */, enum_t)
CMC_COLLECTION_GENERATE(DEQUE, d5, deque5, /* K */, enum_t)
CMC_COLLECTION_GENERATE(LINKEDLIST, ll5, linked5, /* K */, enum_t)
CMC_COLLECTION_GENERATE(HEAP, h5, heap5, /* K */, enum_t)
CMC_COLLECTION_GENERATE(TREESET, ts5, tset5, /* K */, enum_t)
CMC_COLLECTION_GENERATE(TREEMAP, tm5, tmap5, enum_t, enum_t)
CMC_COLLECTION_GENERATE(HASHSET, hs5, hset5, /* K */, enum_t)
CMC_COLLECTION_GENERATE(HASHMAP, hm5, hmap5, enum_t, enum_t)
CMC_COLLECTION_GENERATE(INTERVALHEAP, ih5, iheap5, /* K */, enum_t)
CMC_COLLECTION_GENERATE(MULTIMAP, mm5, mmap5, enum_t, enum_t)
CMC_COLLECTION_GENERATE(MULTISET, ms5, mset5, /* K */, enum_t)
COLLECTION_GENERATE(LIST, l6, list6, static, /* K */, union_t *)
COLLECTION_GENERATE(STACK, s6, stack6, static, /* K */, union_t *)
COLLECTION_GENERATE(QUEUE, q6, queue6, static, /* K */, union_t *)
COLLECTION_GENERATE(DEQUE, d6, deque6, static, /* K */, union_t *)
COLLECTION_GENERATE(LINKEDLIST, ll6, linked6, static, /* K */, union_t *)
COLLECTION_GENERATE(HEAP, h6, heap6, static, /* K */, union_t *)
COLLECTION_GENERATE(TREESET, ts6, tset6, static, /* K */, union_t *)
COLLECTION_GENERATE(TREEMAP, tm6, tmap6, static, union_t *, union_t *)
COLLECTION_GENERATE(HASHSET, hs6, hset6, static, /* K */, union_t *)
COLLECTION_GENERATE(HASHMAP, hm6, hmap6, static, union_t *, union_t *)
CMC_COLLECTION_GENERATE(LIST, l6, list6, /* K */, union_t *)
CMC_COLLECTION_GENERATE(STACK, s6, stack6, /* K */, union_t *)
CMC_COLLECTION_GENERATE(QUEUE, q6, queue6, /* K */, union_t *)
CMC_COLLECTION_GENERATE(DEQUE, d6, deque6, /* K */, union_t *)
CMC_COLLECTION_GENERATE(LINKEDLIST, ll6, linked6, /* K */, union_t *)
CMC_COLLECTION_GENERATE(HEAP, h6, heap6, /* K */, union_t *)
CMC_COLLECTION_GENERATE(TREESET, ts6, tset6, /* K */, union_t *)
CMC_COLLECTION_GENERATE(TREEMAP, tm6, tmap6, union_t *, union_t *)
CMC_COLLECTION_GENERATE(HASHSET, hs6, hset6, /* K */, union_t *)
CMC_COLLECTION_GENERATE(HASHMAP, hm6, hmap6, union_t *, union_t *)
CMC_COLLECTION_GENERATE(INTERVALHEAP, ih6, iheap6, /* K */, union_t *)
CMC_COLLECTION_GENERATE(MULTIMAP, mm6, mmap6, union_t *, union_t *)
CMC_COLLECTION_GENERATE(MULTISET, ms6, mset6, /* K */, union_t *)
COLLECTION_GENERATE(LIST, l7, list7, static, /* K */, union_t)
COLLECTION_GENERATE(STACK, s7, stack7, static, /* K */, union_t)
COLLECTION_GENERATE(QUEUE, q7, queue7, static, /* K */, union_t)
COLLECTION_GENERATE(DEQUE, d7, deque7, static, /* K */, union_t)
COLLECTION_GENERATE(LINKEDLIST, ll7, linked7, static, /* K */, union_t)
COLLECTION_GENERATE(HEAP, h7, heap7, static, /* K */, union_t)
COLLECTION_GENERATE(TREESET, ts7, tset7, static, /* K */, union_t)
COLLECTION_GENERATE(TREEMAP, tm7, tmap7, static, union_t, union_t)
COLLECTION_GENERATE(HASHSET, hs7, hset7, static, /* K */, union_t)
COLLECTION_GENERATE(HASHMAP, hm7, hmap7, static, union_t, union_t)
CMC_COLLECTION_GENERATE(LIST, l7, list7, /* K */, union_t)
CMC_COLLECTION_GENERATE(STACK, s7, stack7, /* K */, union_t)
CMC_COLLECTION_GENERATE(QUEUE, q7, queue7, /* K */, union_t)
CMC_COLLECTION_GENERATE(DEQUE, d7, deque7, /* K */, union_t)
CMC_COLLECTION_GENERATE(LINKEDLIST, ll7, linked7, /* K */, union_t)
CMC_COLLECTION_GENERATE(HEAP, h7, heap7, /* K */, union_t)
CMC_COLLECTION_GENERATE(TREESET, ts7, tset7, /* K */, union_t)
CMC_COLLECTION_GENERATE(TREEMAP, tm7, tmap7, union_t, union_t)
CMC_COLLECTION_GENERATE(HASHSET, hs7, hset7, /* K */, union_t)
CMC_COLLECTION_GENERATE(HASHMAP, hm7, hmap7, union_t, union_t)
CMC_COLLECTION_GENERATE(INTERVALHEAP, ih7, iheap7, /* K */, union_t)
CMC_COLLECTION_GENERATE(MULTIMAP, mm7, mmap7, union_t, union_t)
CMC_COLLECTION_GENERATE(MULTISET, ms7, mset7, /* K */, union_t)
COLLECTION_GENERATE(LIST, l8, list8, static, /* K */, func_t)
COLLECTION_GENERATE(STACK, s8, stack8, static, /* K */, func_t)
COLLECTION_GENERATE(QUEUE, q8, queue8, static, /* K */, func_t)
COLLECTION_GENERATE(DEQUE, d8, deque8, static, /* K */, func_t)
COLLECTION_GENERATE(LINKEDLIST, ll8, linked8, static, /* K */, func_t)
COLLECTION_GENERATE(HEAP, h8, heap8, static, /* K */, func_t)
COLLECTION_GENERATE(TREESET, ts8, tset8, static, /* K */, func_t)
COLLECTION_GENERATE(TREEMAP, tm8, tmap8, static, func_t, func_t)
COLLECTION_GENERATE(HASHSET, hs8, hset8, static, /* K */, func_t)
COLLECTION_GENERATE(HASHMAP, hm8, hmap8, static, func_t, func_t)
CMC_COLLECTION_GENERATE(LIST, l8, list8, /* K */, func_t)
CMC_COLLECTION_GENERATE(STACK, s8, stack8, /* K */, func_t)
CMC_COLLECTION_GENERATE(QUEUE, q8, queue8, /* K */, func_t)
CMC_COLLECTION_GENERATE(DEQUE, d8, deque8, /* K */, func_t)
CMC_COLLECTION_GENERATE(LINKEDLIST, ll8, linked8, /* K */, func_t)
CMC_COLLECTION_GENERATE(HEAP, h8, heap8, /* K */, func_t)
CMC_COLLECTION_GENERATE(TREESET, ts8, tset8, /* K */, func_t)
CMC_COLLECTION_GENERATE(TREEMAP, tm8, tmap8, func_t, func_t)
CMC_COLLECTION_GENERATE(HASHSET, hs8, hset8, /* K */, func_t)
CMC_COLLECTION_GENERATE(HASHMAP, hm8, hmap8, func_t, func_t)
CMC_COLLECTION_GENERATE(INTERVALHEAP, ih8, iheap8, /* K */, func_t)
CMC_COLLECTION_GENERATE(MULTIMAP, mm8, mmap8, func_t, func_t)
CMC_COLLECTION_GENERATE(MULTISET, ms8, mset8, /* K */, func_t)
COLLECTION_GENERATE(LIST, l9, list9, static, /* K */, func_t)
COLLECTION_GENERATE(STACK, s9, stack9, static, /* K */, func_t)
COLLECTION_GENERATE(QUEUE, q9, queue9, static, /* K */, func_t)
COLLECTION_GENERATE(DEQUE, d9, deque9, static, /* K */, func_t)
COLLECTION_GENERATE(LINKEDLIST, ll9, linked9, static, /* K */, func_t)
COLLECTION_GENERATE(HEAP, h9, heap9, static, /* K */, func_t)
COLLECTION_GENERATE(TREESET, ts9, tset9, static, /* K */, func_t)
COLLECTION_GENERATE(TREEMAP, tm9, tmap9, static, func_t, func_t)
COLLECTION_GENERATE(HASHSET, hs9, hset9, static, /* K */, func_t)
COLLECTION_GENERATE(HASHMAP, hm9, hmap9, static, func_t, func_t)
CMC_COLLECTION_GENERATE(LIST, l9, list9, /* K */, func_t)
CMC_COLLECTION_GENERATE(STACK, s9, stack9, /* K */, func_t)
CMC_COLLECTION_GENERATE(QUEUE, q9, queue9, /* K */, func_t)
CMC_COLLECTION_GENERATE(DEQUE, d9, deque9, /* K */, func_t)
CMC_COLLECTION_GENERATE(LINKEDLIST, ll9, linked9, /* K */, func_t)
CMC_COLLECTION_GENERATE(HEAP, h9, heap9, /* K */, func_t)
CMC_COLLECTION_GENERATE(TREESET, ts9, tset9, /* K */, func_t)
CMC_COLLECTION_GENERATE(TREEMAP, tm9, tmap9, func_t, func_t)
CMC_COLLECTION_GENERATE(HASHSET, hs9, hset9, /* K */, func_t)
CMC_COLLECTION_GENERATE(HASHMAP, hm9, hmap9, func_t, func_t)
int main(void)
{