From 71fd0b8ad56f84491b77302702d68c229e2a2b0f Mon Sep 17 00:00:00 2001
From: Leonardo Vencovsky
Date: Thu, 19 Jan 2023 15:37:44 +0100
Subject: [PATCH] More refactoring
---
README.md | 64 +-
TODO | 1 -
examples/Makefile | 9 +
examples/example.c | 68 +++
src/cmc/cmc/bitset/ext/code.h | 12 +-
src/cmc/cmc/bitset/ext/header.h | 12 +-
src/cmc/cmc/bitset/ext/struct.h | 4 +-
src/cmc/cmc/deque/ext/code.h | 12 +-
src/cmc/cmc/deque/ext/header.h | 12 +-
src/cmc/cmc/deque/ext/struct.h | 4 +-
src/cmc/cmc/hashbidimap/ext/code.h | 12 +-
src/cmc/cmc/hashbidimap/ext/header.h | 12 +-
src/cmc/cmc/hashbidimap/ext/struct.h | 4 +-
src/cmc/cmc/hashmap/ext/code.h | 12 +-
src/cmc/cmc/hashmap/ext/header.h | 12 +-
src/cmc/cmc/hashmap/ext/struct.h | 4 +-
src/cmc/cmc/hashmultimap/ext/code.h | 12 +-
src/cmc/cmc/hashmultimap/ext/header.h | 12 +-
src/cmc/cmc/hashmultimap/ext/struct.h | 4 +-
src/cmc/cmc/hashmultiset/ext/code.h | 16 +-
src/cmc/cmc/hashmultiset/ext/header.h | 16 +-
src/cmc/cmc/hashmultiset/ext/struct.h | 4 +-
src/cmc/cmc/hashset/ext/code.h | 16 +-
src/cmc/cmc/hashset/ext/header.h | 16 +-
src/cmc/cmc/hashset/ext/struct.h | 4 +-
src/cmc/cmc/heap/ext/code.h | 12 +-
src/cmc/cmc/heap/ext/header.h | 12 +-
src/cmc/cmc/heap/ext/struct.h | 4 +-
src/cmc/cmc/intervalheap/ext/code.h | 12 +-
src/cmc/cmc/intervalheap/ext/header.h | 12 +-
src/cmc/cmc/linkedlist/code.h | 528 +++++++++++++++++
src/cmc/cmc/linkedlist/ext/code.h | 494 ++++++++++++++++
src/cmc/cmc/linkedlist/ext/header.h | 115 ++++
src/cmc/cmc/linkedlist/ext/struct.h | 32 +
src/cmc/cmc/linkedlist/header.h | 71 +++
src/cmc/cmc/linkedlist/struct.h | 61 ++
src/cmc/cmc/list/ext/code.h | 16 +-
src/cmc/cmc/list/ext/header.h | 16 +-
src/cmc/cmc/list/ext/struct.h | 4 +-
src/cmc/cmc/queue/ext/code.h | 12 +-
src/cmc/cmc/queue/ext/header.h | 12 +-
src/cmc/cmc/queue/ext/struct.h | 4 +-
src/cmc/cmc/sortedlist/code.h | 479 +++++++++++++++
src/cmc/cmc/sortedlist/ext/code.h | 267 +++++++++
src/cmc/cmc/sortedlist/ext/header.h | 85 +++
src/cmc/cmc/sortedlist/ext/struct.h | 23 +
src/cmc/cmc/sortedlist/header.h | 70 +++
src/cmc/cmc/sortedlist/struct.h | 43 ++
src/cmc/cmc/stack/ext/code.h | 12 +-
src/cmc/cmc/stack/ext/header.h | 12 +-
src/cmc/cmc/stack/ext/struct.h | 4 +-
src/cmc/cmc/treemap/code.h | 777 ++++++++++++++++++++++++
src/cmc/cmc/treemap/ext/code.h | 386 ++++++++++++
src/cmc/cmc/treemap/ext/header.h | 94 +++
src/cmc/cmc/treemap/ext/struct.h | 23 +
src/cmc/cmc/treemap/header.h | 85 +++
src/cmc/cmc/treemap/struct.h | 70 +++
src/cmc/cmc/treeset/code.h | 686 +++++++++++++++++++++
src/cmc/cmc/treeset/ext/code.h | 577 ++++++++++++++++++
src/cmc/cmc/treeset/ext/header.h | 111 ++++
src/cmc/cmc/treeset/ext/struct.h | 23 +
src/cmc/cmc/treeset/header.h | 65 ++
src/cmc/cmc/treeset/struct.h | 64 ++
src/cmc/cor/undef.h | 73 +--
src/cmc/linkedlist.h | 86 +++
src/cmc/sortedlist.h | 79 +++
src/cmc/treemap.h | 77 +++
src/cmc/treeset.h | 77 +++
tests/main.c | 36 +-
tests/unt_bitset.h | 3 -
tests/unt_deque.h | 3 -
tests/unt_foreach.h | 474 +++++++++++++++
tests/unt_hashbidimap.h | 3 -
tests/unt_hashmap.h | 3 -
tests/unt_hashmultimap.h | 3 -
tests/unt_hashmultiset.h | 4 -
tests/unt_hashset.h | 4 -
tests/unt_heap.h | 3 -
tests/unt_intervalheap.h | 3 -
tests/unt_linkedlist.h | 817 ++++++++++++++++++++++++++
tests/unt_list.h | 4 -
tests/unt_queue.h | 3 -
tests/unt_sortedlist.h | 717 ++++++++++++++++++++++
tests/unt_stack.h | 3 -
tests/unt_treemap.h | 674 +++++++++++++++++++++
tests/unt_treeset.h | 588 ++++++++++++++++++
86 files changed, 9149 insertions(+), 315 deletions(-)
create mode 100644 examples/Makefile
create mode 100644 examples/example.c
create mode 100644 src/cmc/cmc/linkedlist/code.h
create mode 100644 src/cmc/cmc/linkedlist/ext/code.h
create mode 100644 src/cmc/cmc/linkedlist/ext/header.h
create mode 100644 src/cmc/cmc/linkedlist/ext/struct.h
create mode 100644 src/cmc/cmc/linkedlist/header.h
create mode 100644 src/cmc/cmc/linkedlist/struct.h
create mode 100644 src/cmc/cmc/sortedlist/code.h
create mode 100644 src/cmc/cmc/sortedlist/ext/code.h
create mode 100644 src/cmc/cmc/sortedlist/ext/header.h
create mode 100644 src/cmc/cmc/sortedlist/ext/struct.h
create mode 100644 src/cmc/cmc/sortedlist/header.h
create mode 100644 src/cmc/cmc/sortedlist/struct.h
create mode 100644 src/cmc/cmc/treemap/code.h
create mode 100644 src/cmc/cmc/treemap/ext/code.h
create mode 100644 src/cmc/cmc/treemap/ext/header.h
create mode 100644 src/cmc/cmc/treemap/ext/struct.h
create mode 100644 src/cmc/cmc/treemap/header.h
create mode 100644 src/cmc/cmc/treemap/struct.h
create mode 100644 src/cmc/cmc/treeset/code.h
create mode 100644 src/cmc/cmc/treeset/ext/code.h
create mode 100644 src/cmc/cmc/treeset/ext/header.h
create mode 100644 src/cmc/cmc/treeset/ext/struct.h
create mode 100644 src/cmc/cmc/treeset/header.h
create mode 100644 src/cmc/cmc/treeset/struct.h
create mode 100644 src/cmc/linkedlist.h
create mode 100644 src/cmc/sortedlist.h
create mode 100644 src/cmc/treemap.h
create mode 100644 src/cmc/treeset.h
create mode 100644 tests/unt_foreach.h
create mode 100644 tests/unt_linkedlist.h
create mode 100644 tests/unt_sortedlist.h
create mode 100644 tests/unt_treemap.h
create mode 100644 tests/unt_treeset.h
diff --git a/README.md b/README.md
index ce70370..f2be176 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,6 @@
-
@@ -20,6 +19,12 @@
+
+
+
+
+
+
## Table of Contents
* [Installation](#installation)
@@ -41,26 +46,24 @@ There is a lot to be done. You can check the `TODO` file in the root of the repo
## Usage
-The header `macro_collections.h` includes every feature from the library and comes with higher level APIs that help you generate collections from specific sub-libraries with specific extensions.
-
Below is a minimal example that makes use of some core functionalities. And a lot of explanation too!
```c
-// This is the master header. This will include every feature of the library.
-// This comes with many helper macros (high level API) and utility functions.
-#include "macro_collections.h"
+// The C Macro Collections takes advantage of headers that can be included
+// multiple times. You can check the contents of src/cmc/list.h and there are no
+// include guards, meaning they can be included multiple times and this is what
+// generates the code.
+// Before including it though we need to define a few basic macros. You can
+// check the documentation to see which ones are required.
+#define V int // list value data type
+#define PFX intl // list function's prefix
+#define SNAME int_list // list struct name (struct int_list)
+#define CMC_EXT_STR // Enables an extra functionality (STR) of the list
+#include "cmc/list.h"
-// A PARAM is a standard way to pass required parameters to the lower level API.
-// It is a tuple of form (PFX, SNAME, SIZE, K, V). In this case, not all of them
-// are used, so we can leave them empty. We are creating a list of value int.
-#define MY_LIST_PARAMS (intl, int_list, , , int)
-
-// High level API. Generate a LIST from the CMC library with the STR extension
-// using our previously defined PARAMs. Every collections has a CORE part that
-// needs to be generated first. Then, we can add other parts after. This macro
-// does all of that for us. The STR part will provide us with a function that
-// will be used later.
-C_MACRO_COLLECTIONS_EXTENDED(CMC, LIST, MY_LIST_PARAMS, (STR))
+// This header file includes a lot of functions that can be used as methods to
+// basic data types. In this case, cmc_i32_str is used
+#include "cmc/utl/futils.h"
int main(void)
{
@@ -76,8 +79,8 @@ int main(void)
// hash, comparison and printing. A list doesn't require any of these
// functions. That is, the CORE module doesn't use any of them.
// But since we are using the STR module, we will need to define the 'str'
- // function. luckily, for the 'int' type, the library already provides such
- // function (cmc_i32_str), provided by the /utl/futils.h header file.
+ // function. Luckily, for the 'int' type, the library already provides such
+ // function (cmc_i32_str), provided by the cmc/utl/futils.h header file.
struct int_list *list = intl_new(32, &(struct int_list_fval){ .str = cmc_i32_str, NULL });
// Check if the list was successfully initialized. It could fail if the
@@ -96,7 +99,8 @@ int main(void)
if (!intl_push_back(list, i))
{
enum cmc_flags flag = intl_flag(list);
- // Use cmc_flags_to_str to map the enum error to a string.
+ // Use cmc_flags_to_str (global variable) to map the enum error to a
+ // string.
fprintf(stderr, "%s : push_back failed\n", cmc_flags_to_str[flag]);
}
}
@@ -105,13 +109,11 @@ int main(void)
// '.str' from the function table comes into play. If we haven't defined it,
// the program would've crashed. We also need to define to which file we
// will be printing the list's content. In this case, the terminal. Also,
- // some strings need to be defined. They will be printed: before all elements,
- // between each one, and after all elements. This is very usefull and can
- // print a data structure very nicely.
+ // some strings need to be defined. They will be printed: before all
+ // elements, between each one, and after all elements. This is very useful
+ // for debugging.
intl_print(list, stdout, "[ ", ", ", " ]\n");
- // You should see a nicely printed list in your terminal.
-
// Free all of its resources
intl_free(list);
}
@@ -127,7 +129,7 @@ The C Macro Collections library is organized into many other sub-libraries. The
| :-----: | -------------------------------- | ------------------------------------------------------------------------------------------- |
| CMC | Macro Collections | The main library with dynamically-sized collections |
| COR | Core | Core functionalities used by more than one collection, usually from different sub-libraries |
-| EXT | Extensions | Extension to collections from CMC, SAC and TSC libraries |
+| EXT | Extensions | Extension to collections |
| INT | Integrations | Macros that facilitate the creation of code that involves more than one type of collection |
| SAC | Statically Allocated Collections | Collections with a fixed sized array that don't use any heap allocation |
| TSC | Thread-Safe Collections | Collections that allow multiple operations from multiple threads |
@@ -239,8 +241,8 @@ A priority function works much like the comparator function except that it compa
The following table shows which functions are required, optional or never used for each Collection:
-| Collection | CMP | CPY | STR | FREE | HASH | PRI |
-| ------------ | :------------------------------------------------------: | :------------------------------------------------------: | :------------------------------------------------------: | :------------------------------------------------------: | :------------------------------------------------------: | :------------------------------------------------------: |
+| Collection | CMP | CPY | STR | FREE | HASH | PRI |
+| ------------ | :-------------------------------------------------------=-----: | :-------------------------------------------------------------: | :-------------------------------------------------------------: | :-------------------------------------------------------------: | :-------------------------------------------------------------: | :-------------------------------------------------------------: |
| Deque |  |  |  |  |  |  |
| HashMap |  |  |  |  |  |  |
| HashBidiMap |  |  |  |  |  |  |
@@ -257,8 +259,8 @@ The following table shows which functions are required, optional or never used f
| TreeMap |  |  |  |  |  |  |
| TreeSet |  |  |  |  |  |  |
-| Color | Label |
-| :------------------------------------------------------: | ----------------------------------------- |
+| Color | Label |
+| :-------------------------------------------------------------: | ----------------------------------------- |
|  | Required for basic functionality. |
|  | Required for specific functions. |
|  | Required for non-core specific functions. |
@@ -291,5 +293,5 @@ Modifying a collection will possibly invalidate all iterators currently initiali
## Special Macros
-* `CMC_NO_ALLOC` - disables `"cor/alloc.h"`
+* `CMC_NO_ALLOC` - disables `"cor/alloc.h"`, useful for statically allocated collections (SAC)
* `CMC_NO_IMPORTS` - disables all imports from the standard library at `"cor/core.h"`
diff --git a/TODO b/TODO
index bf2effd..14aad19 100644
--- a/TODO
+++ b/TODO
@@ -44,7 +44,6 @@ Check out CHANGELOG
#!! Patch ----------------------------------------------------------------------
[ ] MultiSets replace existing value with the new added one
-[ ] Fix PUBLIC and PRIVATE incompatibility between CMC and EXT
#!! Considerations -------------------------------------------------------------
diff --git a/examples/Makefile b/examples/Makefile
new file mode 100644
index 0000000..6f80654
--- /dev/null
+++ b/examples/Makefile
@@ -0,0 +1,9 @@
+CC=gcc
+CFLAGS=-Wall -Wextra -Werror
+INCLUDE=-I ../src
+
+example: example.c
+ $(CC) $< -o $@.exe $(CFLAGS) $(INCLUDE)
+
+run: example
+ ./example.exe
diff --git a/examples/example.c b/examples/example.c
new file mode 100644
index 0000000..aceca71
--- /dev/null
+++ b/examples/example.c
@@ -0,0 +1,68 @@
+// The C Macro Collections takes advantage of headers that can be included
+// multiple times. You can check the contents of src/cmc/list.h and there are no
+// include guards, meaning they can be included multiple times and this is what
+// generates the code.
+// Before including it though we need to define a few basic macros. You can
+// check the documentation to see which ones are required.
+#define V int // list value data type
+#define PFX intl // list function's prefix
+#define SNAME int_list // list struct name (struct int_list)
+#define CMC_EXT_STR // Enables an extra functionality (STR) of the list
+#include "cmc/list.h"
+
+// This header file includes a lot of functions that can be used as methods to
+// basic data types. In this case, cmc_i32_str is used
+#include "cmc/utl/futils.h"
+
+int main(void)
+{
+ // Our list type is defined by SNAME and all functions are prefixed by PFX
+ // (PFX can also be thought as the function's namespace). Also, nodes,
+ // entries, iterators and other structures are prefixed by SNAME. So PFX is
+ // for functions and SNAME is for structs, where the main one is simply
+ // 'struct SNAME'.
+ // To initialize a list we need to pass in an initial capacity and something
+ // that is called a function table for the V type.
+ // This function table is a struct with methods that will extract some
+ // (sometimes) necessary behaviour from your custom data type. Things like
+ // hash, comparison and printing. A list doesn't require any of these
+ // functions. That is, the CORE module doesn't use any of them.
+ // But since we are using the STR module, we will need to define the 'str'
+ // function. Luckily, for the 'int' type, the library already provides such
+ // function (cmc_i32_str), provided by the cmc/utl/futils.h header file.
+ struct int_list *list = intl_new(32, &(struct int_list_fval){ .str = cmc_i32_str, NULL });
+
+ // Check if the list was successfully initialized. It could fail if the
+ // initial capacity is too big or if 'struct int_list_fval *' is NULL,
+ // because every data structure must have a valid function table.
+ if (!list)
+ return 1;
+
+ // Add some items to the list. The CMC data structures are all dynamically
+ // sized. So there can be as many items as you want as long as you have
+ // enough memory.
+ for (int i = 0; i < 100; i++)
+ {
+ // Try to add an element to the list. If it fails you can check what
+ // caused it by getting its flag.
+ if (!intl_push_back(list, i))
+ {
+ enum cmc_flags flag = intl_flag(list);
+ // Use cmc_flags_to_str (global variable) to map the enum error to a
+ // string.
+ fprintf(stderr, "%s : push_back failed\n", cmc_flags_to_str[flag]);
+ }
+ }
+
+ // Now we will use the STR module, the _print() function. This is where the
+ // '.str' from the function table comes into play. If we haven't defined it,
+ // the program would've crashed. We also need to define to which file we
+ // will be printing the list's content. In this case, the terminal. Also,
+ // some strings need to be defined. They will be printed: before all
+ // elements, between each one, and after all elements. This is very useful
+ // for debugging.
+ intl_print(list, stdout, "[ ", ", ", " ]\n");
+
+ // Free all of its resources
+ intl_free(list);
+}
diff --git a/src/cmc/cmc/bitset/ext/code.h b/src/cmc/cmc/bitset/ext/code.h
index 024f8fa..c58649a 100644
--- a/src/cmc/cmc/bitset/ext/code.h
+++ b/src/cmc/cmc/bitset/ext/code.h
@@ -28,16 +28,16 @@
* The part 'INIT' gives a new way of initializing a collection. The collection
* struct is not heap allocated, only its internal structure (nodes, buffers).
*/
-#ifdef CMC_EXT_BITSET_INIT
+#ifdef CMC_EXT_INIT
-#endif /* CMC_EXT_BITSET_INIT */
+#endif /* CMC_EXT_INIT */
/**
* ITER
*
* Bitset bi-directional iterator.
*/
-#ifdef CMC_EXT_BITSET_ITER
+#ifdef CMC_EXT_ITER
/* Iterator Functions */
/* Iterator Initialization */
@@ -45,13 +45,13 @@
/* Iterator Movement */
/* Iterator Access */
-#endif /* CMC_EXT_BITSET_ITER */
+#endif /* CMC_EXT_ITER */
/**
* STR
*
* Print helper functions.
*/
-#ifdef CMC_EXT_BITSET_STR
+#ifdef CMC_EXT_STR
-#endif /* CMC_EXT_BITSET_STR */
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/bitset/ext/header.h b/src/cmc/cmc/bitset/ext/header.h
index 024f8fa..c58649a 100644
--- a/src/cmc/cmc/bitset/ext/header.h
+++ b/src/cmc/cmc/bitset/ext/header.h
@@ -28,16 +28,16 @@
* The part 'INIT' gives a new way of initializing a collection. The collection
* struct is not heap allocated, only its internal structure (nodes, buffers).
*/
-#ifdef CMC_EXT_BITSET_INIT
+#ifdef CMC_EXT_INIT
-#endif /* CMC_EXT_BITSET_INIT */
+#endif /* CMC_EXT_INIT */
/**
* ITER
*
* Bitset bi-directional iterator.
*/
-#ifdef CMC_EXT_BITSET_ITER
+#ifdef CMC_EXT_ITER
/* Iterator Functions */
/* Iterator Initialization */
@@ -45,13 +45,13 @@
/* Iterator Movement */
/* Iterator Access */
-#endif /* CMC_EXT_BITSET_ITER */
+#endif /* CMC_EXT_ITER */
/**
* STR
*
* Print helper functions.
*/
-#ifdef CMC_EXT_BITSET_STR
+#ifdef CMC_EXT_STR
-#endif /* CMC_EXT_BITSET_STR */
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/bitset/ext/struct.h b/src/cmc/cmc/bitset/ext/struct.h
index 12b3db3..3fb8bc3 100644
--- a/src/cmc/cmc/bitset/ext/struct.h
+++ b/src/cmc/cmc/bitset/ext/struct.h
@@ -27,7 +27,7 @@
*
* Bitset bi-directional iterator.
*/
-#ifdef CMC_EXT_BITSET_ITER
+#ifdef CMC_EXT_ITER
/* BitSet Iterator */
struct CMC_DEF_ITER(SNAME)
@@ -42,4 +42,4 @@ struct CMC_DEF_ITER(SNAME)
bool end;
};
-#endif /* CMC_EXT_BITSET_ITER */
+#endif /* CMC_EXT_ITER */
diff --git a/src/cmc/cmc/deque/ext/code.h b/src/cmc/cmc/deque/ext/code.h
index 8e7f743..dc4a1b5 100644
--- a/src/cmc/cmc/deque/ext/code.h
+++ b/src/cmc/cmc/deque/ext/code.h
@@ -28,7 +28,7 @@
* The part 'INIT' gives a new way of initializing a collection. The collection
* struct is not heap allocated, only its internal structure (nodes, buffers).
*/
-#ifdef CMC_EXT_DEQUE_INIT
+#ifdef CMC_EXT_INIT
struct SNAME CMC_(PFX, _init)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val)
{
@@ -83,14 +83,14 @@ void CMC_(PFX, _release)(struct SNAME _deque_)
_deque_.alloc->free(_deque_.buffer);
}
-#endif /* CMC_EXT_DEQUE_INIT */
+#endif /* CMC_EXT_INIT */
/**
* ITER
*
* Deque bi-directional iterator.
*/
-#ifdef CMC_EXT_DEQUE_ITER
+#ifdef CMC_EXT_ITER
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target)
{
@@ -302,14 +302,14 @@ size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter)
return iter->index;
}
-#endif /* CMC_EXT_DEQUE_ITER */
+#endif /* CMC_EXT_ITER */
/**
* STR
*
* Print helper functions.
*/
-#ifdef CMC_EXT_DEQUE_STR
+#ifdef CMC_EXT_STR
bool CMC_(PFX, _to_string)(struct SNAME *_deque_, FILE *fptr)
{
@@ -351,4 +351,4 @@ bool CMC_(PFX, _print)(struct SNAME *_deque_, FILE *fptr, const char *start, con
return true;
}
-#endif /* CMC_EXT_DEQUE_STR */
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/deque/ext/header.h b/src/cmc/cmc/deque/ext/header.h
index 51cdea8..ce53a2b 100644
--- a/src/cmc/cmc/deque/ext/header.h
+++ b/src/cmc/cmc/deque/ext/header.h
@@ -28,21 +28,21 @@
* The part 'INIT' gives a new way of initializing a collection. The collection
* struct is not heap allocated, only its internal structure (nodes, buffers).
*/
-#ifdef CMC_EXT_DEQUE_INIT
+#ifdef CMC_EXT_INIT
struct SNAME CMC_(PFX, _init)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val);
struct SNAME CMC_(PFX, _init_custom)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val,
struct CMC_ALLOC_NODE_NAME *alloc, struct CMC_CALLBACKS_NAME *callbacks);
void CMC_(PFX, _release)(struct SNAME _deque_);
-#endif /* CMC_EXT_DEQUE_INIT */
+#endif /* CMC_EXT_INIT */
/**
* ITER
*
* Deque bi-directional iterator.
*/
-#ifdef CMC_EXT_DEQUE_ITER
+#ifdef CMC_EXT_ITER
/* Iterator Initialization */
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target);
@@ -63,18 +63,18 @@ V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter);
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter);
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
-#endif /* CMC_EXT_DEQUE_ITER */
+#endif /* CMC_EXT_ITER */
/**
* STR
*
* Print helper functions.
*/
-#ifdef CMC_EXT_DEQUE_STR
+#ifdef CMC_EXT_STR
/* Debug prints the struct to fptr */
bool CMC_(PFX, _to_string)(struct SNAME *_deque_, FILE *fptr);
/* Prints each item in the deque as an array */
bool CMC_(PFX, _print)(struct SNAME *_deque_, FILE *fptr, const char *start, const char *separator, const char *end);
-#endif /* CMC_EXT_DEQUE_STR */
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/deque/ext/struct.h b/src/cmc/cmc/deque/ext/struct.h
index 4be767d..09e4228 100644
--- a/src/cmc/cmc/deque/ext/struct.h
+++ b/src/cmc/cmc/deque/ext/struct.h
@@ -27,7 +27,7 @@
*
* Deque bi-directional iterator.
*/
-#ifdef CMC_EXT_DEQUE_ITER
+#ifdef CMC_EXT_ITER
/* Deque Iterator */
struct CMC_DEF_ITER(SNAME)
@@ -44,4 +44,4 @@ struct CMC_DEF_ITER(SNAME)
bool end;
};
-#endif /* CMC_EXT_DEQUE_ITER */
+#endif /* CMC_EXT_ITER */
diff --git a/src/cmc/cmc/hashbidimap/ext/code.h b/src/cmc/cmc/hashbidimap/ext/code.h
index 9ae2654..54ab5cb 100644
--- a/src/cmc/cmc/hashbidimap/ext/code.h
+++ b/src/cmc/cmc/hashbidimap/ext/code.h
@@ -28,7 +28,7 @@
* The part 'INIT' gives a new way of initializing a collection. The collection
* struct is not heap allocated, only its internal structure (nodes, buffers).
*/
-#ifdef CMC_EXT_HASHBIDIMAP_INIT
+#ifdef CMC_EXT_INIT
struct SNAME CMC_(PFX, _init)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key,
struct CMC_DEF_FVAL(SNAME) * f_val)
@@ -84,14 +84,14 @@ void CMC_(PFX, _release)(struct SNAME _map_)
_map_.alloc->free(_map_.buffer);
}
-#endif /* CMC_EXT_HASHBIDIMAP_INIT */
+#endif /* CMC_EXT_INIT */
/**
* ITER
*
* Hashbidimap bi-directional iterator.
*/
-#ifdef CMC_EXT_HASHBIDIMAP_ITER
+#ifdef CMC_EXT_ITER
struct CMC_DEF_ITER(SNAME) * CMC_(PFX, _iter_new)(struct SNAME *target)
{
@@ -320,14 +320,14 @@ size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter)
return iter->index;
}
-#endif /* CMC_EXT_HASHBIDIMAP_ITER */
+#endif /* CMC_EXT_ITER */
/**
* STR
*
* Print helper functions.
*/
-#ifdef CMC_EXT_HASHBIDIMAP_STR
+#ifdef CMC_EXT_STR
bool CMC_(PFX, _to_string)(struct SNAME *_map_, FILE *fptr)
{
@@ -390,4 +390,4 @@ bool CMC_(PFX, _print)(struct SNAME *_map_, FILE *fptr, const char *start, const
return true;
}
-#endif /* CMC_EXT_HASHBIDIMAP_STR */
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/hashbidimap/ext/header.h b/src/cmc/cmc/hashbidimap/ext/header.h
index f924208..2cbd29e 100644
--- a/src/cmc/cmc/hashbidimap/ext/header.h
+++ b/src/cmc/cmc/hashbidimap/ext/header.h
@@ -28,7 +28,7 @@
* The part 'INIT' gives a new way of initializing a collection. The collection
* struct is not heap allocated, only its internal structure (nodes, buffers).
*/
-#ifdef CMC_EXT_HASHBIDIMAP_INIT
+#ifdef CMC_EXT_INIT
struct SNAME CMC_(PFX, _init)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key,
struct CMC_DEF_FVAL(SNAME) * f_val);
@@ -37,14 +37,14 @@ struct SNAME CMC_(PFX, _init_custom)(size_t capacity, double load, struct CMC_DE
struct CMC_CALLBACKS_NAME *callbacks);
void CMC_(PFX, _release)(struct SNAME _map_);
-#endif /* CMC_EXT_HASHBIDIMAP_INIT */
+#endif /* CMC_EXT_INIT */
/**
* ITER
*
* Hashbidimap bi-directional iterator.
*/
-#ifdef CMC_EXT_HASHBIDIMAP_ITER
+#ifdef CMC_EXT_ITER
/* Iterator Functions */
/* Iterator Allocation and Deallocation */
@@ -68,14 +68,14 @@ K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter);
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter);
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
-#endif /* CMC_EXT_HASHBIDIMAP_ITER */
+#endif /* CMC_EXT_ITER */
/**
* STR
*
* Print helper functions.
*/
-#ifdef CMC_EXT_HASHBIDIMAP_STR
+#ifdef CMC_EXT_STR
/* Debug prints the struct to fptr */
bool CMC_(PFX, _to_string)(struct SNAME *_map_, FILE *fptr);
@@ -83,4 +83,4 @@ bool CMC_(PFX, _to_string)(struct SNAME *_map_, FILE *fptr);
bool CMC_(PFX, _print)(struct SNAME *_map_, FILE *fptr, const char *start, const char *separator, const char *end,
const char *key_val_sep);
-#endif /* CMC_EXT_HASHBIDIMAP_STR */
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/hashbidimap/ext/struct.h b/src/cmc/cmc/hashbidimap/ext/struct.h
index 557347e..162360f 100644
--- a/src/cmc/cmc/hashbidimap/ext/struct.h
+++ b/src/cmc/cmc/hashbidimap/ext/struct.h
@@ -27,7 +27,7 @@
*
* Hashbidimap bi-directional iterator.
*/
-#ifdef CMC_EXT_HASHBIDIMAP_ITER
+#ifdef CMC_EXT_ITER
/* HashBidiMap Iterator */
struct CMC_DEF_ITER(SNAME)
@@ -48,4 +48,4 @@ struct CMC_DEF_ITER(SNAME)
bool end;
};
-#endif /* CMC_EXT_HASHBIDIMAP_ITER */
+#endif /* CMC_EXT_ITER */
diff --git a/src/cmc/cmc/hashmap/ext/code.h b/src/cmc/cmc/hashmap/ext/code.h
index c3f7efb..976180a 100644
--- a/src/cmc/cmc/hashmap/ext/code.h
+++ b/src/cmc/cmc/hashmap/ext/code.h
@@ -28,7 +28,7 @@
* The part 'INIT' gives a new way of initializing a collection. The collection
* struct is not heap allocated, only its internal structure (nodes, buffers).
*/
-#ifdef CMC_EXT_HASHMAP_INIT
+#ifdef CMC_EXT_INIT
struct SNAME CMC_(PFX, _init)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key,
struct CMC_DEF_FVAL(SNAME) * f_val)
@@ -97,14 +97,14 @@ void CMC_(PFX, _release)(struct SNAME _map_)
_map_.alloc->free(_map_.buffer);
}
-#endif /* CMC_EXT_HASHMAP_INIT */
+#endif /* CMC_EXT_INIT */
/**
* ITER
*
* Hashmap bi-directional iterator.
*/
-#ifdef CMC_EXT_HASHMAP_ITER
+#ifdef CMC_EXT_ITER
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target)
{
@@ -367,14 +367,14 @@ size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter)
return iter->index;
}
-#endif /* CMC_EXT_HASHMAP_ITER */
+#endif /* CMC_EXT_ITER */
/**
* STR
*
* Print helper functions.
*/
-#ifdef CMC_EXT_HASHMAP_STR
+#ifdef CMC_EXT_STR
bool CMC_(PFX, _to_string)(struct SNAME *_map_, FILE *fptr)
{
@@ -435,4 +435,4 @@ bool CMC_(PFX, _print)(struct SNAME *_map_, FILE *fptr, const char *start, const
return true;
}
-#endif /* CMC_EXT_HASHMAP_STR */
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/hashmap/ext/header.h b/src/cmc/cmc/hashmap/ext/header.h
index 8f4d34c..ab15d5c 100644
--- a/src/cmc/cmc/hashmap/ext/header.h
+++ b/src/cmc/cmc/hashmap/ext/header.h
@@ -28,7 +28,7 @@
* The part 'INIT' gives a new way of initializing a collection. The collection
* struct is not heap allocated, only its internal structure (nodes, buffers).
*/
-#ifdef CMC_EXT_HASHMAP_INIT
+#ifdef CMC_EXT_INIT
struct SNAME CMC_(PFX, _init)(size_t capacity, double load, struct CMC_DEF_FKEY(SNAME) * f_key,
struct CMC_DEF_FVAL(SNAME) * f_val);
@@ -37,14 +37,14 @@ struct SNAME CMC_(PFX, _init_custom)(size_t capacity, double load, struct CMC_DE
struct CMC_CALLBACKS_NAME *callbacks);
void CMC_(PFX, _release)(struct SNAME _map_);
-#endif /* CMC_EXT_HASHMAP_INIT */
+#endif /* CMC_EXT_INIT */
/**
* ITER
*
* Hashmap bi-directional iterator.
*/
-#ifdef CMC_EXT_HASHMAP_ITER
+#ifdef CMC_EXT_ITER
/* Iterator Initialization */
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target);
@@ -66,17 +66,17 @@ V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter);
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter);
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
-#endif /* CMC_EXT_HASHMAP_ITER */
+#endif /* CMC_EXT_ITER */
/**
* STR
*
* Print helper functions.
*/
-#ifdef CMC_EXT_HASHMAP_STR
+#ifdef CMC_EXT_STR
bool CMC_(PFX, _to_string)(struct SNAME *_map_, FILE *fptr);
bool CMC_(PFX, _print)(struct SNAME *_map_, FILE *fptr, const char *start, const char *separator, const char *end,
const char *key_val_sep);
-#endif /* CMC_EXT_HASHMAP_STR */
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/hashmap/ext/struct.h b/src/cmc/cmc/hashmap/ext/struct.h
index 926b225..b14c380 100644
--- a/src/cmc/cmc/hashmap/ext/struct.h
+++ b/src/cmc/cmc/hashmap/ext/struct.h
@@ -27,7 +27,7 @@
*
* Hashmap bi-directional iterator.
*/
-#ifdef CMC_EXT_HASHMAP_ITER
+#ifdef CMC_EXT_ITER
/* HashMap Iterator */
struct CMC_DEF_ITER(SNAME)
@@ -48,4 +48,4 @@ struct CMC_DEF_ITER(SNAME)
bool end;
};
-#endif /* CMC_EXT_HASHMAP_ITER */
+#endif /* CMC_EXT_ITER */
diff --git a/src/cmc/cmc/hashmultimap/ext/code.h b/src/cmc/cmc/hashmultimap/ext/code.h
index 4ba8efa..2ed798f 100644
--- a/src/cmc/cmc/hashmultimap/ext/code.h
+++ b/src/cmc/cmc/hashmultimap/ext/code.h
@@ -28,16 +28,16 @@
* The part 'INIT' gives a new way of initializing a collection. The collection
* struct is not heap allocated, only its internal structure (nodes, buffers).
*/
-#ifdef CMC_EXT_HASHMULTIMAP_INIT
+#ifdef CMC_EXT_INIT
-#endif /* CMC_EXT_HASHMULTIMAP_INIT */
+#endif /* CMC_EXT_INIT */
/**
* ITER
*
* List bi-directional iterator.
*/
-#ifdef CMC_EXT_HASHMULTIMAP_ITER
+#ifdef CMC_EXT_ITER
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target)
{
@@ -322,14 +322,14 @@ size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter)
return iter->index;
}
-#endif /* CMC_EXT_HASHMULTIMAP_ITER */
+#endif /* CMC_EXT_ITER */
/**
* STR
*
* Print helper functions.
*/
-#ifdef CMC_EXT_HASHMULTIMAP_STR
+#ifdef CMC_EXT_STR
bool CMC_(PFX, _to_string)(struct SNAME *_map_, FILE *fptr)
{
@@ -394,4 +394,4 @@ bool CMC_(PFX, _print)(struct SNAME *_map_, FILE *fptr, const char *start, const
return true;
}
-#endif /* CMC_EXT_HASHMULTIMAP_STR */
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/hashmultimap/ext/header.h b/src/cmc/cmc/hashmultimap/ext/header.h
index 4bf1c00..99d02c2 100644
--- a/src/cmc/cmc/hashmultimap/ext/header.h
+++ b/src/cmc/cmc/hashmultimap/ext/header.h
@@ -28,16 +28,16 @@
* The part 'INIT' gives a new way of initializing a collection. The collection
* struct is not heap allocated, only its internal structure (nodes, buffers).
*/
-#ifdef CMC_EXT_HASHMULTIMAP_INIT
+#ifdef CMC_EXT_INIT
-#endif /* CMC_EXT_HASHMULTIMAP_INIT */
+#endif /* CMC_EXT_INIT */
/**
* ITER
*
* Hashmultimap bi-directional iterator.
*/
-#ifdef CMC_EXT_HASHMULTIMAP_ITER
+#ifdef CMC_EXT_ITER
/* Iterator Initialization */
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target);
@@ -59,17 +59,17 @@ V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter);
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter);
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
-#endif /* CMC_EXT_HASHMULTIMAP_ITER */
+#endif /* CMC_EXT_ITER */
/**
* STR
*
* Print helper functions.
*/
-#ifdef CMC_EXT_HASHMULTIMAP_STR
+#ifdef CMC_EXT_STR
bool CMC_(PFX, _to_string)(struct SNAME *_map_, FILE *fptr);
bool CMC_(PFX, _print)(struct SNAME *_map_, FILE *fptr, const char *start, const char *separator, const char *end,
const char *key_val_sep);
-#endif /* CMC_EXT_HASHMULTIMAP_STR */
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/hashmultimap/ext/struct.h b/src/cmc/cmc/hashmultimap/ext/struct.h
index cf15af2..6b20c2a 100644
--- a/src/cmc/cmc/hashmultimap/ext/struct.h
+++ b/src/cmc/cmc/hashmultimap/ext/struct.h
@@ -27,7 +27,7 @@
*
* Hashmultimap bi-directional iterator.
*/
-#ifdef CMC_EXT_HASHMULTIMAP_ITER
+#ifdef CMC_EXT_ITER
/* HashMultiMap Iterator */
struct CMC_DEF_ITER(SNAME)
@@ -50,4 +50,4 @@ struct CMC_DEF_ITER(SNAME)
bool end;
};
-#endif /* CMC_EXT_HASHMULTIMAP_ITER */
+#endif /* CMC_EXT_ITER */
diff --git a/src/cmc/cmc/hashmultiset/ext/code.h b/src/cmc/cmc/hashmultiset/ext/code.h
index 4016523..945679d 100644
--- a/src/cmc/cmc/hashmultiset/ext/code.h
+++ b/src/cmc/cmc/hashmultiset/ext/code.h
@@ -28,16 +28,16 @@
* The part 'INIT' gives a new way of initializing a collection. The collection
* struct is not heap allocated, only its internal structure (nodes, buffers).
*/
-#ifdef CMC_EXT_HASHMULTISET_INIT
+#ifdef CMC_EXT_INIT
-#endif /* CMC_EXT_HASHMULTISET_INIT */
+#endif /* CMC_EXT_INIT */
/**
* ITER
*
* List bi-directional iterator.
*/
-#ifdef CMC_EXT_HASHMULTISET_ITER
+#ifdef CMC_EXT_ITER
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target)
{
@@ -292,14 +292,14 @@ size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter)
return iter->index;
}
-#endif /* CMC_EXT_HASHMULTISET_ITER */
+#endif /* CMC_EXT_ITER */
/**
* SETF
*
* Set functions
*/
-#ifdef CMC_EXT_HASHMULTISET_SETF
+#ifdef CMC_EXT_SETF
struct SNAME *CMC_(PFX, _union)(struct SNAME *_set1_, struct SNAME *_set2_)
{
@@ -550,14 +550,14 @@ bool CMC_(PFX, _is_disjointset)(struct SNAME *_set1_, struct SNAME *_set2_)
return true;
}
-#endif /* CMC_EXT_HASHMULTISET_SETF */
+#endif /* CMC_EXT_SETF */
/**
* STR
*
* Print helper functions.
*/
-#ifdef CMC_EXT_HASHMULTISET_STR
+#ifdef CMC_EXT_STR
bool CMC_(PFX, _to_string)(struct SNAME *_set_, FILE *fptr)
{
@@ -618,4 +618,4 @@ bool CMC_(PFX, _print)(struct SNAME *_set_, FILE *fptr, const char *start, const
return true;
}
-#endif /* CMC_EXT_HASHMULTISET_STR */
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/hashmultiset/ext/header.h b/src/cmc/cmc/hashmultiset/ext/header.h
index 82670c8..b916b8a 100644
--- a/src/cmc/cmc/hashmultiset/ext/header.h
+++ b/src/cmc/cmc/hashmultiset/ext/header.h
@@ -28,16 +28,16 @@
* The part 'INIT' gives a new way of initializing a collection. The collection
* struct is not heap allocated, only its internal structure (nodes, buffers).
*/
-#ifdef CMC_EXT_HASHMULTISET_INIT
+#ifdef CMC_EXT_INIT
-#endif /* CMC_EXT_HASHMULTISET_INIT */
+#endif /* CMC_EXT_INIT */
/**
* ITER
*
* List bi-directional iterator.
*/
-#ifdef CMC_EXT_HASHMULTISET_ITER
+#ifdef CMC_EXT_ITER
/* Iterator Initialization */
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target);
@@ -58,14 +58,14 @@ V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter);
size_t CMC_(PFX, _iter_multiplicity)(struct CMC_DEF_ITER(SNAME) * iter);
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
-#endif /* CMC_EXT_HASHMULTISET_ITER */
+#endif /* CMC_EXT_ITER */
/**
* SETF
*
* Set functions
*/
-#ifdef CMC_EXT_HASHMULTISET_SETF
+#ifdef CMC_EXT_SETF
/* Set Operations */
struct SNAME *CMC_(PFX, _union)(struct SNAME *_set1_, struct SNAME *_set2_);
@@ -79,17 +79,17 @@ bool CMC_(PFX, _is_proper_subset)(struct SNAME *_set1_, struct SNAME *_set2_);
bool CMC_(PFX, _is_proper_superset)(struct SNAME *_set1_, struct SNAME *_set2_);
bool CMC_(PFX, _is_disjointset)(struct SNAME *_set1_, struct SNAME *_set2_);
-#endif /* CMC_EXT_HASHMULTISET_SETF */
+#endif /* CMC_EXT_SETF */
/**
* STR
*
* Print helper functions.
*/
-#ifdef CMC_EXT_HASHMULTISET_STR
+#ifdef CMC_EXT_STR
bool CMC_(PFX, _to_string)(struct SNAME *_set_, FILE *fptr);
bool CMC_(PFX, _print)(struct SNAME *_set_, FILE *fptr, const char *start, const char *separator, const char *end,
const char *key_val_sep);
-#endif /* CMC_EXT_HASHMULTISET_STR */
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/hashmultiset/ext/struct.h b/src/cmc/cmc/hashmultiset/ext/struct.h
index 915c7a6..3dddd51 100644
--- a/src/cmc/cmc/hashmultiset/ext/struct.h
+++ b/src/cmc/cmc/hashmultiset/ext/struct.h
@@ -27,7 +27,7 @@
*
* Hashmultiset bi-directional iterator.
*/
-#ifdef CMC_EXT_HASHMULTISET_ITER
+#ifdef CMC_EXT_ITER
/* HashMultiSet Iterator */
struct CMC_DEF_ITER(SNAME)
@@ -54,4 +54,4 @@ struct CMC_DEF_ITER(SNAME)
bool end;
};
-#endif /* CMC_EXT_HASHMULTISET_ITER */
+#endif /* CMC_EXT_ITER */
diff --git a/src/cmc/cmc/hashset/ext/code.h b/src/cmc/cmc/hashset/ext/code.h
index 62b9508..6a839db 100644
--- a/src/cmc/cmc/hashset/ext/code.h
+++ b/src/cmc/cmc/hashset/ext/code.h
@@ -28,16 +28,16 @@
* The part 'INIT' gives a new way of initializing a collection. The collection
* struct is not heap allocated, only its internal structure (nodes, buffers).
*/
-#ifdef CMC_EXT_HASHSET_INIT
+#ifdef CMC_EXT_INIT
-#endif /* CMC_EXT_HASHSET_INIT */
+#endif /* CMC_EXT_INIT */
/**
* ITER
*
* Hashset bi-directional iterator.
*/
-#ifdef CMC_EXT_HASHSET_ITER
+#ifdef CMC_EXT_ITER
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target)
{
@@ -284,14 +284,14 @@ size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter)
return iter->index;
}
-#endif /* CMC_EXT_HASHSET_ITER */
+#endif /* CMC_EXT_ITER */
/**
* SETF
*
* Set functions
*/
-#ifdef CMC_EXT_HASHSET_SETF
+#ifdef CMC_EXT_SETF
struct SNAME *CMC_(PFX, _union)(struct SNAME *_set1_, struct SNAME *_set2_)
{
@@ -527,14 +527,14 @@ bool CMC_(PFX, _is_disjointset)(struct SNAME *_set1_, struct SNAME *_set2_)
return true;
}
-#endif /* CMC_EXT_HASHSET_SETF */
+#endif /* CMC_EXT_SETF */
/**
* STR
*
* Print helper functions.
*/
-#ifdef CMC_EXT_HASHSET_STR
+#ifdef CMC_EXT_STR
bool CMC_(PFX, _to_string)(struct SNAME *_set_, FILE *fptr)
{
@@ -588,4 +588,4 @@ bool CMC_(PFX, _print)(struct SNAME *_set_, FILE *fptr, const char *start, const
return true;
}
-#endif /* CMC_EXT_HASHSET_STR */
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/hashset/ext/header.h b/src/cmc/cmc/hashset/ext/header.h
index 6a0b694..35075b6 100644
--- a/src/cmc/cmc/hashset/ext/header.h
+++ b/src/cmc/cmc/hashset/ext/header.h
@@ -28,16 +28,16 @@
* The part 'INIT' gives a new way of initializing a collection. The collection
* struct is not heap allocated, only its internal structure (nodes, buffers).
*/
-#ifdef CMC_EXT_HASHSET_INIT
+#ifdef CMC_EXT_INIT
-#endif /* CMC_EXT_HASHSET_INIT */
+#endif /* CMC_EXT_INIT */
/**
* ITER
*
* List bi-directional iterator.
*/
-#ifdef CMC_EXT_HASHSET_ITER
+#ifdef CMC_EXT_ITER
/* Iterator Initialization */
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target);
@@ -57,14 +57,14 @@ bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index);
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter);
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
-#endif /* CMC_EXT_HASHSET_ITER */
+#endif /* CMC_EXT_ITER */
/**
* SETF
*
* Set functions
*/
-#ifdef CMC_EXT_HASHSET_SETF
+#ifdef CMC_EXT_SETF
/* Set Operations */
struct SNAME *CMC_(PFX, _union)(struct SNAME *_set1_, struct SNAME *_set2_);
@@ -77,16 +77,16 @@ bool CMC_(PFX, _is_proper_subset)(struct SNAME *_set1_, struct SNAME *_set2_);
bool CMC_(PFX, _is_proper_superset)(struct SNAME *_set1_, struct SNAME *_set2_);
bool CMC_(PFX, _is_disjointset)(struct SNAME *_set1_, struct SNAME *_set2_);
-#endif /* CMC_EXT_HASHSET_SETF */
+#endif /* CMC_EXT_SETF */
/**
* STR
*
* Print helper functions.
*/
-#ifdef CMC_EXT_HASHSET_STR
+#ifdef CMC_EXT_STR
bool CMC_(PFX, _to_string)(struct SNAME *_set_, FILE *fptr);
bool CMC_(PFX, _print)(struct SNAME *_set_, FILE *fptr, const char *start, const char *separator, const char *end);
-#endif /* CMC_EXT_HASHSET_STR */
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/hashset/ext/struct.h b/src/cmc/cmc/hashset/ext/struct.h
index 53e6c56..d675b9b 100644
--- a/src/cmc/cmc/hashset/ext/struct.h
+++ b/src/cmc/cmc/hashset/ext/struct.h
@@ -27,7 +27,7 @@
*
* Hashset bi-directional iterator.
*/
-#ifdef CMC_EXT_HASHSET_ITER
+#ifdef CMC_EXT_ITER
/* HashSet Iterator */
struct CMC_DEF_ITER(SNAME)
@@ -48,4 +48,4 @@ struct CMC_DEF_ITER(SNAME)
bool end;
};
-#endif /* CMC_EXT_HASHSET_ITER */
+#endif /* CMC_EXT_ITER */
diff --git a/src/cmc/cmc/heap/ext/code.h b/src/cmc/cmc/heap/ext/code.h
index 5235aaf..ccb6aca 100644
--- a/src/cmc/cmc/heap/ext/code.h
+++ b/src/cmc/cmc/heap/ext/code.h
@@ -28,16 +28,16 @@
* The part 'INIT' gives a new way of initializing a collection. The collection
* struct is not heap allocated, only its internal structure (nodes, buffers).
*/
-#ifdef CMC_EXT_HEAP_INIT
+#ifdef CMC_EXT_INIT
-#endif /* CMC_EXT_HEAP_INIT */
+#endif /* CMC_EXT_INIT */
/**
* ITER
*
* Heap bi-directional iterator.
*/
-#ifdef CMC_EXT_HEAP_ITER
+#ifdef CMC_EXT_ITER
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target)
{
@@ -215,14 +215,14 @@ size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter)
return iter->cursor;
}
-#endif /* CMC_EXT_HEAP_ITER */
+#endif /* CMC_EXT_ITER */
/**
* STR
*
* Print helper functions.
*/
-#ifdef CMC_EXT_HEAP_STR
+#ifdef CMC_EXT_STR
bool CMC_(PFX, _to_string)(struct SNAME *_heap_, FILE *fptr)
{
@@ -262,4 +262,4 @@ bool CMC_(PFX, _print)(struct SNAME *_heap_, FILE *fptr, const char *start, cons
return true;
}
-#endif /* CMC_EXT_HEAP_STR */
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/heap/ext/header.h b/src/cmc/cmc/heap/ext/header.h
index 5c69ee7..51c6afa 100644
--- a/src/cmc/cmc/heap/ext/header.h
+++ b/src/cmc/cmc/heap/ext/header.h
@@ -28,16 +28,16 @@
* The part 'INIT' gives a new way of initializing a collection. The collection
* struct is not heap allocated, only its internal structure (nodes, buffers).
*/
-#ifdef CMC_EXT_HEAP_INIT
+#ifdef CMC_EXT_INIT
-#endif /* CMC_EXT_HEAP_INIT */
+#endif /* CMC_EXT_INIT */
/**
* ITER
*
* Heap bi-directional iterator.
*/
-#ifdef CMC_EXT_HEAP_ITER
+#ifdef CMC_EXT_ITER
/* Iterator Initialization */
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target);
@@ -57,16 +57,16 @@ bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index);
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter);
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
-#endif /* CMC_EXT_HEAP_ITER */
+#endif /* CMC_EXT_ITER */
/**
* STR
*
* Print helper functions.
*/
-#ifdef CMC_EXT_HEAP_STR
+#ifdef CMC_EXT_STR
bool CMC_(PFX, _to_string)(struct SNAME *_heap_, FILE *fptr);
bool CMC_(PFX, _print)(struct SNAME *_heap_, FILE *fptr, const char *start, const char *separator, const char *end);
-#endif /* CMC_EXT_HEAP_STR */
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/heap/ext/struct.h b/src/cmc/cmc/heap/ext/struct.h
index 8433eba..b3eaf84 100644
--- a/src/cmc/cmc/heap/ext/struct.h
+++ b/src/cmc/cmc/heap/ext/struct.h
@@ -27,7 +27,7 @@
*
* Heap bi-directional iterator.
*/
-#ifdef CMC_EXT_HEAP_ITER
+#ifdef CMC_EXT_ITER
/* Heap Iterator */
struct CMC_DEF_ITER(SNAME)
@@ -42,4 +42,4 @@ struct CMC_DEF_ITER(SNAME)
bool end;
};
-#endif /* CMC_EXT_HEAP_ITER */
+#endif /* CMC_EXT_ITER */
diff --git a/src/cmc/cmc/intervalheap/ext/code.h b/src/cmc/cmc/intervalheap/ext/code.h
index e513abe..67ea111 100644
--- a/src/cmc/cmc/intervalheap/ext/code.h
+++ b/src/cmc/cmc/intervalheap/ext/code.h
@@ -28,9 +28,9 @@
* The part 'INIT' gives a new way of initializing a collection. The collection
* struct is not heap allocated, only its internal structure (nodes, buffers).
*/
-#ifdef CMC_EXT_INTERVALHEAP_INIT
+#ifdef CMC_EXT_INIT
-#endif /* CMC_EXT_INTERVALHEAP_INIT */
+#endif /* CMC_EXT_INIT */
/**
* ITER
@@ -39,7 +39,7 @@
*
* TODO allow creation of iterators exclusively for min or max heap
*/
-#ifdef CMC_EXT_INTERVALHEAP_ITER
+#ifdef CMC_EXT_ITER
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target)
{
@@ -217,14 +217,14 @@ size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter)
return iter->cursor;
}
-#endif /* CMC_EXT_INTERVALHEAP_ITER */
+#endif /* CMC_EXT_ITER */
/**
* STR
*
* Print helper functions.
*/
-#ifdef CMC_EXT_INTERVALHEAP_STR
+#ifdef CMC_EXT_STR
bool CMC_(PFX, _to_string)(struct SNAME *_heap_, FILE *fptr)
{
@@ -263,4 +263,4 @@ bool CMC_(PFX, _print)(struct SNAME *_heap_, FILE *fptr, const char *start, cons
return true;
}
-#endif /* CMC_EXT_INTERVALHEAP_STR */
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/intervalheap/ext/header.h b/src/cmc/cmc/intervalheap/ext/header.h
index ae998e3..6c3b0fd 100644
--- a/src/cmc/cmc/intervalheap/ext/header.h
+++ b/src/cmc/cmc/intervalheap/ext/header.h
@@ -28,16 +28,16 @@
* The part 'INIT' gives a new way of initializing a collection. The collection
* struct is not heap allocated, only its internal structure (nodes, buffers).
*/
-#ifdef CMC_EXT_INTERVALHEAP_INIT
+#ifdef CMC_EXT_INIT
-#endif /* CMC_EXT_INTERVALHEAP_INIT */
+#endif /* CMC_EXT_INIT */
/**
* ITER
*
* List bi-directional iterator.
*/
-#ifdef CMC_EXT_INTERVALHEAP_ITER
+#ifdef CMC_EXT_ITER
/* IntervalHeap Iterator */
struct CMC_DEF_ITER(SNAME)
@@ -73,16 +73,16 @@ bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index);
V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter);
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
-#endif /* CMC_EXT_INTERVALHEAP_ITER */
+#endif /* CMC_EXT_ITER */
/**
* STR
*
* Print helper functions.
*/
-#ifdef CMC_EXT_INTERVALHEAP_STR
+#ifdef CMC_EXT_STR
bool CMC_(PFX, _to_string)(struct SNAME *_heap_, FILE *fptr);
bool CMC_(PFX, _print)(struct SNAME *_heap_, FILE *fptr, const char *start, const char *separator, const char *end);
-#endif /* CMC_EXT_INTERVALHEAP_STR */
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/linkedlist/code.h b/src/cmc/cmc/linkedlist/code.h
new file mode 100644
index 0000000..e37b882
--- /dev/null
+++ b/src/cmc/cmc/linkedlist/code.h
@@ -0,0 +1,528 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* Implementation Detail Functions */
+struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _impl_get_node)(struct SNAME *_list_, size_t index);
+struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _impl_new_node)(struct SNAME *_list_, V value);
+
+struct SNAME *CMC_(PFX, _new)(struct CMC_DEF_FVAL(SNAME) * f_val)
+{
+ return CMC_(PFX, _new_custom)(f_val, NULL, NULL);
+}
+
+struct SNAME *CMC_(PFX, _new_custom)(struct CMC_DEF_FVAL(SNAME) * f_val, struct CMC_ALLOC_NODE_NAME *alloc,
+ struct CMC_CALLBACKS_NAME *callbacks)
+{
+ CMC_CALLBACKS_MAYBE_UNUSED(callbacks);
+
+ if (!f_val)
+ return NULL;
+
+ if (!alloc)
+ alloc = &cmc_alloc_node_default;
+
+ struct SNAME *_list_ = alloc->malloc(sizeof(struct SNAME));
+
+ if (!_list_)
+ return NULL;
+
+ _list_->count = 0;
+ _list_->head = NULL;
+ _list_->tail = NULL;
+ _list_->flag = CMC_FLAG_OK;
+ _list_->f_val = f_val;
+ _list_->alloc = alloc;
+ CMC_CALLBACKS_ASSIGN(_list_, callbacks);
+
+ return _list_;
+}
+
+void CMC_(PFX, _clear)(struct SNAME *_list_)
+{
+ struct CMC_DEF_NODE(SNAME) *scan = _list_->head;
+
+ while (_list_->head != NULL)
+ {
+ _list_->head = _list_->head->next;
+
+ if (_list_->f_val->free)
+ {
+ _list_->f_val->free(scan->value);
+ }
+
+ _list_->alloc->free(scan);
+
+ scan = _list_->head;
+ }
+
+ _list_->count = 0;
+ _list_->head = NULL;
+ _list_->tail = NULL;
+ _list_->flag = CMC_FLAG_OK;
+}
+
+void CMC_(PFX, _free)(struct SNAME *_list_)
+{
+ CMC_(PFX, _clear)(_list_);
+
+ _list_->alloc->free(_list_);
+}
+
+void CMC_(PFX, _customize)(struct SNAME *_list_, struct CMC_ALLOC_NODE_NAME *alloc,
+ struct CMC_CALLBACKS_NAME *callbacks)
+{
+ CMC_CALLBACKS_MAYBE_UNUSED(callbacks);
+
+ if (!alloc)
+ _list_->alloc = &cmc_alloc_node_default;
+ else
+ _list_->alloc = alloc;
+
+ CMC_CALLBACKS_ASSIGN(_list_, callbacks);
+
+ _list_->flag = CMC_FLAG_OK;
+}
+
+bool CMC_(PFX, _push_front)(struct SNAME *_list_, V value)
+{
+ struct CMC_DEF_NODE(SNAME) *_node_ = CMC_(PFX, _impl_new_node)(_list_, value);
+
+ if (!_node_)
+ return false;
+
+ if (CMC_(PFX, _empty)(_list_))
+ {
+ _list_->head = _node_;
+ _list_->tail = _node_;
+ }
+ else
+ {
+ _node_->next = _list_->head;
+ _list_->head->prev = _node_;
+ _list_->head = _node_;
+ }
+
+ _list_->count++;
+ _list_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_list_, create);
+
+ return true;
+}
+
+bool CMC_(PFX, _push_at)(struct SNAME *_list_, V value, size_t index)
+{
+ if (index > _list_->count)
+ {
+ _list_->flag = CMC_FLAG_RANGE;
+ return false;
+ }
+
+ if (index == 0)
+ {
+ return CMC_(PFX, _push_front)(_list_, value);
+ }
+ else if (index == _list_->count)
+ {
+ return CMC_(PFX, _push_back)(_list_, value);
+ }
+
+ struct CMC_DEF_NODE(SNAME) *_node_ = CMC_(PFX, _impl_new_node)(_list_, value);
+
+ if (!_node_)
+ return false;
+
+ struct CMC_DEF_NODE(SNAME) *scan = CMC_(PFX, _impl_get_node)(_list_, index - 1);
+
+ _node_->next = scan->next;
+ _node_->prev = scan;
+ _node_->next->prev = _node_;
+ _node_->prev->next = _node_;
+
+ _list_->count++;
+ _list_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_list_, create);
+
+ return true;
+}
+
+bool CMC_(PFX, _push_back)(struct SNAME *_list_, V value)
+{
+ struct CMC_DEF_NODE(SNAME) *_node_ = CMC_(PFX, _impl_new_node)(_list_, value);
+
+ if (!_node_)
+ return false;
+
+ if (CMC_(PFX, _empty)(_list_))
+ {
+ _list_->head = _node_;
+ _list_->tail = _node_;
+ }
+ else
+ {
+ _node_->prev = _list_->tail;
+ _list_->tail->next = _node_;
+ _list_->tail = _node_;
+ }
+
+ _list_->count++;
+ _list_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_list_, create);
+
+ return true;
+}
+
+bool CMC_(PFX, _pop_front)(struct SNAME *_list_)
+{
+ if (CMC_(PFX, _empty)(_list_))
+ {
+ _list_->flag = CMC_FLAG_EMPTY;
+ return false;
+ }
+
+ struct CMC_DEF_NODE(SNAME) *_node_ = _list_->head;
+ _list_->head = _list_->head->next;
+
+ _list_->alloc->free(_node_);
+
+ if (_list_->head == NULL)
+ _list_->tail = NULL;
+ else
+ _list_->head->prev = NULL;
+
+ _list_->count--;
+ _list_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_list_, delete);
+
+ return true;
+}
+
+bool CMC_(PFX, _pop_at)(struct SNAME *_list_, size_t index)
+{
+ if (CMC_(PFX, _empty)(_list_))
+ {
+ _list_->flag = CMC_FLAG_EMPTY;
+ return false;
+ }
+
+ if (index >= _list_->count)
+ {
+ _list_->flag = CMC_FLAG_RANGE;
+ return false;
+ }
+
+ if (index == 0)
+ {
+ return CMC_(PFX, _pop_front)(_list_);
+ }
+ else if (index == _list_->count - 1)
+ {
+ return CMC_(PFX, _pop_back)(_list_);
+ }
+
+ struct CMC_DEF_NODE(SNAME) *_node_ = CMC_(PFX, _impl_get_node)(_list_, index);
+
+ if (!_node_)
+ return false;
+
+ _node_->next->prev = _node_->prev;
+ _node_->prev->next = _node_->next;
+
+ _list_->alloc->free(_node_);
+
+ _list_->count--;
+ _list_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_list_, delete);
+
+ return true;
+}
+
+bool CMC_(PFX, _pop_back)(struct SNAME *_list_)
+{
+ if (CMC_(PFX, _empty)(_list_))
+ {
+ _list_->flag = CMC_FLAG_EMPTY;
+ return false;
+ }
+
+ struct CMC_DEF_NODE(SNAME) *_node_ = _list_->tail;
+ _list_->tail = _list_->tail->prev;
+
+ _list_->alloc->free(_node_);
+
+ if (_list_->tail == NULL)
+ _list_->head = NULL;
+ else
+ _list_->tail->next = NULL;
+
+ _list_->count--;
+ _list_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_list_, delete);
+
+ return true;
+}
+
+V CMC_(PFX, _front)(struct SNAME *_list_)
+{
+ if (CMC_(PFX, _empty)(_list_))
+ {
+ _list_->flag = CMC_FLAG_EMPTY;
+ return (V){ 0 };
+ }
+
+ _list_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_list_, read);
+
+ return _list_->head->value;
+}
+
+V CMC_(PFX, _get)(struct SNAME *_list_, size_t index)
+{
+ if (CMC_(PFX, _empty)(_list_))
+ {
+ _list_->flag = CMC_FLAG_EMPTY;
+ return (V){ 0 };
+ }
+
+ if (index >= _list_->count)
+ {
+ _list_->flag = CMC_FLAG_RANGE;
+ return (V){ 0 };
+ }
+
+ struct CMC_DEF_NODE(SNAME) *scan = CMC_(PFX, _impl_get_node)(_list_, index);
+
+ if (scan == NULL)
+ return (V){ 0 };
+
+ CMC_CALLBACKS_CALL(_list_, read);
+
+ return scan->value;
+}
+
+V *CMC_(PFX, _get_ref)(struct SNAME *_list_, size_t index)
+{
+ if (CMC_(PFX, _empty)(_list_))
+ {
+ _list_->flag = CMC_FLAG_EMPTY;
+ return NULL;
+ }
+
+ if (index >= _list_->count)
+ {
+ _list_->flag = CMC_FLAG_RANGE;
+ return NULL;
+ }
+
+ struct CMC_DEF_NODE(SNAME) *scan = CMC_(PFX, _impl_get_node)(_list_, index);
+
+ if (scan == NULL)
+ return NULL;
+
+ CMC_CALLBACKS_CALL(_list_, read);
+
+ return &(scan->value);
+}
+
+V CMC_(PFX, _back)(struct SNAME *_list_)
+{
+ if (CMC_(PFX, _empty)(_list_))
+ {
+ _list_->flag = CMC_FLAG_EMPTY;
+ return (V){ 0 };
+ }
+
+ _list_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_list_, read);
+
+ return _list_->tail->value;
+}
+
+bool CMC_(PFX, _contains)(struct SNAME *_list_, V value)
+{
+ _list_->flag = CMC_FLAG_OK;
+
+ bool result = false;
+
+ struct CMC_DEF_NODE(SNAME) *scan = _list_->head;
+
+ while (scan != NULL)
+ {
+ if (_list_->f_val->cmp(scan->value, value) == 0)
+ {
+ result = true;
+ break;
+ }
+
+ scan = scan->next;
+ }
+
+ CMC_CALLBACKS_CALL(_list_, read);
+
+ return result;
+}
+
+bool CMC_(PFX, _empty)(struct SNAME *_list_)
+{
+ return _list_->count == 0;
+}
+
+size_t CMC_(PFX, _count)(struct SNAME *_list_)
+{
+ return _list_->count;
+}
+
+int CMC_(PFX, _flag)(struct SNAME *_list_)
+{
+ return _list_->flag;
+}
+
+struct SNAME *CMC_(PFX, _copy_of)(struct SNAME *_list_)
+{
+ struct SNAME *result = CMC_(PFX, _new_custom)(_list_->f_val, _list_->alloc, NULL);
+
+ if (!result)
+ return NULL;
+
+ CMC_CALLBACKS_ASSIGN(result, _list_->callbacks);
+
+ struct CMC_DEF_NODE(SNAME) *scan = _list_->head;
+
+ while (scan != NULL)
+ {
+ /* This allocation should never fail since it might not be */
+ /* possible to recover from it. That is why it isn't checked */
+ struct CMC_DEF_NODE(SNAME) * new_node;
+
+ if (_list_->f_val->cpy)
+ new_node = CMC_(PFX, _impl_new_node)(_list_, _list_->f_val->cpy(scan->value));
+ else
+ new_node = CMC_(PFX, _impl_new_node)(_list_, scan->value);
+
+ if (!result->head)
+ {
+ result->head = new_node;
+ result->tail = new_node;
+ }
+ else
+ {
+ new_node->prev = result->tail;
+ result->tail->next = new_node;
+ result->tail = new_node;
+ }
+
+ scan = scan->next;
+ }
+
+ result->count = _list_->count;
+
+ _list_->flag = CMC_FLAG_OK;
+
+ return result;
+}
+
+bool CMC_(PFX, _equals)(struct SNAME *_list1_, struct SNAME *_list2_)
+{
+ _list1_->flag = CMC_FLAG_OK;
+ _list2_->flag = CMC_FLAG_OK;
+
+ if (_list1_->count != _list2_->count)
+ return false;
+
+ struct CMC_DEF_NODE(SNAME) *scan1 = _list1_->head;
+ struct CMC_DEF_NODE(SNAME) *scan2 = _list2_->head;
+
+ while (scan1 != NULL && scan2 != NULL)
+ {
+ if (_list1_->f_val->cmp(scan1->value, scan2->value) != 0)
+ return false;
+
+ scan1 = scan1->next;
+ scan2 = scan2->next;
+ }
+
+ return true;
+}
+
+struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _impl_new_node)(struct SNAME *_list_, V value)
+{
+ struct CMC_DEF_NODE(SNAME) *_node_ = _list_->alloc->malloc(sizeof(struct CMC_DEF_NODE(SNAME)));
+
+ if (!_node_)
+ {
+ _list_->flag = CMC_FLAG_ALLOC;
+ return NULL;
+ }
+
+ _node_->value = value;
+ _node_->next = NULL;
+ _node_->prev = NULL;
+
+ return _node_;
+}
+
+struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _impl_get_node)(struct SNAME *_list_, size_t index)
+{
+ if (CMC_(PFX, _empty)(_list_))
+ {
+ _list_->flag = CMC_FLAG_EMPTY;
+ return NULL;
+ }
+
+ if (index >= _list_->count)
+ {
+ _list_->flag = CMC_FLAG_RANGE;
+ return NULL;
+ }
+
+ struct CMC_DEF_NODE(SNAME) *_node_ = NULL;
+
+ if (index <= _list_->count / 2)
+ {
+ _node_ = _list_->head;
+ for (size_t i = 0; i < index; i++)
+ {
+ _node_ = _node_->next;
+ }
+ }
+ else
+ {
+ _node_ = _list_->tail;
+ for (size_t i = _list_->count - 1; i > index; i--)
+ {
+ _node_ = _node_->prev;
+ }
+ }
+
+ _list_->flag = CMC_FLAG_OK;
+
+ return _node_;
+}
diff --git a/src/cmc/cmc/linkedlist/ext/code.h b/src/cmc/cmc/linkedlist/ext/code.h
new file mode 100644
index 0000000..b6eb0df
--- /dev/null
+++ b/src/cmc/cmc/linkedlist/ext/code.h
@@ -0,0 +1,494 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * INIT
+ *
+ * The part 'INIT' gives a new way of initializing a collection. The collection
+ * struct is not heap allocated, only its internal structure (nodes, buffers).
+ */
+#ifdef CMC_EXT_INIT
+
+#endif /* CMC_EXT_INIT */
+
+/**
+ * ITER
+ *
+ * List bi-directional iterator.
+ */
+#ifdef CMC_EXT_ITER
+
+struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target)
+{
+ struct CMC_DEF_ITER(SNAME) iter;
+
+ iter.target = target;
+ iter.cursor = target->head;
+ iter.index = 0;
+ iter.start = true;
+ iter.end = CMC_(PFX, _empty)(target);
+
+ return iter;
+}
+
+struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME *target)
+{
+ struct CMC_DEF_ITER(SNAME) iter;
+
+ iter.target = target;
+ iter.cursor = target->tail;
+ iter.index = 0;
+ iter.start = CMC_(PFX, _empty)(target);
+ iter.end = true;
+
+ if (!CMC_(PFX, _empty)(target))
+ iter.index = target->count - 1;
+
+ return iter;
+}
+
+bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ return CMC_(PFX, _empty)(iter->target) || iter->start;
+}
+
+bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ return CMC_(PFX, _empty)(iter->target) || iter->end;
+}
+
+bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ if (!CMC_(PFX, _empty)(iter->target))
+ {
+ iter->cursor = iter->target->head;
+ iter->index = 0;
+ iter->start = true;
+ iter->end = CMC_(PFX, _empty)(iter->target);
+
+ return true;
+ }
+
+ return false;
+}
+
+bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ if (!CMC_(PFX, _empty)(iter->target))
+ {
+ iter->cursor = iter->target->tail;
+ iter->index = iter->target->count - 1;
+ iter->start = CMC_(PFX, _empty)(iter->target);
+ iter->end = true;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ if (iter->end)
+ return false;
+
+ if (iter->cursor->next == NULL)
+ {
+ iter->end = true;
+ return false;
+ }
+
+ iter->start = CMC_(PFX, _empty)(iter->target);
+
+ iter->cursor = iter->cursor->next;
+ iter->index++;
+
+ return true;
+}
+
+bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ if (iter->start)
+ return false;
+
+ if (iter->cursor->prev == NULL)
+ {
+ iter->start = true;
+ return false;
+ }
+
+ iter->end = CMC_(PFX, _empty)(iter->target);
+
+ iter->cursor = iter->cursor->prev;
+ iter->index--;
+
+ return true;
+}
+
+/* Returns true only if the iterator moved */
+bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps)
+{
+ if (iter->end)
+ return false;
+
+ if (iter->cursor->next == NULL)
+ {
+ iter->end = true;
+ return false;
+ }
+
+ if (steps == 0 || iter->index + steps >= iter->target->count)
+ return false;
+
+ iter->start = CMC_(PFX, _empty)(iter->target);
+
+ iter->index += steps;
+
+ for (size_t i = 0; i < steps; i++)
+ iter->cursor = iter->cursor->next;
+
+ return true;
+}
+
+/* Returns true only if the iterator moved */
+bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps)
+{
+ if (iter->start)
+ return false;
+
+ if (iter->cursor->prev == NULL)
+ {
+ iter->start = true;
+ return false;
+ }
+
+ if (steps == 0 || iter->index < steps)
+ return false;
+
+ iter->end = CMC_(PFX, _empty)(iter->target);
+
+ iter->index -= steps;
+
+ for (size_t i = 0; i < steps; i++)
+ iter->cursor = iter->cursor->prev;
+
+ return true;
+}
+
+/* Returns true only if the iterator was able to be positioned at the */
+/* given index */
+bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index)
+{
+ if (index >= iter->target->count)
+ return false;
+
+ if (iter->index > index)
+ return CMC_(PFX, _iter_rewind)(iter, iter->index - index);
+ else if (iter->index < index)
+ return CMC_(PFX, _iter_advance)(iter, index - iter->index);
+
+ return true;
+}
+
+V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ if (CMC_(PFX, _empty)(iter->target))
+ return (V){ 0 };
+
+ return iter->cursor->value;
+}
+
+V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ if (CMC_(PFX, _empty)(iter->target))
+ return NULL;
+
+ return &(iter->cursor->value);
+}
+
+size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ return iter->index;
+}
+
+struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _iter_node)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ return iter->cursor;
+}
+
+#endif /* CMC_EXT_ITER */
+
+/**
+ * NODE
+ *
+ * Operations relative to a linkedlist node
+ */
+#ifdef CMC_EXT_NODE
+
+struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _new_node)(struct SNAME *_list_, V value)
+{
+ struct CMC_DEF_NODE(SNAME) *_node_ = _list_->alloc->malloc(sizeof(struct CMC_DEF_NODE(SNAME)));
+
+ if (!_node_)
+ {
+ _list_->flag = CMC_FLAG_ALLOC;
+ return NULL;
+ }
+
+ _node_->value = value;
+ _node_->next = NULL;
+ _node_->prev = NULL;
+
+ return _node_;
+}
+
+void CMC_(PFX, _free_node)(struct SNAME *_list_, struct CMC_DEF_NODE(SNAME) * _node_)
+{
+ _list_->alloc->free(_node_);
+}
+
+struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _head)(struct SNAME *_list_)
+{
+ return _list_->head;
+}
+
+struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _get_node)(struct SNAME *_list_, size_t index)
+{
+ if (CMC_(PFX, _empty)(_list_))
+ {
+ _list_->flag = CMC_FLAG_EMPTY;
+ return NULL;
+ }
+
+ if (index >= _list_->count)
+ {
+ _list_->flag = CMC_FLAG_RANGE;
+ return NULL;
+ }
+
+ struct CMC_DEF_NODE(SNAME) *_node_ = NULL;
+
+ if (index <= _list_->count / 2)
+ {
+ _node_ = _list_->head;
+ for (size_t i = 0; i < index; i++)
+ {
+ _node_ = _node_->next;
+ }
+ }
+ else
+ {
+ _node_ = _list_->tail;
+ for (size_t i = _list_->count - 1; i > index; i--)
+ {
+ _node_ = _node_->prev;
+ }
+ }
+
+ _list_->flag = CMC_FLAG_OK;
+
+ return _node_;
+}
+
+struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _tail)(struct SNAME *_list_)
+{
+ return _list_->tail;
+}
+
+bool CMC_(PFX, _add_next)(struct SNAME *_owner_, struct CMC_DEF_NODE(SNAME) * _node_, V value)
+{
+ struct CMC_DEF_NODE(SNAME) *new_node = CMC_(PFX, _new_node)(_owner_, value);
+
+ if (!new_node)
+ return false;
+
+ new_node->next = _node_->next;
+
+ if (_node_->next != NULL)
+ _node_->next->prev = new_node;
+ else
+ _owner_->tail = new_node;
+
+ new_node->prev = _node_;
+ _node_->next = new_node;
+
+ _owner_->count++;
+ _owner_->flag = CMC_FLAG_OK;
+
+ return true;
+}
+
+bool CMC_(PFX, _add_prev)(struct SNAME *_owner_, struct CMC_DEF_NODE(SNAME) * _node_, V value)
+{
+ struct CMC_DEF_NODE(SNAME) *new_node = CMC_(PFX, _new_node)(_owner_, value);
+
+ if (!new_node)
+ return false;
+
+ new_node->prev = _node_->prev;
+
+ if (_node_->prev != NULL)
+ _node_->prev->next = new_node;
+ else
+ _owner_->head = new_node;
+
+ new_node->next = _node_;
+ _node_->prev = new_node;
+
+ _owner_->count++;
+ _owner_->flag = CMC_FLAG_OK;
+
+ return true;
+}
+
+bool CMC_(PFX, _del_next)(struct SNAME *_owner_, struct CMC_DEF_NODE(SNAME) * _node_)
+{
+ if (_node_->next == NULL)
+ {
+ _owner_->flag = CMC_FLAG_INVALID;
+ return false;
+ }
+
+ struct CMC_DEF_NODE(SNAME) *tmp = _node_->next;
+
+ _node_->next = _node_->next->next;
+
+ if (tmp->next != NULL)
+ tmp->next->prev = _node_;
+ else
+ _owner_->tail = _node_;
+
+ _owner_->alloc->free(tmp);
+
+ _owner_->count--;
+ _owner_->flag = CMC_FLAG_OK;
+
+ return true;
+}
+
+bool CMC_(PFX, _del_curr)(struct SNAME *_owner_, struct CMC_DEF_NODE(SNAME) * _node_)
+{
+ if (_node_->prev != NULL)
+ _node_->prev->next = _node_->next;
+ else
+ _owner_->head = _node_->next;
+
+ if (_node_->next != NULL)
+ _node_->next->prev = _node_->prev;
+ else
+ _owner_->tail = _node_->prev;
+
+ _owner_->alloc->free(_node_);
+
+ _owner_->count--;
+ _owner_->flag = CMC_FLAG_OK;
+
+ return true;
+}
+
+bool CMC_(PFX, _del_prev)(struct SNAME *_owner_, struct CMC_DEF_NODE(SNAME) * _node_)
+{
+ if (_node_->prev == NULL)
+ {
+ _owner_->flag = CMC_FLAG_INVALID;
+ return false;
+ }
+
+ struct CMC_DEF_NODE(SNAME) *tmp = _node_->prev;
+
+ _node_->prev = _node_->prev->prev;
+
+ if (tmp->prev != NULL)
+ tmp->prev->next = _node_;
+ else
+ _owner_->head = _node_;
+
+ _owner_->alloc->free(tmp);
+
+ _owner_->count--;
+ _owner_->flag = CMC_FLAG_OK;
+
+ return true;
+}
+
+struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _next_node)(struct CMC_DEF_NODE(SNAME) * _node_)
+{
+ return _node_->next;
+}
+
+struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _prev_node)(struct CMC_DEF_NODE(SNAME) * _node_)
+{
+ return _node_->prev;
+}
+
+#endif /* CMC_EXT_NODE */
+
+/**
+ * STR
+ *
+ * Print helper functions.
+ */
+#ifdef CMC_EXT_STR
+
+bool CMC_(PFX, _to_string)(struct SNAME *_list_, FILE *fptr)
+{
+ struct SNAME *l_ = _list_;
+
+ return 0 <= fprintf(fptr,
+ "struct %s<%s> "
+ "at %p { "
+ "count:%" PRIuMAX ", "
+ "head:%p, "
+ "tail:%p, "
+ "flag:%d, "
+ "f_val:%p, "
+ "alloc:%p, "
+ "callbacks:%p }",
+ CMC_TO_STRING(SNAME), CMC_TO_STRING(V), l_, l_->count, l_->head, l_->tail, l_->flag, l_->f_val,
+ l_->alloc, CMC_CALLBACKS_GET(l_));
+}
+
+bool CMC_(PFX, _print)(struct SNAME *_list_, FILE *fptr, const char *start, const char *separator, const char *end)
+{
+ fprintf(fptr, "%s", start);
+
+ struct CMC_DEF_NODE(SNAME) *scan = _list_->head;
+
+ while (scan != NULL)
+ {
+ if (!_list_->f_val->str(fptr, scan->value))
+ return false;
+
+ scan = scan->next;
+
+ if (scan)
+ fprintf(fptr, "%s", separator);
+ }
+
+ fprintf(fptr, "%s", end);
+
+ return true;
+}
+
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/linkedlist/ext/header.h b/src/cmc/cmc/linkedlist/ext/header.h
new file mode 100644
index 0000000..abe52a7
--- /dev/null
+++ b/src/cmc/cmc/linkedlist/ext/header.h
@@ -0,0 +1,115 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * INIT
+ *
+ * The part 'INIT' gives a new way of initializing a collection. The collection
+ * struct is not heap allocated, only its internal structure (nodes, buffers).
+ */
+#ifdef CMC_EXT_INIT
+
+#endif /* CMC_EXT_INIT */
+
+/**
+ * ITER
+ *
+ * List bi-directional iterator.
+ */
+#ifdef CMC_EXT_ITER
+
+/* LinkedList Iterator */
+struct CMC_DEF_ITER(SNAME)
+{
+ /* Target Linked List */
+ struct SNAME *target;
+ /* Cursor's current node */
+ struct CMC_DEF_NODE(SNAME) * cursor;
+ /* Keeps track of relative index to the iteration of elements */
+ size_t index;
+ /* If the iterator has reached the start of the iteration */
+ bool start;
+ /* If the iterator has reached the end of the iteration */
+ bool end;
+};
+
+/* Iterator Initialization */
+struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target);
+struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME *target);
+/* Iterator State */
+bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter);
+bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter);
+/* Iterator Movement */
+bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter);
+bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter);
+bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter);
+bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter);
+bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps);
+bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps);
+bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index);
+/* Iterator Access */
+V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter);
+V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter);
+size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
+struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _iter_node)(struct CMC_DEF_ITER(SNAME) * iter);
+
+#endif /* CMC_EXT_ITER */
+
+/**
+ * NODE
+ *
+ * Operations relative to a linkedlist node
+ */
+#ifdef CMC_EXT_NODE
+
+/* Node Allocation and Deallocation */
+struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _new_node)(struct SNAME *_list_, V value);
+void CMC_(PFX, _free_node)(struct SNAME *_list_, struct CMC_DEF_NODE(SNAME) * _node_);
+/* Node Access Relative to a Linked List */
+struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _head)(struct SNAME *_list_);
+struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _get_node)(struct SNAME *_list_, size_t index);
+struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _tail)(struct SNAME *_list_);
+/* Input and Output Relative to a Node */
+bool CMC_(PFX, _add_next)(struct SNAME *_owner_, struct CMC_DEF_NODE(SNAME) * _node_, V value);
+bool CMC_(PFX, _add_prev)(struct SNAME *_owner_, struct CMC_DEF_NODE(SNAME) * _node_, V value);
+bool CMC_(PFX, _del_next)(struct SNAME *_owner_, struct CMC_DEF_NODE(SNAME) * _node_);
+bool CMC_(PFX, _del_curr)(struct SNAME *_owner_, struct CMC_DEF_NODE(SNAME) * _node_);
+bool CMC_(PFX, _del_prev)(struct SNAME *_owner_, struct CMC_DEF_NODE(SNAME) * _node_);
+/* Node Access Relative to a Linked List Node */
+struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _next_node)(struct CMC_DEF_NODE(SNAME) * _node_);
+struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _prev_node)(struct CMC_DEF_NODE(SNAME) * _node_);
+
+#endif /* CMC_EXT_NODE */
+
+/**
+ * STR
+ *
+ * Print helper functions.
+ */
+#ifdef CMC_EXT_STR
+
+bool CMC_(PFX, _to_string)(struct SNAME *_list_, FILE *fptr);
+bool CMC_(PFX, _print)(struct SNAME *_list_, FILE *fptr, const char *start, const char *separator, const char *end);
+
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/linkedlist/ext/struct.h b/src/cmc/cmc/linkedlist/ext/struct.h
new file mode 100644
index 0000000..6741cd2
--- /dev/null
+++ b/src/cmc/cmc/linkedlist/ext/struct.h
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * ITER
+ *
+ * List bi-directional iterator.
+ */
+#ifdef CMC_EXT_ITER
+
+#endif /* CMC_EXT_ITER */
diff --git a/src/cmc/cmc/linkedlist/header.h b/src/cmc/cmc/linkedlist/header.h
new file mode 100644
index 0000000..2082677
--- /dev/null
+++ b/src/cmc/cmc/linkedlist/header.h
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* Value struct function table */
+struct CMC_DEF_FVAL(SNAME)
+{
+ /* Comparator function */
+ CMC_DEF_FTAB_CMP(V);
+ /* Copy function */
+ CMC_DEF_FTAB_CPY(V);
+ /* To string function */
+ CMC_DEF_FTAB_STR(V);
+ /* Free from memory function */
+ CMC_DEF_FTAB_FREE(V);
+ /* Hash function */
+ CMC_DEF_FTAB_HASH(V);
+ /* Priority function */
+ CMC_DEF_FTAB_PRI(V);
+};
+
+/* Collection Functions */
+/* Collection Allocation and Deallocation */
+struct SNAME *CMC_(PFX, _new)(struct CMC_DEF_FVAL(SNAME) * f_val);
+struct SNAME *CMC_(PFX, _new_custom)(struct CMC_DEF_FVAL(SNAME) * f_val, struct CMC_ALLOC_NODE_NAME *alloc,
+ struct CMC_CALLBACKS_NAME *callbacks);
+void CMC_(PFX, _clear)(struct SNAME *_list_);
+void CMC_(PFX, _free)(struct SNAME *_list_);
+/* Customization of Allocation and Callbacks */
+void CMC_(PFX, _customize)(struct SNAME *_list_, struct CMC_ALLOC_NODE_NAME *alloc,
+ struct CMC_CALLBACKS_NAME *callbacks);
+/* Collection Input and Output */
+bool CMC_(PFX, _push_front)(struct SNAME *_list_, V value);
+bool CMC_(PFX, _push_at)(struct SNAME *_list_, V value, size_t index);
+bool CMC_(PFX, _push_back)(struct SNAME *_list_, V value);
+bool CMC_(PFX, _pop_front)(struct SNAME *_list_);
+bool CMC_(PFX, _pop_at)(struct SNAME *_list_, size_t index);
+bool CMC_(PFX, _pop_back)(struct SNAME *_list_);
+/* Element Access */
+V CMC_(PFX, _front)(struct SNAME *_list_);
+V CMC_(PFX, _get)(struct SNAME *_list_, size_t index);
+V *CMC_(PFX, _get_ref)(struct SNAME *_list_, size_t index);
+V CMC_(PFX, _back)(struct SNAME *_list_);
+/* Collection State */
+bool CMC_(PFX, _contains)(struct SNAME *_list_, V value);
+bool CMC_(PFX, _empty)(struct SNAME *_list_);
+size_t CMC_(PFX, _count)(struct SNAME *_list_);
+int CMC_(PFX, _flag)(struct SNAME *_list_);
+/* Collection Utility */
+struct SNAME *CMC_(PFX, _copy_of)(struct SNAME *_list_);
+bool CMC_(PFX, _equals)(struct SNAME *_list1_, struct SNAME *_list2_);
diff --git a/src/cmc/cmc/linkedlist/struct.h b/src/cmc/cmc/linkedlist/struct.h
new file mode 100644
index 0000000..e7572c2
--- /dev/null
+++ b/src/cmc/cmc/linkedlist/struct.h
@@ -0,0 +1,61 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* Linked List Structure */
+struct SNAME
+{
+ /* First node in the list */
+ struct CMC_DEF_NODE(SNAME) * head;
+
+ /* Last node in the list */
+ struct CMC_DEF_NODE(SNAME) * tail;
+
+ /* Current amount of elements in the list */
+ size_t count;
+
+ /* Flags indicating errors or success */
+ int flag;
+
+ /* Value function table */
+ struct CMC_DEF_FVAL(SNAME) * f_val;
+
+ /* Custom allocation functions */
+ struct CMC_ALLOC_NODE_NAME *alloc;
+
+ /* Custom callback functions */
+ CMC_CALLBACKS_DECL;
+};
+
+/* Doubly-linked list node */
+struct CMC_DEF_NODE(SNAME)
+{
+ /* Node's value */
+ V value;
+
+ /* Pointer to the next node on the linked list */
+ struct CMC_DEF_NODE(SNAME) * next;
+
+ /* Pointer to the previous node on the linked list */
+ struct CMC_DEF_NODE(SNAME) * prev;
+};
diff --git a/src/cmc/cmc/list/ext/code.h b/src/cmc/cmc/list/ext/code.h
index 97e39a8..182a6b5 100644
--- a/src/cmc/cmc/list/ext/code.h
+++ b/src/cmc/cmc/list/ext/code.h
@@ -28,7 +28,7 @@
* The part 'INIT' gives a new way of initializing a collection. The collection
* struct is not heap allocated, only its internal structure (nodes, buffers).
*/
-#ifdef CMC_EXT_LIST_INIT
+#ifdef CMC_EXT_INIT
struct SNAME CMC_(PFX, _init)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val)
{
@@ -77,14 +77,14 @@ void CMC_(PFX, _release)(struct SNAME _list_)
_list_.alloc->free(_list_.buffer);
}
-#endif /* CMC_EXT_LIST_INIT */
+#endif /* CMC_EXT_INIT */
/**
* ITER
*
* List bi-directional iterator.
*/
-#ifdef CMC_EXT_LIST_ITER
+#ifdef CMC_EXT_ITER
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target)
{
@@ -267,14 +267,14 @@ size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter)
return iter->cursor;
}
-#endif /* CMC_EXT_LIST_ITER */
+#endif /* CMC_EXT_ITER */
/**
* SEQ
*
* Push and pop sequence of items.
*/
-#ifdef CMC_EXT_LIST_SEQ
+#ifdef CMC_EXT_SEQ
bool CMC_(PFX, _seq_push_front)(struct SNAME *_list_, V *values, size_t size)
{
@@ -431,14 +431,14 @@ struct SNAME *CMC_(PFX, _seq_sublist)(struct SNAME *_list_, size_t from, size_t
return result;
}
-#endif /* CMC_EXT_LIST_SEQ */
+#endif /* CMC_EXT_SEQ */
/**
* STR
*
* Print helper functions.
*/
-#ifdef CMC_EXT_LIST_STR
+#ifdef CMC_EXT_STR
bool CMC_(PFX, _to_string)(struct SNAME *_list_, FILE *fptr)
{
@@ -476,4 +476,4 @@ bool CMC_(PFX, _print)(struct SNAME *_list_, FILE *fptr, const char *start, cons
return true;
}
-#endif /* CMC_EXT_LIST_STR */
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/list/ext/header.h b/src/cmc/cmc/list/ext/header.h
index 67deb82..7e2ffd2 100644
--- a/src/cmc/cmc/list/ext/header.h
+++ b/src/cmc/cmc/list/ext/header.h
@@ -28,21 +28,21 @@
* The part 'INIT' gives a new way of initializing a collection. The collection
* struct is not heap allocated, only its internal structure (nodes, buffers).
*/
-#ifdef CMC_EXT_LIST_INIT
+#ifdef CMC_EXT_INIT
struct SNAME CMC_(PFX, _init)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val);
struct SNAME CMC_(PFX, _init_custom)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val,
struct CMC_ALLOC_NODE_NAME *alloc, struct CMC_CALLBACKS_NAME *callbacks);
void CMC_(PFX, _release)(struct SNAME _list_);
-#endif /* CMC_EXT_LIST_INIT */
+#endif /* CMC_EXT_INIT */
/**
* ITER
*
* List bi-directional iterator.
*/
-#ifdef CMC_EXT_LIST_ITER
+#ifdef CMC_EXT_ITER
/* Iterator Initialization */
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target);
@@ -63,14 +63,14 @@ V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter);
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter);
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
-#endif /* CMC_EXT_LIST_ITER */
+#endif /* CMC_EXT_ITER */
/**
* SEQ
*
* Push and pop sequence of items.
*/
-#ifdef CMC_EXT_LIST_SEQ
+#ifdef CMC_EXT_SEQ
/* List Sequence Input and Output */
bool CMC_(PFX, _seq_push_front)(struct SNAME *_list_, V *values, size_t size);
@@ -79,18 +79,18 @@ bool CMC_(PFX, _seq_push_back)(struct SNAME *_list_, V *values, size_t size);
bool CMC_(PFX, _seq_pop_at)(struct SNAME *_list_, size_t from, size_t to);
struct SNAME *CMC_(PFX, _seq_sublist)(struct SNAME *_list_, size_t from, size_t to);
-#endif /* CMC_EXT_LIST_SEQ */
+#endif /* CMC_EXT_SEQ */
/**
* STR
*
* Print helper functions.
*/
-#ifdef CMC_EXT_LIST_STR
+#ifdef CMC_EXT_STR
/* Debug prints the struct to fptr */
bool CMC_(PFX, _to_string)(struct SNAME *_list_, FILE *fptr);
/* Prints each item in the list as an array */
bool CMC_(PFX, _print)(struct SNAME *_list_, FILE *fptr, const char *start, const char *separator, const char *end);
-#endif /* CMC_EXT_LIST_STR */
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/list/ext/struct.h b/src/cmc/cmc/list/ext/struct.h
index fb4c3f9..d82cbd3 100644
--- a/src/cmc/cmc/list/ext/struct.h
+++ b/src/cmc/cmc/list/ext/struct.h
@@ -27,7 +27,7 @@
*
* List bi-directional iterator.
*/
-#ifdef CMC_EXT_LIST_ITER
+#ifdef CMC_EXT_ITER
/* List Iterator */
struct CMC_DEF_ITER(SNAME)
@@ -42,4 +42,4 @@ struct CMC_DEF_ITER(SNAME)
bool end;
};
-#endif /* CMC_EXT_LIST_ITER */
+#endif /* CMC_EXT_ITER */
diff --git a/src/cmc/cmc/queue/ext/code.h b/src/cmc/cmc/queue/ext/code.h
index 3643611..95f53c4 100644
--- a/src/cmc/cmc/queue/ext/code.h
+++ b/src/cmc/cmc/queue/ext/code.h
@@ -28,7 +28,7 @@
* The part 'INIT' gives a new way of initializing a collection. The collection
* struct is not heap allocated, only its internal structure (nodes, buffers).
*/
-#ifdef CMC_EXT_QUEUE_INIT
+#ifdef CMC_EXT_INIT
struct SNAME CMC_(PFX, _init)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val)
{
@@ -83,14 +83,14 @@ void CMC_(PFX, _release)(struct SNAME _queue_)
_queue_.alloc->free(_queue_.buffer);
}
-#endif /* CMC_EXT_QUEUE_INIT */
+#endif /* CMC_EXT_INIT */
/**
* ITER
*
* Queue bi-directional iterator.
*/
-#ifdef CMC_EXT_QUEUE_ITER
+#ifdef CMC_EXT_ITER
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target)
{
@@ -302,14 +302,14 @@ size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter)
return iter->index;
}
-#endif /* CMC_EXT_QUEUE_ITER */
+#endif /* CMC_EXT_ITER */
/**
* STR
*
* Print helper functions.
*/
-#ifdef CMC_EXT_QUEUE_STR
+#ifdef CMC_EXT_STR
bool CMC_(PFX, _to_string)(struct SNAME *_queue_, FILE *fptr)
{
@@ -351,4 +351,4 @@ bool CMC_(PFX, _print)(struct SNAME *_queue_, FILE *fptr, const char *start, con
return true;
}
-#endif /* CMC_EXT_QUEUE_STR */
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/queue/ext/header.h b/src/cmc/cmc/queue/ext/header.h
index 7d9b357..8ad7c5b 100644
--- a/src/cmc/cmc/queue/ext/header.h
+++ b/src/cmc/cmc/queue/ext/header.h
@@ -28,21 +28,21 @@
* The part 'INIT' gives a new way of initializing a collection. The collection
* struct is not heap allocated, only its internal structure (nodes, buffers).
*/
-#ifdef CMC_EXT_QUEUE_INIT
+#ifdef CMC_EXT_INIT
struct SNAME CMC_(PFX, _init)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val);
struct SNAME CMC_(PFX, _init_custom)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val,
struct CMC_ALLOC_NODE_NAME *alloc, struct CMC_CALLBACKS_NAME *callbacks);
void CMC_(PFX, _release)(struct SNAME _queue_);
-#endif /* CMC_EXT_QUEUE_INIT */
+#endif /* CMC_EXT_INIT */
/**
* ITER
*
* Queue bi-directional iterator.
*/
-#ifdef CMC_EXT_QUEUE_ITER
+#ifdef CMC_EXT_ITER
/* Iterator Initialization */
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target);
@@ -63,18 +63,18 @@ V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter);
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter);
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
-#endif /* CMC_EXT_QUEUE_ITER */
+#endif /* CMC_EXT_ITER */
/**
* STR
*
* Print helper functions.
*/
-#ifdef CMC_EXT_QUEUE_STR
+#ifdef CMC_EXT_STR
/* Debug prints the struct to fptr */
bool CMC_(PFX, _to_string)(struct SNAME *_queue_, FILE *fptr);
/* Prints each item in the queue as an array */
bool CMC_(PFX, _print)(struct SNAME *_queue_, FILE *fptr, const char *start, const char *separator, const char *end);
-#endif /* CMC_EXT_QUEUE_STR */
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/queue/ext/struct.h b/src/cmc/cmc/queue/ext/struct.h
index c773ad5..40f9838 100644
--- a/src/cmc/cmc/queue/ext/struct.h
+++ b/src/cmc/cmc/queue/ext/struct.h
@@ -27,7 +27,7 @@
*
* Queue bi-directional iterator.
*/
-#ifdef CMC_EXT_QUEUE_ITER
+#ifdef CMC_EXT_ITER
/* Queue Iterator */
struct CMC_DEF_ITER(SNAME)
@@ -44,4 +44,4 @@ struct CMC_DEF_ITER(SNAME)
bool end;
};
-#endif /* CMC_EXT_QUEUE_ITER */
+#endif /* CMC_EXT_ITER */
diff --git a/src/cmc/cmc/sortedlist/code.h b/src/cmc/cmc/sortedlist/code.h
new file mode 100644
index 0000000..483e346
--- /dev/null
+++ b/src/cmc/cmc/sortedlist/code.h
@@ -0,0 +1,479 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* Implementation Detail Functions */
+static size_t CMC_(PFX, _impl_binary_search_first)(struct SNAME *_list_, V value);
+static size_t CMC_(PFX, _impl_binary_search_last)(struct SNAME *_list_, V value);
+void CMC_(PFX, _impl_sort_quicksort)(V *array, int (*cmp)(V, V), size_t low, size_t high);
+void CMC_(PFX, _impl_sort_insertion)(V *array, int (*cmp)(V, V), size_t low, size_t high);
+
+struct SNAME *CMC_(PFX, _new)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val)
+{
+ return CMC_(PFX, _new_custom)(capacity, f_val, NULL, NULL);
+}
+
+struct SNAME *CMC_(PFX, _new_custom)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val,
+ struct CMC_ALLOC_NODE_NAME *alloc, struct CMC_CALLBACKS_NAME *callbacks)
+{
+ CMC_CALLBACKS_MAYBE_UNUSED(callbacks);
+
+ if (capacity < 1)
+ return NULL;
+
+ if (!alloc)
+ alloc = &cmc_alloc_node_default;
+
+ struct SNAME *_list_ = alloc->malloc(sizeof(struct SNAME));
+
+ if (!_list_)
+ return NULL;
+
+ _list_->buffer = alloc->calloc(capacity, sizeof(V));
+
+ if (!_list_->buffer)
+ {
+ alloc->free(_list_);
+ return NULL;
+ }
+
+ _list_->capacity = capacity;
+ _list_->count = 0;
+ _list_->is_sorted = false;
+ _list_->flag = CMC_FLAG_OK;
+ _list_->f_val = f_val;
+ _list_->alloc = alloc;
+ CMC_CALLBACKS_ASSIGN(_list_, callbacks);
+
+ return _list_;
+}
+
+void CMC_(PFX, _clear)(struct SNAME *_list_)
+{
+ if (_list_->f_val->free)
+ {
+ for (size_t i = 0; i < _list_->count; i++)
+ _list_->f_val->free(_list_->buffer[i]);
+ }
+
+ memset(_list_->buffer, 0, sizeof(V) * _list_->capacity);
+
+ _list_->count = 0;
+ _list_->flag = CMC_FLAG_OK;
+}
+
+void CMC_(PFX, _free)(struct SNAME *_list_)
+{
+ if (_list_->f_val->free)
+ {
+ for (size_t i = 0; i < _list_->count; i++)
+ _list_->f_val->free(_list_->buffer[i]);
+ }
+
+ _list_->alloc->free(_list_->buffer);
+ _list_->alloc->free(_list_);
+}
+
+void CMC_(PFX, _customize)(struct SNAME *_list_, struct CMC_ALLOC_NODE_NAME *alloc,
+ struct CMC_CALLBACKS_NAME *callbacks)
+{
+ CMC_CALLBACKS_MAYBE_UNUSED(callbacks);
+
+ if (!alloc)
+ _list_->alloc = &cmc_alloc_node_default;
+ else
+ _list_->alloc = alloc;
+
+ CMC_CALLBACKS_ASSIGN(_list_, callbacks);
+
+ _list_->flag = CMC_FLAG_OK;
+}
+
+bool CMC_(PFX, _insert)(struct SNAME *_list_, V value)
+{
+ if (CMC_(PFX, _full)(_list_))
+ {
+ if (!CMC_(PFX, _resize)(_list_, _list_->capacity * 2))
+ return false;
+ }
+
+ _list_->buffer[_list_->count++] = value;
+
+ _list_->is_sorted = false;
+ _list_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_list_, create);
+
+ return true;
+}
+
+bool CMC_(PFX, _remove)(struct SNAME *_list_, size_t index)
+{
+ if (CMC_(PFX, _empty)(_list_))
+ {
+ _list_->flag = CMC_FLAG_EMPTY;
+ return false;
+ }
+
+ if (index >= _list_->count)
+ {
+ _list_->flag = CMC_FLAG_RANGE;
+ return false;
+ }
+
+ memmove(_list_->buffer + index, _list_->buffer + index + 1, (_list_->count - index) * sizeof(V));
+
+ _list_->buffer[--_list_->count] = (V){ 0 };
+
+ _list_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_list_, delete);
+
+ return true;
+}
+
+V CMC_(PFX, _max)(struct SNAME *_list_)
+{
+ if (CMC_(PFX, _empty)(_list_))
+ {
+ _list_->flag = CMC_FLAG_EMPTY;
+ return (V){ 0 };
+ }
+
+ CMC_(PFX, _sort)(_list_);
+
+ _list_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_list_, read);
+
+ return _list_->buffer[_list_->count - 1];
+}
+
+V CMC_(PFX, _min)(struct SNAME *_list_)
+{
+ if (CMC_(PFX, _empty)(_list_))
+ {
+ _list_->flag = CMC_FLAG_EMPTY;
+ return (V){ 0 };
+ }
+
+ CMC_(PFX, _sort)(_list_);
+
+ _list_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_list_, read);
+
+ return _list_->buffer[0];
+}
+
+V CMC_(PFX, _get)(struct SNAME *_list_, size_t index)
+{
+ if (CMC_(PFX, _empty)(_list_))
+ {
+ _list_->flag = CMC_FLAG_EMPTY;
+ return (V){ 0 };
+ }
+
+ if (index >= _list_->count)
+ {
+ _list_->flag = CMC_FLAG_RANGE;
+ return (V){ 0 };
+ }
+
+ CMC_(PFX, _sort)(_list_);
+
+ _list_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_list_, read);
+
+ return _list_->buffer[index];
+}
+
+size_t CMC_(PFX, _index_of)(struct SNAME *_list_, V value, bool from_start)
+{
+ _list_->flag = CMC_FLAG_OK;
+
+ CMC_(PFX, _sort)(_list_);
+
+ CMC_CALLBACKS_CALL(_list_, read);
+
+ if (from_start)
+ {
+ return CMC_(PFX, _impl_binary_search_first)(_list_, value);
+ }
+
+ return CMC_(PFX, _impl_binary_search_last)(_list_, value);
+}
+
+bool CMC_(PFX, _contains)(struct SNAME *_list_, V value)
+{
+ _list_->flag = CMC_FLAG_OK;
+
+ if (CMC_(PFX, _empty)(_list_))
+ return false;
+
+ CMC_(PFX, _sort)(_list_);
+
+ CMC_CALLBACKS_CALL(_list_, read);
+
+ return CMC_(PFX, _impl_binary_search_first)(_list_, value) < _list_->count;
+}
+
+bool CMC_(PFX, _empty)(struct SNAME *_list_)
+{
+ return _list_->count == 0;
+}
+
+bool CMC_(PFX, _full)(struct SNAME *_list_)
+{
+ return _list_->count >= _list_->capacity;
+}
+
+size_t CMC_(PFX, _count)(struct SNAME *_list_)
+{
+ return _list_->count;
+}
+
+size_t CMC_(PFX, _capacity)(struct SNAME *_list_)
+{
+ return _list_->capacity;
+}
+
+int CMC_(PFX, _flag)(struct SNAME *_list_)
+{
+ return _list_->flag;
+}
+
+bool CMC_(PFX, _resize)(struct SNAME *_list_, size_t capacity)
+{
+ if (_list_->capacity == capacity)
+ goto success;
+
+ if (capacity < _list_->count)
+ {
+ _list_->flag = CMC_FLAG_INVALID;
+ return false;
+ }
+
+ V *new_buffer = _list_->alloc->realloc(_list_->buffer, sizeof(V) * capacity);
+
+ if (!new_buffer)
+ {
+ _list_->flag = CMC_FLAG_ALLOC;
+ return false;
+ }
+
+ /* TODO zero out remaining slots */
+
+ _list_->buffer = new_buffer;
+ _list_->capacity = capacity;
+
+success:
+
+ _list_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_list_, resize);
+
+ return true;
+}
+
+void CMC_(PFX, _sort)(struct SNAME *_list_)
+{
+ _list_->flag = CMC_FLAG_OK;
+
+ if (!_list_->is_sorted && _list_->count > 1)
+ {
+ CMC_(PFX, _impl_sort_quicksort)
+ (_list_->buffer, _list_->f_val->cmp, 0, _list_->count - 1);
+
+ _list_->is_sorted = true;
+ }
+}
+
+struct SNAME *CMC_(PFX, _copy_of)(struct SNAME *_list_)
+{
+ struct SNAME *result = CMC_(PFX, _new_custom)(_list_->capacity, _list_->f_val, _list_->alloc, NULL);
+
+ if (!result)
+ {
+ _list_->flag = CMC_FLAG_ERROR;
+ return NULL;
+ }
+
+ CMC_CALLBACKS_ASSIGN(result, _list_->callbacks);
+
+ if (_list_->f_val->cpy)
+ {
+ for (size_t i = 0; i < _list_->count; i++)
+ result->buffer[i] = _list_->f_val->cpy(_list_->buffer[i]);
+ }
+ else
+ memcpy(result->buffer, _list_->buffer, sizeof(V) * _list_->count);
+
+ result->count = _list_->count;
+
+ _list_->flag = CMC_FLAG_OK;
+
+ return result;
+}
+
+bool CMC_(PFX, _equals)(struct SNAME *_list1_, struct SNAME *_list2_)
+{
+ if (_list1_->count != _list2_->count)
+ return false;
+
+ CMC_(PFX, _sort)(_list1_);
+ CMC_(PFX, _sort)(_list2_);
+
+ for (size_t i = 0; i < _list1_->count; i++)
+ {
+ if (_list1_->f_val->cmp(_list1_->buffer[i], _list2_->buffer[i]) != 0)
+ return false;
+ }
+
+ return true;
+}
+
+static size_t CMC_(PFX, _impl_binary_search_first)(struct SNAME *_list_, V value)
+{
+ if (CMC_(PFX, _empty)(_list_))
+ return 1;
+
+ size_t L = 0;
+ size_t R = _list_->count;
+
+ while (L < R)
+ {
+ size_t M = L + (R - L) / 2;
+
+ if (_list_->f_val->cmp(_list_->buffer[M], value) < 0)
+ L = M + 1;
+ else
+ R = M;
+ }
+
+ if (_list_->f_val->cmp(_list_->buffer[L], value) == 0)
+ return L;
+
+ /* Not found */
+ return _list_->count;
+}
+
+static size_t CMC_(PFX, _impl_binary_search_last)(struct SNAME *_list_, V value)
+{
+ if (CMC_(PFX, _empty)(_list_))
+ return 1;
+
+ size_t L = 0;
+ size_t R = _list_->count;
+
+ while (L < R)
+ {
+ size_t M = L + (R - L) / 2;
+
+ if (_list_->f_val->cmp(_list_->buffer[M], value) > 0)
+ R = M;
+ else
+ L = M + 1;
+ }
+
+ if (L > 0 && _list_->f_val->cmp(_list_->buffer[L - 1], value) == 0)
+ return L - 1;
+
+ /* Not found */
+ return _list_->count;
+}
+
+/* Characteristics of this quicksort implementation: */
+/* - Hybrid: uses insertion sort for small arrays */
+/* - Partition: Lomuto's Method */
+/* - Tail recursion: minimize recursion depth */
+void CMC_(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)
+ {
+ CMC_(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)
+ {
+ CMC_(PFX, _impl_sort_quicksort)
+ (array, cmp, low, pindex - 1);
+
+ low = pindex + 1;
+ }
+ else
+ {
+ CMC_(PFX, _impl_sort_quicksort)
+ (array, cmp, pindex + 1, high);
+
+ high = pindex - 1;
+ }
+ }
+ }
+}
+
+void CMC_(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_;
+ }
+}
diff --git a/src/cmc/cmc/sortedlist/ext/code.h b/src/cmc/cmc/sortedlist/ext/code.h
new file mode 100644
index 0000000..8427190
--- /dev/null
+++ b/src/cmc/cmc/sortedlist/ext/code.h
@@ -0,0 +1,267 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * INIT
+ *
+ * The part 'INIT' gives a new way of initializing a collection. The collection
+ * struct is not heap allocated, only its internal structure (nodes, buffers).
+ */
+#ifdef CMC_EXT_INIT
+
+#endif /* CMC_EXT_INIT */
+
+/**
+ * ITER
+ *
+ * List bi-directional iterator.
+ */
+#ifdef CMC_EXT_ITER
+
+struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target)
+{
+ CMC_(PFX, _sort)(target);
+
+ struct CMC_DEF_ITER(SNAME) iter;
+
+ iter.target = target;
+ iter.cursor = 0;
+ iter.start = true;
+ iter.end = CMC_(PFX, _empty)(target);
+
+ return iter;
+}
+
+struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME *target)
+{
+ CMC_(PFX, _sort)(target);
+
+ struct CMC_DEF_ITER(SNAME) iter;
+
+ iter.target = target;
+ iter.cursor = 0;
+ iter.start = CMC_(PFX, _empty)(target);
+ iter.end = true;
+
+ if (!CMC_(PFX, _empty)(target))
+ iter.cursor = target->count - 1;
+
+ return iter;
+}
+
+bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ return CMC_(PFX, _empty)(iter->target) || iter->start;
+}
+
+bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ return CMC_(PFX, _empty)(iter->target) || iter->end;
+}
+
+bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ if (!CMC_(PFX, _empty)(iter->target))
+ {
+ iter->cursor = 0;
+ iter->start = true;
+ iter->end = CMC_(PFX, _empty)(iter->target);
+
+ return true;
+ }
+
+ return false;
+}
+
+bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ if (!CMC_(PFX, _empty)(iter->target))
+ {
+ iter->start = CMC_(PFX, _empty)(iter->target);
+ iter->cursor = iter->target->count - 1;
+ iter->end = true;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ if (iter->end)
+ return false;
+
+ if (iter->cursor + 1 == iter->target->count)
+ {
+ iter->end = true;
+ return false;
+ }
+
+ iter->start = CMC_(PFX, _empty)(iter->target);
+
+ iter->cursor++;
+
+ return true;
+}
+
+bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ if (iter->start)
+ return false;
+
+ if (iter->cursor == 0)
+ {
+ iter->start = true;
+ return false;
+ }
+
+ iter->end = CMC_(PFX, _empty)(iter->target);
+
+ iter->cursor--;
+
+ return true;
+}
+
+/* Returns true only if the iterator moved */
+bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps)
+{
+ if (iter->end)
+ return false;
+
+ if (iter->cursor + 1 == iter->target->count)
+ {
+ iter->end = true;
+ return false;
+ }
+
+ if (steps == 0 || iter->cursor + steps >= iter->target->count)
+ return false;
+
+ iter->start = CMC_(PFX, _empty)(iter->target);
+
+ iter->cursor += steps;
+
+ return true;
+}
+
+/* Returns true only if the iterator moved */
+bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps)
+{
+ if (iter->start)
+ return false;
+
+ if (iter->cursor == 0)
+ {
+ iter->start = true;
+ return false;
+ }
+
+ if (steps == 0 || iter->cursor < steps)
+ return false;
+
+ iter->end = CMC_(PFX, _empty)(iter->target);
+
+ iter->cursor -= steps;
+
+ return true;
+}
+
+/* Returns true only if the iterator was able to be positioned at the */
+/* given index */
+bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index)
+{
+ if (index >= iter->target->count)
+ return false;
+
+ if (iter->cursor > index)
+ return CMC_(PFX, _iter_rewind)(iter, iter->cursor - index);
+ else if (iter->cursor < index)
+ return CMC_(PFX, _iter_advance)(iter, index - iter->cursor);
+
+ return true;
+}
+
+V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ if (CMC_(PFX, _empty)(iter->target))
+ return (V){ 0 };
+
+ return iter->target->buffer[iter->cursor];
+}
+
+size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ return iter->cursor;
+}
+
+#endif /* CMC_EXT_ITER */
+
+/**
+ * STR
+ *
+ * Print helper functions.
+ */
+#ifdef CMC_EXT_STR
+
+bool CMC_(PFX, _to_string)(struct SNAME *_list_, FILE *fptr)
+{
+ struct SNAME *l_ = _list_;
+
+ return 0 <= fprintf(fptr,
+ "struct %s<%s> "
+ "at %p { "
+ "buffer:%p, "
+ "capacity:%" PRIuMAX ", "
+ "count:%" PRIuMAX ", "
+ "is_sorted:%s, "
+ "flag:%d, "
+ "f_val:%p, "
+ "alloc:%p, "
+ "callbacks:%p }",
+ CMC_TO_STRING(SNAME), CMC_TO_STRING(V), l_, l_->buffer, l_->capacity, l_->count,
+ l_->is_sorted ? "true" : "false", l_->flag, l_->f_val, l_->alloc, CMC_CALLBACKS_GET(l_));
+}
+
+bool CMC_(PFX, _print)(struct SNAME *_list_, FILE *fptr, const char *start, const char *separator, const char *end)
+{
+ CMC_(PFX, _sort)(_list_);
+
+ fprintf(fptr, "%s", start);
+
+ for (size_t i = 0; i < _list_->count; i++)
+ {
+ if (!_list_->f_val->str(fptr, _list_->buffer[i]))
+ return false;
+
+ if (i + 1 < _list_->count)
+ fprintf(fptr, "%s", separator);
+ }
+
+ fprintf(fptr, "%s", end);
+
+ return true;
+}
+
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/sortedlist/ext/header.h b/src/cmc/cmc/sortedlist/ext/header.h
new file mode 100644
index 0000000..5533908
--- /dev/null
+++ b/src/cmc/cmc/sortedlist/ext/header.h
@@ -0,0 +1,85 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * INIT
+ *
+ * The part 'INIT' gives a new way of initializing a collection. The collection
+ * struct is not heap allocated, only its internal structure (nodes, buffers).
+ */
+#ifdef CMC_EXT_INIT
+
+#endif /* CMC_EXT_INIT */
+
+/**
+ * ITER
+ *
+ * List bi-directional iterator.
+ */
+#ifdef CMC_EXT_ITER
+
+/* List Iterator */
+struct CMC_DEF_ITER(SNAME)
+{
+ /* Target list */
+ struct SNAME *target;
+ /* Cursor's position (index) */
+ size_t cursor;
+ /* If the iterator has reached the start of the iteration */
+ bool start;
+ /* If the iterator has reached the end of the iteration */
+ bool end;
+};
+
+/* Iterator Initialization */
+struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target);
+struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME *target);
+/* Iterator State */
+bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter);
+bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter);
+/* Iterator Movement */
+bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter);
+bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter);
+bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter);
+bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter);
+bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps);
+bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps);
+bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index);
+/* Iterator Access */
+V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter);
+size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
+
+#endif /* CMC_EXT_ITER */
+
+/**
+ * STR
+ *
+ * Print helper functions.
+ */
+#ifdef CMC_EXT_STR
+
+bool CMC_(PFX, _to_string)(struct SNAME *_list_, FILE *fptr);
+bool CMC_(PFX, _print)(struct SNAME *_list_, FILE *fptr, const char *start, const char *separator, const char *end);
+
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/sortedlist/ext/struct.h b/src/cmc/cmc/sortedlist/ext/struct.h
new file mode 100644
index 0000000..59c5376
--- /dev/null
+++ b/src/cmc/cmc/sortedlist/ext/struct.h
@@ -0,0 +1,23 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
diff --git a/src/cmc/cmc/sortedlist/header.h b/src/cmc/cmc/sortedlist/header.h
new file mode 100644
index 0000000..04321cc
--- /dev/null
+++ b/src/cmc/cmc/sortedlist/header.h
@@ -0,0 +1,70 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* Value struct function table */
+struct CMC_DEF_FVAL(SNAME)
+{
+ /* Comparator function */
+ CMC_DEF_FTAB_CMP(V);
+ /* Copy function */
+ CMC_DEF_FTAB_CPY(V);
+ /* To string function */
+ CMC_DEF_FTAB_STR(V);
+ /* Free from memory function */
+ CMC_DEF_FTAB_FREE(V);
+ /* Hash function */
+ CMC_DEF_FTAB_HASH(V);
+ /* Priority function */
+ CMC_DEF_FTAB_PRI(V);
+};
+
+/* Collection Allocation and Deallocation */
+struct SNAME *CMC_(PFX, _new)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val);
+struct SNAME *CMC_(PFX, _new_custom)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val,
+ struct CMC_ALLOC_NODE_NAME *alloc, struct CMC_CALLBACKS_NAME *callbacks);
+void CMC_(PFX, _clear)(struct SNAME *_list_);
+void CMC_(PFX, _free)(struct SNAME *_list_);
+/* Customization of Allocation and Callbacks */
+void CMC_(PFX, _customize)(struct SNAME *_list_, struct CMC_ALLOC_NODE_NAME *alloc,
+ struct CMC_CALLBACKS_NAME *callbacks);
+/* Collection Input and Output */
+bool CMC_(PFX, _insert)(struct SNAME *_list_, V value);
+bool CMC_(PFX, _remove)(struct SNAME *_list_, size_t index);
+/* Element Access */
+V CMC_(PFX, _max)(struct SNAME *_list_);
+V CMC_(PFX, _min)(struct SNAME *_list_);
+V CMC_(PFX, _get)(struct SNAME *_list_, size_t index);
+size_t CMC_(PFX, _index_of)(struct SNAME *_list_, V value, bool from_start);
+/* Collection State */
+bool CMC_(PFX, _contains)(struct SNAME *_list_, V value);
+bool CMC_(PFX, _empty)(struct SNAME *_list_);
+bool CMC_(PFX, _full)(struct SNAME *_list_);
+size_t CMC_(PFX, _count)(struct SNAME *_list_);
+size_t CMC_(PFX, _capacity)(struct SNAME *_list_);
+int CMC_(PFX, _flag)(struct SNAME *_list_);
+/* Collection Utility */
+bool CMC_(PFX, _resize)(struct SNAME *_list_, size_t capacity);
+void CMC_(PFX, _sort)(struct SNAME *_list_);
+struct SNAME *CMC_(PFX, _copy_of)(struct SNAME *_list_);
+bool CMC_(PFX, _equals)(struct SNAME *_list1_, struct SNAME *_list2_);
diff --git a/src/cmc/cmc/sortedlist/struct.h b/src/cmc/cmc/sortedlist/struct.h
new file mode 100644
index 0000000..c9456c4
--- /dev/null
+++ b/src/cmc/cmc/sortedlist/struct.h
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+struct SNAME
+{
+ /* 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;
+ /* Flags indicating errors or success */
+ int flag;
+ /* Value function table */
+ struct CMC_DEF_FVAL(SNAME) * f_val;
+ /* Custom allocation functions */
+ struct CMC_ALLOC_NODE_NAME *alloc;
+ /* Custom callback functions */
+ CMC_CALLBACKS_DECL;
+};
diff --git a/src/cmc/cmc/stack/ext/code.h b/src/cmc/cmc/stack/ext/code.h
index b61e4a4..6b179b9 100644
--- a/src/cmc/cmc/stack/ext/code.h
+++ b/src/cmc/cmc/stack/ext/code.h
@@ -28,7 +28,7 @@
* The part 'INIT' gives a new way of initializing a collection. The collection
* struct is not heap allocated, only its internal structure (nodes, buffers).
*/
-#ifdef CMC_EXT_STACK_INIT
+#ifdef CMC_EXT_INIT
struct SNAME CMC_(PFX, _init)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val)
{
@@ -77,14 +77,14 @@ void CMC_(PFX, _release)(struct SNAME _stack_)
_stack_.alloc->free(_stack_.buffer);
}
-#endif /* CMC_EXT_STACK_INIT */
+#endif /* CMC_EXT_INIT */
/**
* ITER
*
* Stack bi-directional iterator.
*/
-#ifdef CMC_EXT_STACK_ITER
+#ifdef CMC_EXT_ITER
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target)
{
@@ -270,14 +270,14 @@ size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter)
return iter->target->count - 1 - iter->cursor;
}
-#endif /* CMC_EXT_STACK_ITER */
+#endif /* CMC_EXT_ITER */
/**
* STR
*
* Print helper functions.
*/
-#ifdef CMC_EXT_STACK_STR
+#ifdef CMC_EXT_STR
bool CMC_(PFX, _to_string)(struct SNAME *_stack_, FILE *fptr)
{
@@ -315,4 +315,4 @@ bool CMC_(PFX, _print)(struct SNAME *_stack_, FILE *fptr, const char *start, con
return true;
}
-#endif /* CMC_EXT_STACK_STR */
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/stack/ext/header.h b/src/cmc/cmc/stack/ext/header.h
index bb8f372..e94db40 100644
--- a/src/cmc/cmc/stack/ext/header.h
+++ b/src/cmc/cmc/stack/ext/header.h
@@ -28,21 +28,21 @@
* The part 'INIT' gives a new way of initializing a collection. The collection
* struct is not heap allocated, only its internal structure (nodes, buffers).
*/
-#ifdef CMC_EXT_STACK_INIT
+#ifdef CMC_EXT_INIT
struct SNAME CMC_(PFX, _init)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val);
struct SNAME CMC_(PFX, _init_custom)(size_t capacity, struct CMC_DEF_FVAL(SNAME) * f_val,
struct CMC_ALLOC_NODE_NAME *alloc, struct CMC_CALLBACKS_NAME *callbacks);
void CMC_(PFX, _release)(struct SNAME _stack_);
-#endif /* CMC_EXT_STACK_INIT */
+#endif /* CMC_EXT_INIT */
/**
* ITER
*
* Stack bi-directional iterator.
*/
-#ifdef CMC_EXT_STACK_ITER
+#ifdef CMC_EXT_ITER
/* Iterator Initialization */
struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target);
@@ -63,18 +63,18 @@ V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter);
V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter);
size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
-#endif /* CMC_EXT_STACK_ITER */
+#endif /* CMC_EXT_ITER */
/**
* STR
*
* Print helper functions.
*/
-#ifdef CMC_EXT_STACK_STR
+#ifdef CMC_EXT_STR
/* Debug prints the struct to fptr */
bool CMC_(PFX, _to_string)(struct SNAME *_stack_, FILE *fptr);
/* Prints each item in the stack as an array */
bool CMC_(PFX, _print)(struct SNAME *_stack_, FILE *fptr, const char *start, const char *separator, const char *end);
-#endif /* CMC_EXT_STACK_STR */
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/stack/ext/struct.h b/src/cmc/cmc/stack/ext/struct.h
index 81e7afd..bc275bc 100644
--- a/src/cmc/cmc/stack/ext/struct.h
+++ b/src/cmc/cmc/stack/ext/struct.h
@@ -27,7 +27,7 @@
*
* Stack bi-directional iterator.
*/
-#ifdef CMC_EXT_STACK_ITER
+#ifdef CMC_EXT_ITER
/* Stack Iterator */
struct CMC_DEF_ITER(SNAME)
@@ -42,4 +42,4 @@ struct CMC_DEF_ITER(SNAME)
bool end;
};
-#endif /* CMC_EXT_STACK_ITER */
+#endif /* CMC_EXT_ITER */
diff --git a/src/cmc/cmc/treemap/code.h b/src/cmc/cmc/treemap/code.h
new file mode 100644
index 0000000..7697dbe
--- /dev/null
+++ b/src/cmc/cmc/treemap/code.h
@@ -0,0 +1,777 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* Implementation Detail Functions */
+static struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _impl_new_node)(struct SNAME *_map_, K key, V value);
+static struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _impl_get_node)(struct SNAME *_map_, K key);
+static unsigned char CMC_(PFX, _impl_h)(struct CMC_DEF_NODE(SNAME) * node);
+static unsigned char CMC_(PFX, _impl_hupdate)(struct CMC_DEF_NODE(SNAME) * node);
+static void CMC_(PFX, _impl_rotate_right)(struct CMC_DEF_NODE(SNAME) * *Z);
+static void CMC_(PFX, _impl_rotate_left)(struct CMC_DEF_NODE(SNAME) * *Z);
+static void CMC_(PFX, _impl_rebalance)(struct SNAME *_map_, struct CMC_DEF_NODE(SNAME) * node);
+
+struct SNAME *CMC_(PFX, _new)(struct CMC_DEF_FKEY(SNAME) * f_key, struct CMC_DEF_FVAL(SNAME) * f_val)
+{
+ return CMC_(PFX, _new_custom)(f_key, f_val, NULL, NULL);
+}
+
+struct SNAME *CMC_(PFX, _new_custom)(struct CMC_DEF_FKEY(SNAME) * f_key, struct CMC_DEF_FVAL(SNAME) * f_val,
+ struct CMC_ALLOC_NODE_NAME *alloc, struct CMC_CALLBACKS_NAME *callbacks)
+{
+ CMC_CALLBACKS_MAYBE_UNUSED(callbacks);
+
+ if (!f_key || !f_val)
+ return NULL;
+
+ if (!alloc)
+ alloc = &cmc_alloc_node_default;
+
+ struct SNAME *_map_ = alloc->malloc(sizeof(struct SNAME));
+
+ if (!_map_)
+ return NULL;
+
+ _map_->count = 0;
+ _map_->root = NULL;
+ _map_->flag = CMC_FLAG_OK;
+ _map_->f_key = f_key;
+ _map_->f_val = f_val;
+ _map_->alloc = alloc;
+ CMC_CALLBACKS_ASSIGN(_map_, callbacks);
+
+ return _map_;
+}
+
+void CMC_(PFX, _clear)(struct SNAME *_map_)
+{
+ struct CMC_DEF_NODE(SNAME) *scan = _map_->root;
+ struct CMC_DEF_NODE(SNAME) *up = NULL;
+
+ while (scan != NULL)
+ {
+ if (scan->left != NULL)
+ {
+ struct CMC_DEF_NODE(SNAME) *left = scan->left;
+
+ scan->left = up;
+ up = scan;
+ scan = left;
+ }
+ else if (scan->right != NULL)
+ {
+ struct CMC_DEF_NODE(SNAME) *right = scan->right;
+
+ scan->left = up;
+ scan->right = NULL;
+ up = scan;
+ scan = right;
+ }
+ else
+ {
+ if (up == NULL)
+ {
+ if (_map_->f_key->free)
+ _map_->f_key->free(scan->key);
+ if (_map_->f_val->free)
+ _map_->f_val->free(scan->value);
+
+ _map_->alloc->free(scan);
+ scan = NULL;
+ }
+
+ while (up != NULL)
+ {
+ if (_map_->f_key->free)
+ _map_->f_key->free(scan->key);
+ if (_map_->f_val->free)
+ _map_->f_val->free(scan->value);
+
+ _map_->alloc->free(scan);
+
+ if (up->right != NULL)
+ {
+ scan = up->right;
+ up->right = NULL;
+ break;
+ }
+ else
+ {
+ scan = up;
+ up = up->left;
+ }
+ }
+ }
+ }
+
+ _map_->count = 0;
+ _map_->root = NULL;
+ _map_->flag = CMC_FLAG_OK;
+}
+
+void CMC_(PFX, _free)(struct SNAME *_map_)
+{
+ CMC_(PFX, _clear)(_map_);
+
+ _map_->alloc->free(_map_);
+}
+
+void CMC_(PFX, _customize)(struct SNAME *_map_, struct CMC_ALLOC_NODE_NAME *alloc, struct CMC_CALLBACKS_NAME *callbacks)
+{
+ CMC_CALLBACKS_MAYBE_UNUSED(callbacks);
+
+ if (!alloc)
+ _map_->alloc = &cmc_alloc_node_default;
+ else
+ _map_->alloc = alloc;
+
+ CMC_CALLBACKS_ASSIGN(_map_, callbacks);
+
+ _map_->flag = CMC_FLAG_OK;
+}
+
+bool CMC_(PFX, _insert)(struct SNAME *_map_, K key, V value)
+{
+ if (CMC_(PFX, _empty)(_map_))
+ {
+ _map_->root = CMC_(PFX, _impl_new_node)(_map_, key, value);
+
+ if (!_map_->root)
+ {
+ _map_->flag = CMC_FLAG_ALLOC;
+ return false;
+ }
+ }
+ else
+ {
+ struct CMC_DEF_NODE(SNAME) *scan = _map_->root;
+ struct CMC_DEF_NODE(SNAME) *parent = scan;
+
+ while (scan != NULL)
+ {
+ parent = scan;
+
+ if (_map_->f_key->cmp(scan->key, key) > 0)
+ scan = scan->left;
+ else if (_map_->f_key->cmp(scan->key, key) < 0)
+ scan = scan->right;
+ else
+ {
+ _map_->flag = CMC_FLAG_DUPLICATE;
+ return false;
+ }
+ }
+
+ struct CMC_DEF_NODE(SNAME) * node;
+
+ if (_map_->f_key->cmp(parent->key, key) > 0)
+ {
+ parent->left = CMC_(PFX, _impl_new_node)(_map_, key, value);
+
+ if (!parent->left)
+ {
+ _map_->flag = CMC_FLAG_ALLOC;
+ return false;
+ }
+
+ parent->left->parent = parent;
+ node = parent->left;
+ }
+ else
+ {
+ parent->right = CMC_(PFX, _impl_new_node)(_map_, key, value);
+
+ if (!parent->right)
+ {
+ _map_->flag = CMC_FLAG_ALLOC;
+ return false;
+ }
+
+ parent->right->parent = parent;
+ node = parent->right;
+ }
+
+ CMC_(PFX, _impl_rebalance)(_map_, node);
+ }
+
+ _map_->count++;
+ _map_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_map_, create);
+
+ return true;
+}
+
+bool CMC_(PFX, _update)(struct SNAME *_map_, K key, V new_value, V *old_value)
+{
+ struct CMC_DEF_NODE(SNAME) *node = CMC_(PFX, _impl_get_node)(_map_, key);
+
+ if (!node)
+ {
+ _map_->flag = CMC_FLAG_NOT_FOUND;
+ return false;
+ }
+
+ if (old_value)
+ *old_value = node->value;
+
+ node->value = new_value;
+
+ _map_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_map_, update);
+
+ return true;
+}
+
+bool CMC_(PFX, _remove)(struct SNAME *_map_, K key, V *out_value)
+{
+ if (CMC_(PFX, _empty)(_map_))
+ {
+ _map_->flag = CMC_FLAG_EMPTY;
+ return false;
+ }
+
+ struct CMC_DEF_NODE(SNAME) *node = CMC_(PFX, _impl_get_node)(_map_, key);
+
+ if (!node)
+ {
+ _map_->flag = CMC_FLAG_NOT_FOUND;
+ return false;
+ }
+
+ if (out_value)
+ *out_value = node->value;
+
+ struct CMC_DEF_NODE(SNAME) *temp = NULL, *unbalanced = NULL;
+
+ bool is_root = node->parent == NULL;
+
+ if (node->left == NULL && node->right == NULL)
+ {
+ if (is_root)
+ _map_->root = NULL;
+ else
+ {
+ unbalanced = node->parent;
+
+ if (node->parent->right == node)
+ node->parent->right = NULL;
+ else
+ node->parent->left = NULL;
+ }
+
+ _map_->alloc->free(node);
+ }
+ else if (node->left == NULL)
+ {
+ if (is_root)
+ {
+ _map_->root = node->right;
+ _map_->root->parent = NULL;
+ }
+ else
+ {
+ unbalanced = node->parent;
+
+ node->right->parent = node->parent;
+
+ if (node->parent->right == node)
+ node->parent->right = node->right;
+ else
+ node->parent->left = node->right;
+ }
+
+ _map_->alloc->free(node);
+ }
+ else if (node->right == NULL)
+ {
+ if (is_root)
+ {
+ _map_->root = node->left;
+ _map_->root->parent = NULL;
+ }
+ else
+ {
+ unbalanced = node->parent;
+
+ node->left->parent = node->parent;
+
+ if (node->parent->right == node)
+ node->parent->right = node->left;
+ else
+ node->parent->left = node->left;
+ }
+
+ _map_->alloc->free(node);
+ }
+ else
+ {
+ temp = node->right;
+ while (temp->left != NULL)
+ temp = temp->left;
+
+ K temp_key = temp->key;
+ V temp_val = temp->value;
+
+ unbalanced = temp->parent;
+
+ if (temp->left == NULL && temp->right == NULL)
+ {
+ if (temp->parent->right == temp)
+ temp->parent->right = NULL;
+ else
+ temp->parent->left = NULL;
+ }
+ else if (temp->left == NULL)
+ {
+ temp->right->parent = temp->parent;
+
+ if (temp->parent->right == temp)
+ temp->parent->right = temp->right;
+ else
+ temp->parent->left = temp->right;
+ }
+ else if (temp->right == NULL)
+ {
+ temp->left->parent = temp->parent;
+
+ if (temp->parent->right == temp)
+ temp->parent->right = temp->left;
+ else
+ temp->parent->left = temp->left;
+ }
+
+ _map_->alloc->free(temp);
+
+ node->key = temp_key;
+ node->value = temp_val;
+ }
+
+ if (unbalanced != NULL)
+ CMC_(PFX, _impl_rebalance)(_map_, unbalanced);
+
+ if (_map_->count == 0)
+ _map_->root = NULL;
+
+ _map_->count--;
+ _map_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_map_, delete);
+
+ return true;
+}
+
+bool CMC_(PFX, _max)(struct SNAME *_map_, K *key, V *value)
+{
+ if (CMC_(PFX, _empty)(_map_))
+ {
+ _map_->flag = CMC_FLAG_EMPTY;
+ return false;
+ }
+
+ struct CMC_DEF_NODE(SNAME) *scan = _map_->root;
+
+ while (scan->right != NULL)
+ scan = scan->right;
+
+ if (key)
+ *key = scan->key;
+ if (value)
+ *value = scan->value;
+
+ _map_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_map_, read);
+
+ return true;
+}
+
+bool CMC_(PFX, _min)(struct SNAME *_map_, K *key, V *value)
+{
+ if (CMC_(PFX, _empty)(_map_))
+ {
+ _map_->flag = CMC_FLAG_EMPTY;
+ return false;
+ }
+
+ struct CMC_DEF_NODE(SNAME) *scan = _map_->root;
+
+ while (scan->left != NULL)
+ scan = scan->left;
+
+ if (key)
+ *key = scan->key;
+ if (value)
+ *value = scan->value;
+
+ _map_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_map_, read);
+
+ return true;
+}
+
+V CMC_(PFX, _get)(struct SNAME *_map_, K key)
+{
+ if (CMC_(PFX, _empty)(_map_))
+ {
+ _map_->flag = CMC_FLAG_EMPTY;
+ return (V){ 0 };
+ }
+
+ struct CMC_DEF_NODE(SNAME) *node = CMC_(PFX, _impl_get_node)(_map_, key);
+
+ if (!node)
+ {
+ _map_->flag = CMC_FLAG_NOT_FOUND;
+ return (V){ 0 };
+ }
+
+ _map_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_map_, read);
+
+ return node->value;
+}
+
+V *CMC_(PFX, _get_ref)(struct SNAME *_map_, K key)
+{
+ if (CMC_(PFX, _empty)(_map_))
+ {
+ _map_->flag = CMC_FLAG_EMPTY;
+ return NULL;
+ }
+
+ struct CMC_DEF_NODE(SNAME) *node = CMC_(PFX, _impl_get_node)(_map_, key);
+
+ if (!node)
+ {
+ _map_->flag = CMC_FLAG_NOT_FOUND;
+ return NULL;
+ }
+
+ _map_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_map_, read);
+
+ return &(node->value);
+}
+
+bool CMC_(PFX, _contains)(struct SNAME *_map_, K key)
+{
+ bool result = CMC_(PFX, _impl_get_node)(_map_, key) != NULL;
+
+ CMC_CALLBACKS_CALL(_map_, read);
+
+ return result;
+}
+
+bool CMC_(PFX, _empty)(struct SNAME *_map_)
+{
+ return _map_->count == 0;
+}
+
+size_t CMC_(PFX, _count)(struct SNAME *_map_)
+{
+ return _map_->count;
+}
+
+int CMC_(PFX, _flag)(struct SNAME *_map_)
+{
+ return _map_->flag;
+}
+
+struct SNAME *CMC_(PFX, _copy_of)(struct SNAME *_map_)
+{
+ /* Callback will be added later */
+ struct SNAME *result = CMC_(PFX, _new_custom)(_map_->f_key, _map_->f_val, _map_->alloc, NULL);
+
+ if (!result)
+ {
+ _map_->flag = CMC_FLAG_ERROR;
+ return NULL;
+ }
+
+ struct CMC_DEF_NODE(SNAME) *root = _map_->root;
+
+ bool left_done = false;
+
+ while (root)
+ {
+ if (!left_done)
+ {
+ while (root->left)
+ root = root->left;
+ }
+
+ K key;
+ V value;
+
+ if (_map_->f_key->cpy)
+ key = _map_->f_key->cpy(root->key);
+ else
+ key = root->key;
+ if (_map_->f_val->cpy)
+ value = _map_->f_val->cpy(root->value);
+ else
+ value = root->value;
+
+ /* TODO check this for errors */
+ CMC_(PFX, _insert)(result, key, value);
+
+ left_done = true;
+
+ if (root->right)
+ {
+ left_done = false;
+ root = root->right;
+ }
+ else if (root->parent)
+ {
+ while (root->parent && root == root->parent->right)
+ root = root->parent;
+
+ if (!root->parent)
+ break;
+
+ root = root->parent;
+ }
+ else
+ break;
+ }
+
+ _map_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_ASSIGN(result, _map_->callbacks);
+
+ return result;
+}
+
+bool CMC_(PFX, _equals)(struct SNAME *_map1_, struct SNAME *_map2_)
+{
+ _map1_->flag = CMC_FLAG_OK;
+ _map2_->flag = CMC_FLAG_OK;
+
+ if (_map1_->count != _map2_->count)
+ return false;
+
+ struct CMC_DEF_NODE(SNAME) *root = _map1_->root;
+
+ bool left_done = false;
+
+ while (root)
+ {
+ if (!left_done)
+ {
+ while (root->left)
+ root = root->left;
+ }
+
+ /* TODO this can be optimized by doing two in-order traversals */
+ struct CMC_DEF_NODE(SNAME) *node = CMC_(PFX, _impl_get_node)(_map2_, root->key);
+
+ if (node == NULL)
+ return false;
+
+ if (_map1_->f_val->cmp(node->value, root->value) != 0)
+ return false;
+
+ left_done = true;
+
+ if (root->right)
+ {
+ left_done = false;
+ root = root->right;
+ }
+ else if (root->parent)
+ {
+ while (root->parent && root == root->parent->right)
+ root = root->parent;
+
+ if (!root->parent)
+ break;
+
+ root = root->parent;
+ }
+ else
+ break;
+ }
+
+ return true;
+}
+
+static struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _impl_new_node)(struct SNAME *_map_, K key, V value)
+{
+ struct CMC_DEF_NODE(SNAME) *node = _map_->alloc->malloc(sizeof(struct CMC_DEF_NODE(SNAME)));
+
+ if (!node)
+ return NULL;
+
+ node->key = key;
+ node->value = value;
+ node->right = NULL;
+ node->left = NULL;
+ node->parent = NULL;
+ node->height = 0;
+
+ return node;
+}
+
+static struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _impl_get_node)(struct SNAME *_map_, K key)
+{
+ struct CMC_DEF_NODE(SNAME) *scan = _map_->root;
+
+ while (scan != NULL)
+ {
+ if (_map_->f_key->cmp(scan->key, key) > 0)
+ scan = scan->left;
+ else if (_map_->f_key->cmp(scan->key, key) < 0)
+ scan = scan->right;
+ else
+ return scan;
+ }
+
+ return NULL;
+}
+
+static unsigned char CMC_(PFX, _impl_h)(struct CMC_DEF_NODE(SNAME) * node)
+{
+ if (node == NULL)
+ return 0;
+
+ return node->height;
+}
+
+static unsigned char CMC_(PFX, _impl_hupdate)(struct CMC_DEF_NODE(SNAME) * node)
+{
+ if (node == NULL)
+ return 0;
+
+ unsigned char h_l = CMC_(PFX, _impl_h)(node->left);
+ unsigned char h_r = CMC_(PFX, _impl_h)(node->right);
+
+ return 1 + (h_l > h_r ? h_l : h_r);
+}
+
+static void CMC_(PFX, _impl_rotate_right)(struct CMC_DEF_NODE(SNAME) * *Z)
+{
+ struct CMC_DEF_NODE(SNAME) *root = *Z;
+ struct CMC_DEF_NODE(SNAME) *new_root = root->left;
+
+ if (root->parent != NULL)
+ {
+ if (root->parent->left == root)
+ root->parent->left = new_root;
+ else
+ root->parent->right = new_root;
+ }
+
+ new_root->parent = root->parent;
+
+ root->parent = new_root;
+ root->left = new_root->right;
+
+ if (root->left)
+ root->left->parent = root;
+
+ new_root->right = root;
+
+ root->height = CMC_(PFX, _impl_hupdate)(root);
+ new_root->height = CMC_(PFX, _impl_hupdate)(new_root);
+
+ *Z = new_root;
+}
+
+static void CMC_(PFX, _impl_rotate_left)(struct CMC_DEF_NODE(SNAME) * *Z)
+{
+ struct CMC_DEF_NODE(SNAME) *root = *Z;
+ struct CMC_DEF_NODE(SNAME) *new_root = root->right;
+
+ if (root->parent != NULL)
+ {
+ if (root->parent->right == root)
+ root->parent->right = new_root;
+ else
+ root->parent->left = new_root;
+ }
+
+ new_root->parent = root->parent;
+
+ root->parent = new_root;
+ root->right = new_root->left;
+
+ if (root->right)
+ root->right->parent = root;
+
+ new_root->left = root;
+
+ root->height = CMC_(PFX, _impl_hupdate)(root);
+ new_root->height = CMC_(PFX, _impl_hupdate)(new_root);
+
+ *Z = new_root;
+}
+
+static void CMC_(PFX, _impl_rebalance)(struct SNAME *_map_, struct CMC_DEF_NODE(SNAME) * node)
+{
+ struct CMC_DEF_NODE(SNAME) *scan = node, *child = NULL;
+
+ int balance;
+ bool is_root = false;
+
+ while (scan != NULL)
+ {
+ if (scan->parent == NULL)
+ is_root = true;
+
+ scan->height = CMC_(PFX, _impl_hupdate)(scan);
+ balance = CMC_(PFX, _impl_h)(scan->right) - CMC_(PFX, _impl_h)(scan->left);
+
+ if (balance >= 2)
+ {
+ child = scan->right;
+
+ if (CMC_(PFX, _impl_h)(child->right) < CMC_(PFX, _impl_h)(child->left))
+ CMC_(PFX, _impl_rotate_right)(&(scan->right));
+
+ CMC_(PFX, _impl_rotate_left)(&scan);
+ }
+ else if (balance <= -2)
+ {
+ child = scan->left;
+
+ if (CMC_(PFX, _impl_h)(child->left) < CMC_(PFX, _impl_h)(child->right))
+ CMC_(PFX, _impl_rotate_left)(&(scan->left));
+
+ CMC_(PFX, _impl_rotate_right)(&scan);
+ }
+
+ if (is_root)
+ {
+ _map_->root = scan;
+ is_root = false;
+ }
+
+ scan = scan->parent;
+ }
+}
diff --git a/src/cmc/cmc/treemap/ext/code.h b/src/cmc/cmc/treemap/ext/code.h
new file mode 100644
index 0000000..a100226
--- /dev/null
+++ b/src/cmc/cmc/treemap/ext/code.h
@@ -0,0 +1,386 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * INIT
+ *
+ * The part 'INIT' gives a new way of initializing a collection. The collection
+ * struct is not heap allocated, only its internal structure (nodes, buffers).
+ */
+#ifdef CMC_EXT_INIT
+
+#endif /* CMC_EXT_INIT */
+
+/**
+ * ITER
+ *
+ * Treemap bi-directional iterator.
+ */
+#ifdef CMC_EXT_ITER
+
+struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target)
+{
+ struct CMC_DEF_ITER(SNAME) iter;
+
+ iter.target = target;
+ iter.cursor = target->root;
+ iter.first = NULL;
+ iter.last = NULL;
+ iter.index = 0;
+ iter.start = true;
+ iter.end = CMC_(PFX, _empty)(target);
+
+ if (!CMC_(PFX, _empty)(target))
+ {
+ while (iter.cursor->left != NULL)
+ iter.cursor = iter.cursor->left;
+
+ iter.first = iter.cursor;
+
+ iter.last = target->root;
+ while (iter.last->right != NULL)
+ iter.last = iter.last->right;
+ }
+
+ return iter;
+}
+
+struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME *target)
+{
+ struct CMC_DEF_ITER(SNAME) iter;
+
+ iter.target = target;
+ iter.cursor = target->root;
+ iter.first = NULL;
+ iter.last = NULL;
+ iter.index = 0;
+ iter.start = CMC_(PFX, _empty)(target);
+ iter.end = true;
+
+ if (!CMC_(PFX, _empty)(target))
+ {
+ while (iter.cursor->right != NULL)
+ iter.cursor = iter.cursor->right;
+
+ iter.last = iter.cursor;
+
+ iter.first = target->root;
+ while (iter.first->left != NULL)
+ iter.first = iter.first->left;
+
+ iter.index = target->count - 1;
+ }
+
+ return iter;
+}
+
+bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ return CMC_(PFX, _empty)(iter->target) || iter->start;
+}
+
+bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ return CMC_(PFX, _empty)(iter->target) || iter->end;
+}
+
+bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ if (!CMC_(PFX, _empty)(iter->target))
+ {
+ iter->index = 0;
+ iter->start = true;
+ iter->end = CMC_(PFX, _empty)(iter->target);
+ iter->cursor = iter->first;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ if (!CMC_(PFX, _empty)(iter->target))
+ {
+ iter->index = iter->target->count - 1;
+ iter->start = CMC_(PFX, _empty)(iter->target);
+ iter->end = true;
+ iter->cursor = iter->last;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ if (iter->end)
+ return false;
+
+ if (iter->cursor == iter->last)
+ {
+ iter->end = true;
+ return false;
+ }
+
+ iter->start = CMC_(PFX, _empty)(iter->target);
+
+ if (iter->cursor->right != NULL)
+ {
+ iter->cursor = iter->cursor->right;
+
+ while (iter->cursor->left != NULL)
+ iter->cursor = iter->cursor->left;
+
+ iter->index++;
+
+ return true;
+ }
+
+ while (true)
+ {
+ if (iter->cursor->parent->left == iter->cursor)
+ {
+ iter->cursor = iter->cursor->parent;
+
+ iter->index++;
+
+ return true;
+ }
+
+ iter->cursor = iter->cursor->parent;
+ }
+}
+
+bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ if (iter->start)
+ return false;
+
+ if (iter->cursor == iter->first)
+ {
+ iter->start = true;
+ return false;
+ }
+
+ iter->end = CMC_(PFX, _empty)(iter->target);
+
+ if (iter->cursor->left != NULL)
+ {
+ iter->cursor = iter->cursor->left;
+
+ while (iter->cursor->right != NULL)
+ iter->cursor = iter->cursor->right;
+
+ iter->index--;
+
+ return true;
+ }
+
+ while (true)
+ {
+ if (iter->cursor->parent->right == iter->cursor)
+ {
+ iter->cursor = iter->cursor->parent;
+
+ iter->index--;
+
+ return true;
+ }
+
+ iter->cursor = iter->cursor->parent;
+ }
+}
+
+/* Returns true only if the iterator moved */
+bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps)
+{
+ if (iter->end)
+ return false;
+
+ if (iter->cursor == iter->last)
+ {
+ iter->end = true;
+ return false;
+ }
+
+ if (steps == 0 || iter->index + steps >= iter->target->count)
+ return false;
+
+ for (size_t i = 0; i < steps; i++)
+ CMC_(PFX, _iter_next)(iter);
+
+ return true;
+}
+
+/* Returns true only if the iterator moved */
+bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps)
+{
+ if (iter->start)
+ return false;
+
+ if (iter->cursor == iter->first)
+ {
+ iter->start = true;
+ return false;
+ }
+
+ if (steps == 0 || iter->index < steps)
+ return false;
+
+ for (size_t i = 0; i < steps; i++)
+ CMC_(PFX, _iter_prev)(iter);
+
+ return true;
+}
+
+/* Returns true only if the iterator was able to be positioned at the */
+/* given index */
+bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index)
+{
+ if (index >= iter->target->count)
+ return false;
+
+ if (iter->index > index)
+ return CMC_(PFX, _iter_rewind)(iter, iter->index - index);
+ else if (iter->index < index)
+ return CMC_(PFX, _iter_advance)(iter, index - iter->index);
+
+ return true;
+}
+
+K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ if (CMC_(PFX, _empty)(iter->target))
+ return (K){ 0 };
+
+ return iter->cursor->key;
+}
+
+V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ if (CMC_(PFX, _empty)(iter->target))
+ return (V){ 0 };
+
+ return iter->cursor->value;
+}
+
+V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ if (CMC_(PFX, _empty)(iter->target))
+ return NULL;
+
+ return &(iter->cursor->value);
+}
+
+size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ return iter->index;
+}
+
+#endif /* CMC_EXT_ITER */
+
+/**
+ * STR
+ *
+ * Print helper functions.
+ */
+#ifdef CMC_EXT_STR
+
+bool CMC_(PFX, _to_string)(struct SNAME *_map_, FILE *fptr)
+{
+ struct SNAME *m_ = _map_;
+
+ return 0 <= fprintf(fptr,
+ "struct %s<%s, %s> "
+ "at %p { "
+ "root:%p, "
+ "count:%" PRIuMAX ", "
+ "flag:%d, "
+ "f_val:%p, "
+ "f_key:%p, "
+ "alloc:%p, "
+ "callbacks:%p }",
+ CMC_TO_STRING(SNAME), CMC_TO_STRING(K), CMC_TO_STRING(V), m_, m_->root, m_->count, m_->flag,
+ m_->f_key, m_->f_val, m_->alloc, CMC_CALLBACKS_GET(m_));
+}
+
+bool CMC_(PFX, _print)(struct SNAME *_map_, FILE *fptr, const char *start, const char *separator, const char *end,
+ const char *key_val_sep)
+{
+ fprintf(fptr, "%s", start);
+
+ struct CMC_DEF_NODE(SNAME) *root = _map_->root;
+
+ bool left_done = false;
+
+ size_t i = 0;
+ while (root)
+ {
+ if (!left_done)
+ {
+ while (root->left)
+ root = root->left;
+ }
+
+ if (!_map_->f_key->str(fptr, root->key))
+ return false;
+
+ fprintf(fptr, "%s", key_val_sep);
+
+ if (!_map_->f_val->str(fptr, root->value))
+ return false;
+
+ if (++i < _map_->count)
+ fprintf(fptr, "%s", separator);
+
+ left_done = true;
+
+ if (root->right)
+ {
+ left_done = false;
+ root = root->right;
+ }
+ else if (root->parent)
+ {
+ while (root->parent && root == root->parent->right)
+ root = root->parent;
+
+ if (!root->parent)
+ break;
+
+ root = root->parent;
+ }
+ else
+ break;
+ }
+
+ fprintf(fptr, "%s", end);
+
+ return true;
+}
+
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/treemap/ext/header.h b/src/cmc/cmc/treemap/ext/header.h
new file mode 100644
index 0000000..1e11696
--- /dev/null
+++ b/src/cmc/cmc/treemap/ext/header.h
@@ -0,0 +1,94 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * INIT
+ *
+ * The part 'INIT' gives a new way of initializing a collection. The collection
+ * struct is not heap allocated, only its internal structure (nodes, buffers).
+ */
+#ifdef CMC_EXT_INIT
+
+#endif /* CMC_EXT_INIT */
+
+/**
+ * ITER
+ *
+ * Treemap bi-directional iterator.
+ */
+#ifdef CMC_EXT_ITER
+
+/* Treemap Iterator */
+struct CMC_DEF_ITER(SNAME)
+{
+ /* Target treemap */
+ struct SNAME *target;
+ /* Cursor's current node */
+ struct CMC_DEF_NODE(SNAME) * cursor;
+ /* The first node in the iteration */
+ struct CMC_DEF_NODE(SNAME) * first;
+ /* The last node in the iteration */
+ struct CMC_DEF_NODE(SNAME) * last;
+ /* Keeps track of relative index to the iteration of elements */
+ size_t index;
+ /* If the iterator has reached the start of the iteration */
+ bool start;
+ /* If the iterator has reached the end of the iteration */
+ bool end;
+};
+
+/* Iterator Initialization */
+struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target);
+struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME *target);
+/* Iterator State */
+bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter);
+bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter);
+/* Iterator Movement */
+bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter);
+bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter);
+bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter);
+bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter);
+bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps);
+bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps);
+bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index);
+/* Iterator Access */
+K CMC_(PFX, _iter_key)(struct CMC_DEF_ITER(SNAME) * iter);
+V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter);
+V *CMC_(PFX, _iter_rvalue)(struct CMC_DEF_ITER(SNAME) * iter);
+size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
+
+#endif /* CMC_EXT_ITER */
+
+/**
+ * STR
+ *
+ * Print helper functions.
+ */
+#ifdef CMC_EXT_STR
+
+bool CMC_(PFX, _to_string)(struct SNAME *_map_, FILE *fptr);
+bool CMC_(PFX, _print)(struct SNAME *_map_, FILE *fptr, const char *start, const char *separator, const char *end,
+ const char *key_val_sep);
+
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/treemap/ext/struct.h b/src/cmc/cmc/treemap/ext/struct.h
new file mode 100644
index 0000000..59c5376
--- /dev/null
+++ b/src/cmc/cmc/treemap/ext/struct.h
@@ -0,0 +1,23 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
diff --git a/src/cmc/cmc/treemap/header.h b/src/cmc/cmc/treemap/header.h
new file mode 100644
index 0000000..7af9f27
--- /dev/null
+++ b/src/cmc/cmc/treemap/header.h
@@ -0,0 +1,85 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* Key struct function table */
+struct CMC_DEF_FKEY(SNAME)
+{
+ /* Comparator function */
+ CMC_DEF_FTAB_CMP(K);
+ /* Copy function */
+ CMC_DEF_FTAB_CPY(K);
+ /* To string function */
+ CMC_DEF_FTAB_STR(K);
+ /* Free from memory function */
+ CMC_DEF_FTAB_FREE(K);
+ /* Hash function */
+ CMC_DEF_FTAB_HASH(K);
+ /* Priority function */
+ CMC_DEF_FTAB_PRI(K);
+};
+
+/* Value struct function table */
+struct CMC_DEF_FVAL(SNAME)
+{
+ /* Comparator function */
+ CMC_DEF_FTAB_CMP(V);
+ /* Copy function */
+ CMC_DEF_FTAB_CPY(V);
+ /* To string function */
+ CMC_DEF_FTAB_STR(V);
+ /* Free from memory function */
+ CMC_DEF_FTAB_FREE(V);
+ /* Hash function */
+ CMC_DEF_FTAB_HASH(V);
+ /* Priority function */
+ CMC_DEF_FTAB_PRI(V);
+};
+
+/* Collection Functions */
+/* Collection Allocation and Deallocation */
+struct SNAME *CMC_(PFX, _new)(struct CMC_DEF_FKEY(SNAME) * f_key, struct CMC_DEF_FVAL(SNAME) * f_val);
+struct SNAME *CMC_(PFX, _new_custom)(struct CMC_DEF_FKEY(SNAME) * f_key, struct CMC_DEF_FVAL(SNAME) * f_val,
+ struct CMC_ALLOC_NODE_NAME *alloc, struct CMC_CALLBACKS_NAME *callbacks);
+void CMC_(PFX, _clear)(struct SNAME *_map_);
+void CMC_(PFX, _free)(struct SNAME *_map_);
+/* Customization of Allocation and Callbacks */
+void CMC_(PFX, _customize)(struct SNAME *_map_, struct CMC_ALLOC_NODE_NAME *alloc,
+ struct CMC_CALLBACKS_NAME *callbacks);
+/* Collection Input and Output */
+bool CMC_(PFX, _insert)(struct SNAME *_map_, K key, V value);
+bool CMC_(PFX, _update)(struct SNAME *_map_, K key, V new_value, V *old_value);
+bool CMC_(PFX, _remove)(struct SNAME *_map_, K key, V *out_value);
+/* Element Access */
+bool CMC_(PFX, _max)(struct SNAME *_map_, K *key, V *value);
+bool CMC_(PFX, _min)(struct SNAME *_map_, K *key, V *value);
+V CMC_(PFX, _get)(struct SNAME *_map_, K key);
+V *CMC_(PFX, _get_ref)(struct SNAME *_map_, K key);
+/* Collection State */
+bool CMC_(PFX, _contains)(struct SNAME *_map_, K key);
+bool CMC_(PFX, _empty)(struct SNAME *_map_);
+size_t CMC_(PFX, _count)(struct SNAME *_map_);
+int CMC_(PFX, _flag)(struct SNAME *_map_);
+/* Collection Utility */
+struct SNAME *CMC_(PFX, _copy_of)(struct SNAME *_map_);
+bool CMC_(PFX, _equals)(struct SNAME *_map1_, struct SNAME *_map2_);
diff --git a/src/cmc/cmc/treemap/struct.h b/src/cmc/cmc/treemap/struct.h
new file mode 100644
index 0000000..fcaa75e
--- /dev/null
+++ b/src/cmc/cmc/treemap/struct.h
@@ -0,0 +1,70 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* Treemap Structure */
+struct SNAME
+{
+ /* Root node */
+ struct CMC_DEF_NODE(SNAME) * root;
+
+ /* Current amount of keys */
+ size_t count;
+
+ /* Flags indicating errors or success */
+ int flag;
+
+ /* Key function table */
+ struct CMC_DEF_FKEY(SNAME) * f_key;
+
+ /* Value function table */
+ struct CMC_DEF_FVAL(SNAME) * f_val;
+
+ /* Custom allocation functions */
+ struct CMC_ALLOC_NODE_NAME *alloc;
+
+ /* Custom callback functions */
+ CMC_CALLBACKS_DECL;
+};
+
+/* Treemap Node */
+struct CMC_DEF_NODE(SNAME)
+{
+ /* Node Key */
+ K key;
+
+ /* Node Value */
+ V value;
+
+ /* Node height used by the AVL tree to keep it strictly balanced */
+ unsigned char height;
+
+ /* Right child node or subtree */
+ struct CMC_DEF_NODE(SNAME) * right;
+
+ /* Left child node or subtree */
+ struct CMC_DEF_NODE(SNAME) * left;
+
+ /* Parent node */
+ struct CMC_DEF_NODE(SNAME) * parent;
+};
diff --git a/src/cmc/cmc/treeset/code.h b/src/cmc/cmc/treeset/code.h
new file mode 100644
index 0000000..a444938
--- /dev/null
+++ b/src/cmc/cmc/treeset/code.h
@@ -0,0 +1,686 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* Implementation Detail Functions */
+static struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _impl_new_node)(struct SNAME *_set_, V value);
+static struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _impl_get_node)(struct SNAME *_set_, V value);
+static unsigned char CMC_(PFX, _impl_h)(struct CMC_DEF_NODE(SNAME) * node);
+static unsigned char CMC_(PFX, _impl_hupdate)(struct CMC_DEF_NODE(SNAME) * node);
+static void CMC_(PFX, _impl_rotate_right)(struct CMC_DEF_NODE(SNAME) * *Z);
+static void CMC_(PFX, _impl_rotate_left)(struct CMC_DEF_NODE(SNAME) * *Z);
+static void CMC_(PFX, _impl_rebalance)(struct SNAME *_set_, struct CMC_DEF_NODE(SNAME) * node);
+
+struct SNAME *CMC_(PFX, _new)(struct CMC_DEF_FVAL(SNAME) * f_val)
+{
+ return CMC_(PFX, _new_custom)(f_val, NULL, NULL);
+}
+
+struct SNAME *CMC_(PFX, _new_custom)(struct CMC_DEF_FVAL(SNAME) * f_val, struct CMC_ALLOC_NODE_NAME *alloc,
+ struct CMC_CALLBACKS_NAME *callbacks)
+{
+ CMC_CALLBACKS_MAYBE_UNUSED(callbacks);
+
+ if (!f_val)
+ return NULL;
+
+ if (!alloc)
+ alloc = &cmc_alloc_node_default;
+
+ struct SNAME *_set_ = alloc->malloc(sizeof(struct SNAME));
+
+ if (!_set_)
+ return NULL;
+
+ _set_->count = 0;
+ _set_->root = NULL;
+ _set_->flag = CMC_FLAG_OK;
+ _set_->f_val = f_val;
+ _set_->alloc = alloc;
+ CMC_CALLBACKS_ASSIGN(_set_, callbacks);
+
+ return _set_;
+}
+
+void CMC_(PFX, _clear)(struct SNAME *_set_)
+{
+ struct CMC_DEF_NODE(SNAME) *scan = _set_->root;
+ struct CMC_DEF_NODE(SNAME) *up = NULL;
+
+ while (scan != NULL)
+ {
+ if (scan->left != NULL)
+ {
+ struct CMC_DEF_NODE(SNAME) *left = scan->left;
+
+ scan->left = up;
+ up = scan;
+ scan = left;
+ }
+ else if (scan->right != NULL)
+ {
+ struct CMC_DEF_NODE(SNAME) *right = scan->right;
+
+ scan->left = up;
+ scan->right = NULL;
+ up = scan;
+ scan = right;
+ }
+ else
+ {
+ if (up == NULL)
+ {
+ if (_set_->f_val->free)
+ _set_->f_val->free(scan->value);
+
+ _set_->alloc->free(scan);
+ scan = NULL;
+ }
+
+ while (up != NULL)
+ {
+ if (_set_->f_val->free)
+ _set_->f_val->free(scan->value);
+
+ _set_->alloc->free(scan);
+
+ if (up->right != NULL)
+ {
+ scan = up->right;
+ up->right = NULL;
+ break;
+ }
+ else
+ {
+ scan = up;
+ up = up->left;
+ }
+ }
+ }
+ }
+
+ _set_->count = 0;
+ _set_->root = NULL;
+ _set_->flag = CMC_FLAG_OK;
+}
+
+void CMC_(PFX, _free)(struct SNAME *_set_)
+{
+ CMC_(PFX, _clear)(_set_);
+
+ _set_->alloc->free(_set_);
+}
+
+void CMC_(PFX, _customize)(struct SNAME *_set_, struct CMC_ALLOC_NODE_NAME *alloc, struct CMC_CALLBACKS_NAME *callbacks)
+{
+ CMC_CALLBACKS_MAYBE_UNUSED(callbacks);
+
+ if (!alloc)
+ _set_->alloc = &cmc_alloc_node_default;
+ else
+ _set_->alloc = alloc;
+
+ CMC_CALLBACKS_ASSIGN(_set_, callbacks);
+
+ _set_->flag = CMC_FLAG_OK;
+}
+
+bool CMC_(PFX, _insert)(struct SNAME *_set_, V value)
+{
+ if (CMC_(PFX, _empty)(_set_))
+ {
+ _set_->root = CMC_(PFX, _impl_new_node)(_set_, value);
+
+ if (!_set_->root)
+ {
+ _set_->flag = CMC_FLAG_ALLOC;
+ return false;
+ }
+ }
+ else
+ {
+ struct CMC_DEF_NODE(SNAME) *scan = _set_->root;
+ struct CMC_DEF_NODE(SNAME) *parent = scan;
+
+ while (scan != NULL)
+ {
+ parent = scan;
+
+ if (_set_->f_val->cmp(scan->value, value) > 0)
+ scan = scan->left;
+ else if (_set_->f_val->cmp(scan->value, value) < 0)
+ scan = scan->right;
+ else
+ {
+ _set_->flag = CMC_FLAG_DUPLICATE;
+ return false;
+ }
+ }
+
+ struct CMC_DEF_NODE(SNAME) * node;
+
+ if (_set_->f_val->cmp(parent->value, value) > 0)
+ {
+ parent->left = CMC_(PFX, _impl_new_node)(_set_, value);
+
+ if (!parent->left)
+ {
+ _set_->flag = CMC_FLAG_ALLOC;
+ return false;
+ }
+
+ parent->left->parent = parent;
+ node = parent->left;
+ }
+ else
+ {
+ parent->right = CMC_(PFX, _impl_new_node)(_set_, value);
+
+ if (!parent->right)
+ {
+ _set_->flag = CMC_FLAG_ALLOC;
+ return false;
+ }
+
+ parent->right->parent = parent;
+ node = parent->right;
+ }
+
+ CMC_(PFX, _impl_rebalance)(_set_, node);
+ }
+
+ _set_->count++;
+ _set_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_set_, create);
+
+ return true;
+}
+
+bool CMC_(PFX, _remove)(struct SNAME *_set_, V value)
+{
+ if (CMC_(PFX, _empty)(_set_))
+ {
+ _set_->flag = CMC_FLAG_EMPTY;
+ return false;
+ }
+
+ struct CMC_DEF_NODE(SNAME) *node = CMC_(PFX, _impl_get_node)(_set_, value);
+
+ if (!node)
+ {
+ _set_->flag = CMC_FLAG_NOT_FOUND;
+ return false;
+ }
+
+ struct CMC_DEF_NODE(SNAME) *temp = NULL, *unbalanced = NULL;
+
+ bool is_root = node->parent == NULL;
+
+ if (node->left == NULL && node->right == NULL)
+ {
+ if (is_root)
+ _set_->root = NULL;
+ else
+ {
+ unbalanced = node->parent;
+
+ if (node->parent->right == node)
+ node->parent->right = NULL;
+ else
+ node->parent->left = NULL;
+ }
+
+ _set_->alloc->free(node);
+ }
+ else if (node->left == NULL)
+ {
+ if (is_root)
+ {
+ _set_->root = node->right;
+ _set_->root->parent = NULL;
+ }
+ else
+ {
+ unbalanced = node->parent;
+
+ node->right->parent = node->parent;
+
+ if (node->parent->right == node)
+ node->parent->right = node->right;
+ else
+ node->parent->left = node->right;
+ }
+
+ _set_->alloc->free(node);
+ }
+ else if (node->right == NULL)
+ {
+ if (is_root)
+ {
+ _set_->root = node->left;
+ _set_->root->parent = NULL;
+ }
+ else
+ {
+ unbalanced = node->parent;
+
+ node->left->parent = node->parent;
+
+ if (node->parent->right == node)
+ node->parent->right = node->left;
+ else
+ node->parent->left = node->left;
+ }
+
+ _set_->alloc->free(node);
+ }
+ else
+ {
+ temp = node->right;
+ while (temp->left != NULL)
+ temp = temp->left;
+
+ V temp_value = temp->value;
+
+ unbalanced = temp->parent;
+
+ if (temp->left == NULL && temp->right == NULL)
+ {
+ if (temp->parent->right == temp)
+ temp->parent->right = NULL;
+ else
+ temp->parent->left = NULL;
+ }
+ else if (temp->left == NULL)
+ {
+ temp->right->parent = temp->parent;
+
+ if (temp->parent->right == temp)
+ temp->parent->right = temp->right;
+ else
+ temp->parent->left = temp->right;
+ }
+ else if (temp->right == NULL)
+ {
+ temp->left->parent = temp->parent;
+
+ if (temp->parent->right == temp)
+ temp->parent->right = temp->left;
+ else
+ temp->parent->left = temp->left;
+ }
+
+ _set_->alloc->free(temp);
+
+ node->value = temp_value;
+ }
+
+ if (unbalanced != NULL)
+ CMC_(PFX, _impl_rebalance)(_set_, unbalanced);
+
+ if (_set_->count == 0)
+ _set_->root = NULL;
+
+ _set_->count--;
+ _set_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_set_, delete);
+
+ return true;
+}
+
+bool CMC_(PFX, _max)(struct SNAME *_set_, V *value)
+{
+ if (CMC_(PFX, _empty)(_set_))
+ {
+ _set_->flag = CMC_FLAG_EMPTY;
+ return false;
+ }
+
+ struct CMC_DEF_NODE(SNAME) *scan = _set_->root;
+
+ while (scan->right != NULL)
+ scan = scan->right;
+
+ if (value)
+ *value = scan->value;
+
+ _set_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_set_, read);
+
+ return true;
+}
+
+bool CMC_(PFX, _min)(struct SNAME *_set_, V *value)
+{
+ if (CMC_(PFX, _empty)(_set_))
+ {
+ _set_->flag = CMC_FLAG_EMPTY;
+ return false;
+ }
+
+ struct CMC_DEF_NODE(SNAME) *scan = _set_->root;
+
+ while (scan->left != NULL)
+ scan = scan->left;
+
+ if (value)
+ *value = scan->value;
+
+ _set_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_CALL(_set_, read);
+
+ return true;
+}
+
+bool CMC_(PFX, _contains)(struct SNAME *_set_, V value)
+{
+ bool result = CMC_(PFX, _impl_get_node)(_set_, value) != NULL;
+
+ CMC_CALLBACKS_CALL(_set_, read);
+
+ return result;
+}
+
+bool CMC_(PFX, _empty)(struct SNAME *_set_)
+{
+ return _set_->count == 0;
+}
+
+size_t CMC_(PFX, _count)(struct SNAME *_set_)
+{
+ return _set_->count;
+}
+
+int CMC_(PFX, _flag)(struct SNAME *_set_)
+{
+ return _set_->flag;
+}
+
+struct SNAME *CMC_(PFX, _copy_of)(struct SNAME *_set_)
+{
+ /* Callback will be added later */
+ struct SNAME *result = CMC_(PFX, _new_custom)(_set_->f_val, _set_->alloc, NULL);
+
+ if (!result)
+ {
+ _set_->flag = CMC_FLAG_ERROR;
+ return NULL;
+ }
+
+ struct CMC_DEF_NODE(SNAME) *root = _set_->root;
+
+ bool left_done = false;
+
+ while (root)
+ {
+ if (!left_done)
+ {
+ while (root->left)
+ root = root->left;
+ }
+
+ V value;
+
+ if (_set_->f_val->cpy)
+ value = _set_->f_val->cpy(root->value);
+ else
+ value = root->value;
+
+ /* TODO check this for errors */
+ CMC_(PFX, _insert)(result, value);
+
+ left_done = true;
+
+ if (root->right)
+ {
+ left_done = false;
+ root = root->right;
+ }
+ else if (root->parent)
+ {
+ while (root->parent && root == root->parent->right)
+ root = root->parent;
+
+ if (!root->parent)
+ break;
+
+ root = root->parent;
+ }
+ else
+ break;
+ }
+
+ _set_->flag = CMC_FLAG_OK;
+
+ CMC_CALLBACKS_ASSIGN(result, _set_->callbacks);
+
+ return result;
+}
+
+bool CMC_(PFX, _equals)(struct SNAME *_set1_, struct SNAME *_set2_)
+{
+ _set1_->flag = CMC_FLAG_OK;
+ _set2_->flag = CMC_FLAG_OK;
+
+ if (_set1_->count != _set2_->count)
+ return false;
+
+ struct CMC_DEF_NODE(SNAME) *root = _set1_->root;
+
+ bool left_done = false;
+
+ while (root)
+ {
+ if (!left_done)
+ {
+ while (root->left)
+ root = root->left;
+ }
+
+ /* TODO this can be optimized by doing two in-order traversals */
+ struct CMC_DEF_NODE(SNAME) *node = CMC_(PFX, _impl_get_node)(_set2_, root->value);
+
+ if (node == NULL)
+ return false;
+
+ left_done = true;
+
+ if (root->right)
+ {
+ left_done = false;
+ root = root->right;
+ }
+ else if (root->parent)
+ {
+ while (root->parent && root == root->parent->right)
+ root = root->parent;
+
+ if (!root->parent)
+ break;
+
+ root = root->parent;
+ }
+ else
+ break;
+ }
+
+ return true;
+}
+
+static struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _impl_new_node)(struct SNAME *_set_, V value)
+{
+ struct CMC_DEF_NODE(SNAME) *node = _set_->alloc->malloc(sizeof(struct CMC_DEF_NODE(SNAME)));
+
+ if (!node)
+ return NULL;
+
+ node->value = value;
+ node->right = NULL;
+ node->left = NULL;
+ node->parent = NULL;
+ node->height = 0;
+
+ return node;
+}
+
+static struct CMC_DEF_NODE(SNAME) * CMC_(PFX, _impl_get_node)(struct SNAME *_set_, V value)
+{
+ struct CMC_DEF_NODE(SNAME) *scan = _set_->root;
+
+ while (scan != NULL)
+ {
+ if (_set_->f_val->cmp(scan->value, value) > 0)
+ scan = scan->left;
+ else if (_set_->f_val->cmp(scan->value, value) < 0)
+ scan = scan->right;
+ else
+ return scan;
+ }
+
+ return NULL;
+}
+
+static unsigned char CMC_(PFX, _impl_h)(struct CMC_DEF_NODE(SNAME) * node)
+{
+ if (node == NULL)
+ return 0;
+
+ return node->height;
+}
+
+static unsigned char CMC_(PFX, _impl_hupdate)(struct CMC_DEF_NODE(SNAME) * node)
+{
+ if (node == NULL)
+ return 0;
+
+ unsigned char h_l = CMC_(PFX, _impl_h)(node->left);
+ unsigned char h_r = CMC_(PFX, _impl_h)(node->right);
+
+ return 1 + (h_l > h_r ? h_l : h_r);
+}
+
+static void CMC_(PFX, _impl_rotate_right)(struct CMC_DEF_NODE(SNAME) * *Z)
+{
+ struct CMC_DEF_NODE(SNAME) *root = *Z;
+ struct CMC_DEF_NODE(SNAME) *new_root = root->left;
+
+ if (root->parent != NULL)
+ {
+ if (root->parent->left == root)
+ root->parent->left = new_root;
+ else
+ root->parent->right = new_root;
+ }
+
+ new_root->parent = root->parent;
+
+ root->parent = new_root;
+ root->left = new_root->right;
+
+ if (root->left)
+ root->left->parent = root;
+
+ new_root->right = root;
+
+ root->height = CMC_(PFX, _impl_hupdate)(root);
+ new_root->height = CMC_(PFX, _impl_hupdate)(new_root);
+
+ *Z = new_root;
+}
+
+static void CMC_(PFX, _impl_rotate_left)(struct CMC_DEF_NODE(SNAME) * *Z)
+{
+ struct CMC_DEF_NODE(SNAME) *root = *Z;
+ struct CMC_DEF_NODE(SNAME) *new_root = root->right;
+
+ if (root->parent != NULL)
+ {
+ if (root->parent->right == root)
+ root->parent->right = new_root;
+ else
+ root->parent->left = new_root;
+ }
+
+ new_root->parent = root->parent;
+
+ root->parent = new_root;
+ root->right = new_root->left;
+
+ if (root->right)
+ root->right->parent = root;
+
+ new_root->left = root;
+
+ root->height = CMC_(PFX, _impl_hupdate)(root);
+ new_root->height = CMC_(PFX, _impl_hupdate)(new_root);
+
+ *Z = new_root;
+}
+
+static void CMC_(PFX, _impl_rebalance)(struct SNAME *_set_, struct CMC_DEF_NODE(SNAME) * node)
+{
+ struct CMC_DEF_NODE(SNAME) *scan = node, *child = NULL;
+
+ int balance;
+ bool is_root = false;
+
+ while (scan != NULL)
+ {
+ if (scan->parent == NULL)
+ is_root = true;
+
+ scan->height = CMC_(PFX, _impl_hupdate)(scan);
+ balance = CMC_(PFX, _impl_h)(scan->right) - CMC_(PFX, _impl_h)(scan->left);
+
+ if (balance >= 2)
+ {
+ child = scan->right;
+
+ if (CMC_(PFX, _impl_h)(child->right) < CMC_(PFX, _impl_h)(child->left))
+ CMC_(PFX, _impl_rotate_right)(&(scan->right));
+
+ CMC_(PFX, _impl_rotate_left)(&scan);
+ }
+ else if (balance <= -2)
+ {
+ child = scan->left;
+
+ if (CMC_(PFX, _impl_h)(child->left) < CMC_(PFX, _impl_h)(child->right))
+ CMC_(PFX, _impl_rotate_left)(&(scan->left));
+
+ CMC_(PFX, _impl_rotate_right)(&scan);
+ }
+
+ if (is_root)
+ {
+ _set_->root = scan;
+ is_root = false;
+ }
+
+ scan = scan->parent;
+ }
+}
diff --git a/src/cmc/cmc/treeset/ext/code.h b/src/cmc/cmc/treeset/ext/code.h
new file mode 100644
index 0000000..8a33411
--- /dev/null
+++ b/src/cmc/cmc/treeset/ext/code.h
@@ -0,0 +1,577 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * INIT
+ *
+ * The part 'INIT' gives a new way of initializing a collection. The collection
+ * struct is not heap allocated, only its internal structure (nodes, buffers).
+ */
+#ifdef CMC_EXT_INIT
+
+#endif /* CMC_EXT_INIT */
+
+/**
+ * ITER
+ *
+ * Treeset bi-directional iterator.
+ */
+#ifdef CMC_EXT_ITER
+
+struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target)
+{
+ struct CMC_DEF_ITER(SNAME) iter;
+
+ iter.target = target;
+ iter.cursor = target->root;
+ iter.first = NULL;
+ iter.last = NULL;
+ iter.index = 0;
+ iter.start = true;
+ iter.end = CMC_(PFX, _empty)(target);
+
+ if (!CMC_(PFX, _empty)(target))
+ {
+ while (iter.cursor->left != NULL)
+ iter.cursor = iter.cursor->left;
+
+ iter.first = iter.cursor;
+
+ iter.last = target->root;
+ while (iter.last->right != NULL)
+ iter.last = iter.last->right;
+ }
+
+ return iter;
+}
+
+struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME *target)
+{
+ struct CMC_DEF_ITER(SNAME) iter;
+
+ iter.target = target;
+ iter.cursor = target->root;
+ iter.first = NULL;
+ iter.last = NULL;
+ iter.index = 0;
+ iter.start = CMC_(PFX, _empty)(target);
+ iter.end = true;
+
+ if (!CMC_(PFX, _empty)(target))
+ {
+ while (iter.cursor->right != NULL)
+ iter.cursor = iter.cursor->right;
+
+ iter.last = iter.cursor;
+
+ iter.first = target->root;
+ while (iter.first->left != NULL)
+ iter.first = iter.first->left;
+
+ iter.index = target->count - 1;
+ }
+
+ return iter;
+}
+
+bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ return CMC_(PFX, _empty)(iter->target) || iter->start;
+}
+
+bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ return CMC_(PFX, _empty)(iter->target) || iter->end;
+}
+
+bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ if (!CMC_(PFX, _empty)(iter->target))
+ {
+ iter->index = 0;
+ iter->start = true;
+ iter->end = CMC_(PFX, _empty)(iter->target);
+ iter->cursor = iter->first;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ if (!CMC_(PFX, _empty)(iter->target))
+ {
+ iter->index = iter->target->count - 1;
+ iter->start = CMC_(PFX, _empty)(iter->target);
+ iter->end = true;
+ iter->cursor = iter->last;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ if (iter->end)
+ return false;
+
+ if (iter->cursor == iter->last)
+ {
+ iter->end = true;
+ return false;
+ }
+
+ iter->start = CMC_(PFX, _empty)(iter->target);
+
+ if (iter->cursor->right != NULL)
+ {
+ iter->cursor = iter->cursor->right;
+
+ while (iter->cursor->left != NULL)
+ iter->cursor = iter->cursor->left;
+
+ iter->index++;
+
+ return true;
+ }
+
+ while (true)
+ {
+ if (iter->cursor->parent->left == iter->cursor)
+ {
+ iter->cursor = iter->cursor->parent;
+
+ iter->index++;
+
+ return true;
+ }
+
+ iter->cursor = iter->cursor->parent;
+ }
+}
+
+bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ if (iter->start)
+ return false;
+
+ if (iter->cursor == iter->first)
+ {
+ iter->start = true;
+ return false;
+ }
+
+ iter->end = CMC_(PFX, _empty)(iter->target);
+
+ if (iter->cursor->left != NULL)
+ {
+ iter->cursor = iter->cursor->left;
+
+ while (iter->cursor->right != NULL)
+ iter->cursor = iter->cursor->right;
+
+ iter->index--;
+
+ return true;
+ }
+
+ while (true)
+ {
+ if (iter->cursor->parent->right == iter->cursor)
+ {
+ iter->cursor = iter->cursor->parent;
+
+ iter->index--;
+
+ return true;
+ }
+
+ iter->cursor = iter->cursor->parent;
+ }
+}
+
+/* Returns true only if the iterator moved */
+bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps)
+{
+ if (iter->end)
+ return false;
+
+ if (iter->cursor == iter->last)
+ {
+ iter->end = true;
+ return false;
+ }
+
+ if (steps == 0 || iter->index + steps >= iter->target->count)
+ return false;
+
+ for (size_t i = 0; i < steps; i++)
+ CMC_(PFX, _iter_next)(iter);
+
+ return true;
+}
+
+/* Returns true only if the iterator moved */
+bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps)
+{
+ if (iter->start)
+ return false;
+
+ if (iter->cursor == iter->first)
+ {
+ iter->start = true;
+ return false;
+ }
+
+ if (steps == 0 || iter->index < steps)
+ return false;
+
+ for (size_t i = 0; i < steps; i++)
+ CMC_(PFX, _iter_prev)(iter);
+
+ return true;
+}
+
+/* Returns true only if the iterator was able to be positioned at the */
+/* given index */
+bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index)
+{
+ if (index >= iter->target->count)
+ return false;
+
+ if (iter->index > index)
+ return CMC_(PFX, _iter_rewind)(iter, iter->index - index);
+ else if (iter->index < index)
+ return CMC_(PFX, _iter_advance)(iter, index - iter->index);
+
+ return true;
+}
+
+V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ if (CMC_(PFX, _empty)(iter->target))
+ return (V){ 0 };
+
+ return iter->cursor->value;
+}
+
+size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter)
+{
+ return iter->index;
+}
+
+#endif /* CMC_EXT_ITER */
+
+/**
+ * SETF
+ *
+ * Set functions
+ */
+#ifdef CMC_EXT_SETF
+
+struct SNAME *CMC_(PFX, _union)(struct SNAME *_set1_, struct SNAME *_set2_)
+{
+ struct SNAME *_set_r_ = CMC_(PFX, _new_custom)(_set1_->f_val, _set1_->alloc, NULL);
+
+ if (!_set_r_)
+ return NULL;
+
+ struct CMC_DEF_ITER(SNAME) iter1 = CMC_(PFX, _iter_start)(_set1_);
+ struct CMC_DEF_ITER(SNAME) iter2 = CMC_(PFX, _iter_start)(_set2_);
+
+ for (; !CMC_(PFX, _iter_at_end)(&iter1); CMC_(PFX, _iter_next)(&iter1))
+ {
+ CMC_(PFX, _insert)(_set_r_, CMC_(PFX, _iter_value)(&iter1));
+ }
+
+ for (; !CMC_(PFX, _iter_at_end)(&iter2); CMC_(PFX, _iter_next)(&iter2))
+ {
+ CMC_(PFX, _insert)(_set_r_, CMC_(PFX, _iter_value)(&iter2));
+ }
+
+ CMC_CALLBACKS_ASSIGN(_set_r_, _set1_->callbacks);
+
+ return _set_r_;
+}
+
+struct SNAME *CMC_(PFX, _intersection)(struct SNAME *_set1_, struct SNAME *_set2_)
+{
+ struct SNAME *_set_r_ = CMC_(PFX, _new_custom)(_set1_->f_val, _set1_->alloc, NULL);
+
+ if (!_set_r_)
+ return NULL;
+
+ /** TODO Should this compare count or capacity? */
+ struct SNAME *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_;
+ struct SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_;
+
+ struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set_A_);
+
+ for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter))
+ {
+ V value = CMC_(PFX, _iter_value)(&iter);
+
+ if (CMC_(PFX, _impl_get_node)(_set_B_, value) != NULL)
+ CMC_(PFX, _insert)(_set_r_, value);
+ }
+
+ CMC_CALLBACKS_ASSIGN(_set_r_, _set1_->callbacks);
+
+ return _set_r_;
+}
+
+struct SNAME *CMC_(PFX, _difference)(struct SNAME *_set1_, struct SNAME *_set2_)
+{
+ struct SNAME *_set_r_ = CMC_(PFX, _new_custom)(_set1_->f_val, _set1_->alloc, NULL);
+
+ if (!_set_r_)
+ return NULL;
+
+ struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_);
+
+ for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter))
+ {
+ V value = CMC_(PFX, _iter_value)(&iter);
+
+ if (CMC_(PFX, _impl_get_node)(_set2_, value) == NULL)
+ CMC_(PFX, _insert)(_set_r_, value);
+ }
+
+ CMC_CALLBACKS_ASSIGN(_set_r_, _set1_->callbacks);
+
+ return _set_r_;
+}
+
+struct SNAME *CMC_(PFX, _symmetric_difference)(struct SNAME *_set1_, struct SNAME *_set2_)
+{
+ struct SNAME *_set_r_ = CMC_(PFX, _new_custom)(_set1_->f_val, _set1_->alloc, NULL);
+
+ if (!_set_r_)
+ return NULL;
+
+ struct CMC_DEF_ITER(SNAME) iter1 = CMC_(PFX, _iter_start)(_set1_);
+ struct CMC_DEF_ITER(SNAME) iter2 = CMC_(PFX, _iter_start)(_set2_);
+
+ for (; !CMC_(PFX, _iter_at_end)(&iter1); CMC_(PFX, _iter_next)(&iter1))
+ {
+ V value = CMC_(PFX, _iter_value)(&iter1);
+
+ if (CMC_(PFX, _impl_get_node)(_set2_, value) == NULL)
+ CMC_(PFX, _insert)(_set_r_, value);
+ }
+
+ for (; !CMC_(PFX, _iter_at_end)(&iter2); CMC_(PFX, _iter_next)(&iter2))
+ {
+ V value = CMC_(PFX, _iter_value)(&iter2);
+
+ if (CMC_(PFX, _impl_get_node)(_set1_, value) == NULL)
+ CMC_(PFX, _insert)(_set_r_, value);
+ }
+
+ CMC_CALLBACKS_ASSIGN(_set_r_, _set1_->callbacks);
+
+ return _set_r_;
+}
+
+/* Is _set1_ a subset of _set2_ ? */
+/* A set X is a subset of a set Y when: X <= Y */
+/* If X is a subset of Y, then Y is a superset of X */
+bool CMC_(PFX, _is_subset)(struct SNAME *_set1_, struct SNAME *_set2_)
+{
+ /* If the cardinality of _set1_ is greater than that of _set2_ */
+ /* then it is safe to say that _set1_ can't be a subset of _set2_ */
+ if (_set1_->count > _set2_->count)
+ return false;
+
+ /* The empty set is a subset of all sets */
+ if (CMC_(PFX, _empty)(_set1_))
+ return true;
+
+ struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_);
+
+ for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter))
+ {
+ V value = CMC_(PFX, _iter_value)(&iter);
+
+ if (CMC_(PFX, _impl_get_node)(_set2_, value) == NULL)
+ return false;
+ }
+
+ return true;
+}
+
+/* Is _set1_ a superset of _set2_ ? */
+/* A set X is a superset of a set Y when: X >= Y */
+/* If X is a superset of Y, then Y is a subset of X */
+bool CMC_(PFX, _is_superset)(struct SNAME *_set1_, struct SNAME *_set2_)
+{
+ return CMC_(PFX, _is_subset)(_set2_, _set1_);
+}
+
+/* Is _set1_ a proper subset of _set2_ ? */
+/* A set X is a proper subset of a set Y when: X < Y */
+/* If X is a proper subset of Y, then Y is a proper superset of X */
+bool CMC_(PFX, _is_proper_subset)(struct SNAME *_set1_, struct SNAME *_set2_)
+{
+ /* If the cardinality of _set1_ is greater than or equal to that */
+ /* of _set2_, then it is safe to say that _set1_ can't be a proper */
+ /* subset of _set2_ */
+ if (_set1_->count >= _set2_->count)
+ return false;
+
+ if (CMC_(PFX, _empty)(_set1_))
+ {
+ /* The empty set is a proper subset of all non-empty sets */
+ if (!CMC_(PFX, _empty)(_set2_))
+ return true;
+ /* The empty set is not a proper subset of itself (this is true */
+ /* for any set) */
+ else
+ return false;
+ }
+
+ struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_);
+
+ for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter))
+ {
+ V value = CMC_(PFX, _iter_value)(&iter);
+
+ if (CMC_(PFX, _impl_get_node)(_set2_, value) == NULL)
+ return false;
+ }
+
+ return true;
+}
+
+/* Is _set1_ a proper superset of _set2_ ? */
+/* A set X is a proper superset of a set Y when: X > Y */
+/* If X is a proper superset of Y, then Y is a proper subset of X */
+bool CMC_(PFX, _is_proper_superset)(struct SNAME *_set1_, struct SNAME *_set2_)
+{
+ return CMC_(PFX, _is_proper_subset)(_set2_, _set1_);
+}
+
+/* Is _set1_ a disjointset of _set2_ ? */
+/* A set X is a disjointset of a set Y if their intersection is empty, */
+/* that is, if there are no elements in common between the two */
+bool CMC_(PFX, _is_disjointset)(struct SNAME *_set1_, struct SNAME *_set2_)
+{
+ /* The intersection of an empty set with any other set will result */
+ /* in an empty set */
+ if (CMC_(PFX, _empty)(_set1_))
+ return true;
+
+ struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set1_);
+
+ for (; !CMC_(PFX, _iter_at_end)(&iter); CMC_(PFX, _iter_next)(&iter))
+ {
+ V value = CMC_(PFX, _iter_value)(&iter);
+
+ if (CMC_(PFX, _impl_get_node)(_set2_, value) != NULL)
+ return false;
+ }
+
+ return true;
+}
+
+#endif /* CMC_EXT_SETF */
+
+/**
+ * STR
+ *
+ * Print helper functions.
+ */
+#ifdef CMC_EXT_STR
+
+bool CMC_(PFX, _to_string)(struct SNAME *_set_, FILE *fptr)
+{
+ struct SNAME *s_ = _set_;
+
+ return 0 <= fprintf(fptr,
+ "struct %s<%s> "
+ "at %p { "
+ "root:%p, "
+ "count:%" PRIuMAX ", "
+ "flag:%d, "
+ "f_val:%p, "
+ "alloc:%p, "
+ "callbacks:%p }",
+ CMC_TO_STRING(SNAME), CMC_TO_STRING(V), s_, s_->root, s_->count, s_->flag, s_->f_val, s_->alloc,
+ CMC_CALLBACKS_GET(s_));
+}
+
+bool CMC_(PFX, _print)(struct SNAME *_set_, FILE *fptr, const char *start, const char *separator, const char *end)
+{
+ fprintf(fptr, "%s", start);
+
+ struct CMC_DEF_NODE(SNAME) *root = _set_->root;
+
+ bool left_done = false;
+
+ size_t i = 0;
+ while (root)
+ {
+ if (!left_done)
+ {
+ while (root->left)
+ root = root->left;
+ }
+
+ if (!_set_->f_val->str(fptr, root->value))
+ return false;
+
+ if (++i < _set_->count)
+ fprintf(fptr, "%s", separator);
+
+ left_done = true;
+
+ if (root->right)
+ {
+ left_done = false;
+ root = root->right;
+ }
+ else if (root->parent)
+ {
+ while (root->parent && root == root->parent->right)
+ root = root->parent;
+
+ if (!root->parent)
+ break;
+
+ root = root->parent;
+ }
+ else
+ break;
+ }
+
+ fprintf(fptr, "%s", end);
+
+ return true;
+}
+
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/treeset/ext/header.h b/src/cmc/cmc/treeset/ext/header.h
new file mode 100644
index 0000000..34229cb
--- /dev/null
+++ b/src/cmc/cmc/treeset/ext/header.h
@@ -0,0 +1,111 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * INIT
+ *
+ * The part 'INIT' gives a new way of initializing a collection. The collection
+ * struct is not heap allocated, only its internal structure (nodes, buffers).
+ */
+#ifdef CMC_EXT_INIT
+
+#endif /* CMC_EXT_INIT */
+
+/**
+ * ITER
+ *
+ * Treeset bi-directional iterator.
+ */
+#ifdef CMC_EXT_ITER
+
+/* Treeset Iterator */
+struct CMC_DEF_ITER(SNAME)
+{
+ /* Target treeset */
+ struct SNAME *target;
+ /* Cursor's current node */
+ struct CMC_DEF_NODE(SNAME) * cursor;
+ /* The first node in the iteration */
+ struct CMC_DEF_NODE(SNAME) * first;
+ /* The last node in the iteration */
+ struct CMC_DEF_NODE(SNAME) * last;
+ /* Keeps track of relative index to the iteration of elements */
+ size_t index;
+ /* If the iterator has reached the start of the iteration */
+ bool start;
+ /* If the iterator has reached the end of the iteration */
+ bool end;
+};
+
+/* Iterator Initialization */
+struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_start)(struct SNAME *target);
+struct CMC_DEF_ITER(SNAME) CMC_(PFX, _iter_end)(struct SNAME *target);
+/* Iterator State */
+bool CMC_(PFX, _iter_at_start)(struct CMC_DEF_ITER(SNAME) * iter);
+bool CMC_(PFX, _iter_at_end)(struct CMC_DEF_ITER(SNAME) * iter);
+/* Iterator Movement */
+bool CMC_(PFX, _iter_to_start)(struct CMC_DEF_ITER(SNAME) * iter);
+bool CMC_(PFX, _iter_to_end)(struct CMC_DEF_ITER(SNAME) * iter);
+bool CMC_(PFX, _iter_next)(struct CMC_DEF_ITER(SNAME) * iter);
+bool CMC_(PFX, _iter_prev)(struct CMC_DEF_ITER(SNAME) * iter);
+bool CMC_(PFX, _iter_advance)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps);
+bool CMC_(PFX, _iter_rewind)(struct CMC_DEF_ITER(SNAME) * iter, size_t steps);
+bool CMC_(PFX, _iter_go_to)(struct CMC_DEF_ITER(SNAME) * iter, size_t index);
+/* Iterator Access */
+V CMC_(PFX, _iter_value)(struct CMC_DEF_ITER(SNAME) * iter);
+size_t CMC_(PFX, _iter_index)(struct CMC_DEF_ITER(SNAME) * iter);
+
+#endif /* CMC_EXT_ITER */
+
+/**
+ * SETF
+ *
+ * Set functions
+ */
+#ifdef CMC_EXT_SETF
+
+/* Set Operations */
+struct SNAME *CMC_(PFX, _union)(struct SNAME *_set1_, struct SNAME *_set2_);
+struct SNAME *CMC_(PFX, _intersection)(struct SNAME *_set1_, struct SNAME *_set2_);
+struct SNAME *CMC_(PFX, _difference)(struct SNAME *_set1_, struct SNAME *_set2_);
+struct SNAME *CMC_(PFX, _symmetric_difference)(struct SNAME *_set1_, struct SNAME *_set2_);
+bool CMC_(PFX, _is_subset)(struct SNAME *_set1_, struct SNAME *_set2_);
+bool CMC_(PFX, _is_superset)(struct SNAME *_set1_, struct SNAME *_set2_);
+bool CMC_(PFX, _is_proper_subset)(struct SNAME *_set1_, struct SNAME *_set2_);
+bool CMC_(PFX, _is_proper_superset)(struct SNAME *_set1_, struct SNAME *_set2_);
+bool CMC_(PFX, _is_disjointset)(struct SNAME *_set1_, struct SNAME *_set2_);
+
+#endif /* CMC_EXT_SETF */
+
+/**
+ * STR
+ *
+ * Print helper functions.
+ */
+#ifdef CMC_EXT_STR
+
+bool CMC_(PFX, _to_string)(struct SNAME *_set_, FILE *fptr);
+bool CMC_(PFX, _print)(struct SNAME *_set_, FILE *fptr, const char *start, const char *separator, const char *end);
+
+#endif /* CMC_EXT_STR */
diff --git a/src/cmc/cmc/treeset/ext/struct.h b/src/cmc/cmc/treeset/ext/struct.h
new file mode 100644
index 0000000..59c5376
--- /dev/null
+++ b/src/cmc/cmc/treeset/ext/struct.h
@@ -0,0 +1,23 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
diff --git a/src/cmc/cmc/treeset/header.h b/src/cmc/cmc/treeset/header.h
new file mode 100644
index 0000000..a9d66e7
--- /dev/null
+++ b/src/cmc/cmc/treeset/header.h
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* Value struct function table */
+struct CMC_DEF_FVAL(SNAME)
+{
+ /* Comparator function */
+ CMC_DEF_FTAB_CMP(V);
+ /* Copy function */
+ CMC_DEF_FTAB_CPY(V);
+ /* To string function */
+ CMC_DEF_FTAB_STR(V);
+ /* Free from memory function */
+ CMC_DEF_FTAB_FREE(V);
+ /* Hash function */
+ CMC_DEF_FTAB_HASH(V);
+ /* Priority function */
+ CMC_DEF_FTAB_PRI(V);
+};
+
+/* Collection Functions */
+/* Collection Allocation and Deallocation */
+struct SNAME *CMC_(PFX, _new)(struct CMC_DEF_FVAL(SNAME) * f_val);
+struct SNAME *CMC_(PFX, _new_custom)(struct CMC_DEF_FVAL(SNAME) * f_val, struct CMC_ALLOC_NODE_NAME *alloc,
+ struct CMC_CALLBACKS_NAME *callbacks);
+void CMC_(PFX, _clear)(struct SNAME *_set_);
+void CMC_(PFX, _free)(struct SNAME *_set_);
+/* Customization of Allocation and Callbacks */
+void CMC_(PFX, _customize)(struct SNAME *_set_, struct CMC_ALLOC_NODE_NAME *alloc,
+ struct CMC_CALLBACKS_NAME *callbacks);
+/* Collection Input and Output */
+bool CMC_(PFX, _insert)(struct SNAME *_set_, V value);
+bool CMC_(PFX, _remove)(struct SNAME *_set_, V value);
+/* Element Access */
+bool CMC_(PFX, _max)(struct SNAME *_set_, V *value);
+bool CMC_(PFX, _min)(struct SNAME *_set_, V *value);
+/* Collection State */
+bool CMC_(PFX, _contains)(struct SNAME *_set_, V value);
+bool CMC_(PFX, _empty)(struct SNAME *_set_);
+size_t CMC_(PFX, _count)(struct SNAME *_set_);
+int CMC_(PFX, _flag)(struct SNAME *_set_);
+/* Collection Utility */
+struct SNAME *CMC_(PFX, _copy_of)(struct SNAME *_set_);
+bool CMC_(PFX, _equals)(struct SNAME *_set1_, struct SNAME *_set2_);
diff --git a/src/cmc/cmc/treeset/struct.h b/src/cmc/cmc/treeset/struct.h
new file mode 100644
index 0000000..7635b49
--- /dev/null
+++ b/src/cmc/cmc/treeset/struct.h
@@ -0,0 +1,64 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* Treeset Structure */
+struct SNAME
+{
+ /* Root node */
+ struct CMC_DEF_NODE(SNAME) * root;
+
+ /* Current amount of elements */
+ size_t count;
+
+ /* Flags indicating errors or success */
+ int flag;
+
+ /* Value function table */
+ struct CMC_DEF_FVAL(SNAME) * f_val;
+
+ /* Custom allocation functions */
+ struct CMC_ALLOC_NODE_NAME *alloc;
+
+ /* Custom callback functions */
+ CMC_CALLBACKS_DECL;
+};
+
+/* Treeset Node */
+struct CMC_DEF_NODE(SNAME)
+{
+ /* Node element */
+ V value;
+
+ /* Node height used by the AVL tree to keep it strictly balanced */
+ unsigned char height;
+
+ /* Right child node or subtree */
+ struct CMC_DEF_NODE(SNAME) * right;
+
+ /* Left child node or subtree */
+ struct CMC_DEF_NODE(SNAME) * left;
+
+ /* Parent node */
+ struct CMC_DEF_NODE(SNAME) * parent;
+};
diff --git a/src/cmc/cor/undef.h b/src/cmc/cor/undef.h
index d2097a7..ebe8447 100644
--- a/src/cmc/cor/undef.h
+++ b/src/cmc/cor/undef.h
@@ -23,7 +23,7 @@
*/
/**
- * prelude.h
+ * undef.h
*
* Creation Date: 12/01/2023
*
@@ -36,60 +36,29 @@
* Common undefs
*/
-#ifndef CMC_ARGS_FALLTHROUGH
-
-#undef V
-#undef K
+/* You never want these to fallthrough since they should be unique for each collection */
#undef PFX
#undef SNAME
+
+#ifndef CMC_ARGS_FALLTHROUGH
+
+#ifndef CMC_ARGS_KEY_FALLTHROUGH
+#undef K
+#endif
+
+#ifndef CMC_ARGS_VAL_FALLTHROUGH
+#undef V
+#endif
+
#undef SIZE
-/* Deque */
-#undef CMC_EXT_DEQUE_INIT
-#undef CMC_EXT_DEQUE_ITER
-#undef CMC_EXT_DEQUE_STR
-
-/* Hashbidimap */
-#undef CMC_EXT_HASHBIDIMAP_INIT
-#undef CMC_EXT_HASHBIDIMAP_ITER
-#undef CMC_EXT_HASHBIDIMAP_STR
-
-/* Hashmap */
-#undef CMC_EXT_HASHMAP_INIT
-#undef CMC_EXT_HASHMAP_ITER
-#undef CMC_EXT_HASHMAP_STR
-
-/* Hashmultimap */
-#undef CMC_EXT_HASHMULTIMAP_INIT
-#undef CMC_EXT_HASHMULTIMAP_ITER
-#undef CMC_EXT_HASHMULTIMAP_STR
-
-/* Hashmultiset */
-#undef CMC_EXT_HASHMULTISET_INIT
-#undef CMC_EXT_HASHMULTISET_ITER
-#undef CMC_EXT_HASHMULTISET_SETF
-#undef CMC_EXT_HASHMULTISET_STR
-
-/* Hashset */
-#undef CMC_EXT_HASHMSET_INIT
-#undef CMC_EXT_HASHMSET_ITER
-#undef CMC_EXT_HASHMSET_SETF
-#undef CMC_EXT_HASHMSET_STR
-
-/* List */
-#undef CMC_EXT_LIST_INIT
-#undef CMC_EXT_LIST_ITER
-#undef CMC_EXT_LIST_SEQ
-#undef CMC_EXT_LIST_STR
-
-/* Queue */
-#undef CMC_EXT_QUEUE_INIT
-#undef CMC_EXT_QUEUE_ITER
-#undef CMC_EXT_QUEUE_STR
-
-/* Stack */
-#undef CMC_EXT_STACK_INIT
-#undef CMC_EXT_STACK_ITER
-#undef CMC_EXT_STACK_STR
+#ifndef CMC_EXT_FALLTHROUGH
+#undef CMC_EXT_INIT
+#undef CMC_EXT_ITER
+#undef CMC_EXT_NODE
+#undef CMC_EXT_SEQ
+#undef CMC_EXT_SETF
+#undef CMC_EXT_STR
+#endif
#endif
diff --git a/src/cmc/linkedlist.h b/src/cmc/linkedlist.h
new file mode 100644
index 0000000..9e401c6
--- /dev/null
+++ b/src/cmc/linkedlist.h
@@ -0,0 +1,86 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * linkedlist.h
+ *
+ * Creation Date: 22/03/2019
+ *
+ * Authors:
+ * Leonardo Vencovsky (https://github.com/LeoVen)
+ *
+ */
+
+/**
+ * LinkedList
+ *
+ * A LinkedList is a linear collection of elements, whose order is not given by
+ * their physical placement in memory. Instead, each element points to the next
+ * (singly-linked list) and to a previous one (doubly-linked list). It consists
+ * of nodes connected by these next or previous pointers. Unlike an array, the
+ * LinkedList can indefinitely grow.
+ *
+ * Implementation
+ *
+ * The LinkedList is implemented as a doubly-linked list and allows insertions
+ * and removals at both ends in O(1) and in a given index in O(N). The list has
+ * a head and tail pointer. The head points to the first element in the sequence
+ * and tail points to the last.
+ */
+
+#include "cor/core.h"
+
+/**
+ * Used values
+ * V - linkedlist data type
+ * SNAME - struct name and prefix of other related structs
+ * PFX - functions prefix
+ */
+
+/* Structs definition */
+#include "cmc/linkedlist/struct.h"
+
+/* Function declaration */
+#include "cmc/linkedlist/header.h"
+
+/* Function implementation */
+#include "cmc/linkedlist/code.h"
+
+/**
+ * Extensions
+ *
+ * INIT - Initializes the struct on the stack
+ * ITER - List iterator
+ * NODE - Operations relative to a linkedlist node
+ * STR - Print helper functions
+ */
+#define CMC_EXT_LINKEDLIST_PARTS INIT, ITER, NODE, STR
+/**/
+#include "cmc/linkedlist/ext/struct.h"
+/**/
+#include "cmc/linkedlist/ext/header.h"
+/**/
+#include "cmc/linkedlist/ext/code.h"
+
+#include "cor/undef.h"
diff --git a/src/cmc/sortedlist.h b/src/cmc/sortedlist.h
new file mode 100644
index 0000000..386578a
--- /dev/null
+++ b/src/cmc/sortedlist.h
@@ -0,0 +1,79 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * sortedlist.h
+ *
+ * Creation Date: 17/09/2019
+ *
+ * Authors:
+ * Leonardo Vencovsky (https://github.com/LeoVen)
+ *
+ */
+
+/**
+ * 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. The array is sorted using a
+ * variation of quick sort that uses insertion sort for small partitions.
+ */
+
+#include "cor/core.h"
+
+/**
+ * Used values
+ * V - sortedlist data type
+ * SNAME - struct name and prefix of other related structs
+ * PFX - functions prefix
+ */
+
+/* Structs definition */
+#include "cmc/sortedlist/struct.h"
+
+/* Function declaration */
+#include "cmc/sortedlist/header.h"
+
+/* Function implementation */
+#include "cmc/sortedlist/code.h"
+
+/**
+ * Extensions
+ *
+ * INIT - Initializes the struct on the stack
+ * ITER - List iterator
+ * STR - Print helper functions
+ */
+#define CMC_EXT_SORTEDLIST_PARTS INIT, ITER, STR
+/**/
+#include "cmc/sortedlist/ext/struct.h"
+/**/
+#include "cmc/sortedlist/ext/header.h"
+/**/
+#include "cmc/sortedlist/ext/code.h"
+
+#include "cor/undef.h"
diff --git a/src/cmc/treemap.h b/src/cmc/treemap.h
new file mode 100644
index 0000000..35a7a64
--- /dev/null
+++ b/src/cmc/treemap.h
@@ -0,0 +1,77 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * treemap.h
+ *
+ * Creation Date: 28/03/2019
+ *
+ * Authors:
+ * Leonardo Vencovsky (https://github.com/LeoVen)
+ *
+ */
+
+/**
+ * TreeMap
+ *
+ * A TreeMap is an implementation of a Map that keeps its keys sorted. Like a
+ * Map, it has only unique keys. This implementation uses a balanced binary
+ * tree called AVL Tree that uses the height of nodes to keep its keys balanced.
+ */
+
+#include "cor/core.h"
+
+/**
+ * Used values
+ * K - treemap key data type
+ * V - treemap value data type
+ * SNAME - struct name and prefix of other related structs
+ * PFX - functions prefix
+ */
+
+/* Structs definition */
+#include "cmc/treemap/struct.h"
+
+/* Function declaration */
+#include "cmc/treemap/header.h"
+
+/* Function implementation */
+#include "cmc/treemap/code.h"
+
+/**
+ * Extensions
+ *
+ * INIT - Initializes the struct on the stack
+ * ITER - treemap iterator
+ * STR - Print helper functions
+ */
+#define CMC_EXT_TREEMAP_PARTS INIT, ITER, STR
+/**/
+#include "cmc/treemap/ext/struct.h"
+/**/
+#include "cmc/treemap/ext/header.h"
+/**/
+#include "cmc/treemap/ext/code.h"
+
+#include "cor/undef.h"
diff --git a/src/cmc/treeset.h b/src/cmc/treeset.h
new file mode 100644
index 0000000..2862bc7
--- /dev/null
+++ b/src/cmc/treeset.h
@@ -0,0 +1,77 @@
+/**
+ * Copyright (c) 2019 Leonardo Vencovsky
+ *
+ * This file is part of the C Macro Collections Libray.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * treeset.h
+ *
+ * Creation Date: 27/03/2019
+ *
+ * Authors:
+ * Leonardo Vencovsky (https://github.com/LeoVen)
+ *
+ */
+
+/**
+ * TreeSet
+ *
+ * A TreeSet is an implementation of a Set that keeps its elements sorted. Like
+ * a Set it has only unique keys. This implementation uses a balanced binary
+ * tree called AVL Tree that uses the height of nodes to keep its keys balanced.
+ */
+
+#include "cor/core.h"
+
+/**
+ * Used values
+ * V - treeset value data type
+ * SNAME - struct name and prefix of other related structs
+ * PFX - functions prefix
+ */
+
+/* Structs definition */
+#include "cmc/treeset/struct.h"
+
+/* Function declaration */
+#include "cmc/treeset/header.h"
+
+/* Function implementation */
+#include "cmc/treeset/code.h"
+
+/**
+ * Extensions
+ *
+ * INIT - Initializes the struct on the stack
+ * ITER - treeset iterator
+ * SETF - Set functions
+ * STR - Print helper functions
+ */
+#define CMC_EXT_TREESET_PARTS INIT, ITER, SETF, STR
+/**/
+#include "cmc/treeset/ext/struct.h"
+/**/
+#include "cmc/treeset/ext/header.h"
+/**/
+#include "cmc/treeset/ext/code.h"
+
+#include "cor/undef.h"
diff --git a/tests/main.c b/tests/main.c
index 0760c3d..8e2a476 100644
--- a/tests/main.c
+++ b/tests/main.c
@@ -1,6 +1,14 @@
#include
#include
+#define CMC_EXT_FALLTHROUGH
+#define CMC_EXT_INIT
+#define CMC_EXT_ITER
+#define CMC_EXT_NODE
+#define CMC_EXT_SEQ
+#define CMC_EXT_SETF
+#define CMC_EXT_STR
+
#include "unt_bitset.h"
#include "unt_deque.h"
#include "unt_hashbidimap.h"
@@ -10,15 +18,15 @@
#include "unt_hashset.h"
#include "unt_heap.h"
#include "unt_intervalheap.h"
-// #include "unt_linkedlist.h"
+#include "unt_linkedlist.h"
#include "unt_list.h"
#include "unt_queue.h"
-// #include "unt_sortedlist.h"
+#include "unt_sortedlist.h"
#include "unt_stack.h"
-// #include "unt_treemap.h"
-// #include "unt_treeset.h"
+#include "unt_treemap.h"
+#include "unt_treeset.h"
-// #include "unt_foreach.h"
+#include "unt_foreach.h"
#include "cmc/utl/assert.h"
#include "cmc/utl/timer.h"
@@ -70,22 +78,22 @@ int main(void)
cmc_run(CMCHeapIter, units, tests);
cmc_run(CMCIntervalHeap, units, tests);
cmc_run(CMCIntervalHeapIter, units, tests);
- // cmc_run(CMCLinkedList, units, tests);
- // cmc_run(CMCLinkedListIter, units, tests);
+ cmc_run(CMCLinkedList, units, tests);
+ cmc_run(CMCLinkedListIter, units, tests);
cmc_run(CMCList, units, tests);
cmc_run(CMCListIter, units, tests);
cmc_run(CMCQueue, units, tests);
cmc_run(CMCQueueIter, units, tests);
- // cmc_run(CMCSortedList, units, tests);
- // cmc_run(CMCSortedListIter, units, tests);
+ cmc_run(CMCSortedList, units, tests);
+ cmc_run(CMCSortedListIter, units, tests);
cmc_run(CMCStack, units, tests);
cmc_run(CMCStackIter, units, tests);
- // cmc_run(CMCTreeMap, units, tests);
- // cmc_run(CMCTreeMapIter, units, tests);
- // cmc_run(CMCTreeSet, units, tests);
- // cmc_run(CMCTreeSetIter, units, tests);
+ cmc_run(CMCTreeMap, units, tests);
+ cmc_run(CMCTreeMapIter, units, tests);
+ cmc_run(CMCTreeSet, units, tests);
+ cmc_run(CMCTreeSetIter, units, tests);
- // cmc_run(ForEach, units, tests);
+ cmc_run(ForEach, units, tests);
cmc_timer_stop(timer);
diff --git a/tests/unt_bitset.h b/tests/unt_bitset.h
index b163ebd..a533b30 100644
--- a/tests/unt_bitset.h
+++ b/tests/unt_bitset.h
@@ -5,9 +5,6 @@
#define PFX bs
#define SNAME bitset
-#define CMC_EXT_BITSET_INIT
-#define CMC_EXT_BITSET_ITER
-#define CMC_EXT_BITSET_STR
#include "cmc/bitset.h"
struct cmc_alloc_node *bs_alloc_node =
diff --git a/tests/unt_deque.h b/tests/unt_deque.h
index f765eda..92ce83f 100644
--- a/tests/unt_deque.h
+++ b/tests/unt_deque.h
@@ -6,9 +6,6 @@
#define V size_t
#define PFX d
#define SNAME deque
-#define CMC_EXT_DEQUE_INIT
-#define CMC_EXT_DEQUE_ITER
-#define CMC_EXT_DEQUE_STR
#include "cmc/deque.h"
struct deque_fval *d_fval = &(struct deque_fval){
diff --git a/tests/unt_foreach.h b/tests/unt_foreach.h
new file mode 100644
index 0000000..d74ef1a
--- /dev/null
+++ b/tests/unt_foreach.h
@@ -0,0 +1,474 @@
+#ifndef CMC_TESTS_UNT_UTL_FOREACH_H
+#define CMC_TESTS_UNT_UTL_FOREACH_H
+
+CMC_CREATE_UNIT(ForEach, true, {
+ // CMC_CREATE_TEST(CMC, {
+ // struct bitset *bs = bs_new(10000);
+
+ // // WIP
+
+ // bs_free(bs);
+ // });
+
+ CMC_CREATE_TEST(CMC, {
+ struct deque *d = d_new(10000, &(struct deque_fval){ .cmp = cmc_size_cmp,
+ .cpy = NULL,
+ .str = cmc_size_str,
+ .free = NULL,
+ .hash = cmc_size_hash,
+ .pri = cmc_size_cmp });
+
+ for (size_t i = 1; i <= 10000; i++)
+ d_push_back(d, i);
+
+ size_t sum = 0;
+ CMC_FOREACH (d, deque, it, d)
+ {
+ sum += d_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sum);
+
+ sum = 0;
+ CMC_FOREACH_REV (d, deque, it, d)
+ {
+ sum += d_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sum);
+
+ d_free(d);
+ });
+
+ // CMC_CREATE_TEST(CMC, {
+ // struct hashbidimap *hbm =
+ // hbm_new(10000, 0.7,
+ // &(struct hashbidimap_fkey){ .cmp = cmc_size_cmp,
+ // .cpy = NULL,
+ // .str = cmc_size_str,
+ // .free = NULL,
+ // .hash = cmc_size_hash,
+ // .pri = cmc_size_cmp },
+ // &(struct hashbidimap_fval){ .cmp = cmc_size_cmp,
+ // .cpy = NULL,
+ // .str = cmc_size_str,
+ // .free = NULL,
+ // .hash = cmc_size_hash,
+ // .pri = cmc_size_cmp });
+
+ // // WIP
+
+ // hbm_free(hbm);
+ // });
+
+ CMC_CREATE_TEST(CMC, {
+ struct hashmap *hm = hm_new(10000, 0.6,
+ &(struct hashmap_fkey){ .cmp = cmc_size_cmp,
+ .cpy = NULL,
+ .str = cmc_size_str,
+ .free = NULL,
+ .hash = cmc_size_hash,
+ .pri = cmc_size_cmp },
+ &(struct hashmap_fval){ .cmp = cmc_size_cmp,
+ .cpy = NULL,
+ .str = cmc_size_str,
+ .free = NULL,
+ .hash = cmc_size_hash,
+ .pri = cmc_size_cmp });
+
+ for (size_t i = 1; i <= 10000; i++)
+ hm_insert(hm, i, i);
+
+ size_t sumk = 0;
+ size_t sumv = 0;
+ CMC_FOREACH (hm, hashmap, it, hm)
+ {
+ sumk += hm_iter_key(&it);
+ sumv += hm_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumk);
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ sumk = 0;
+ sumv = 0;
+ CMC_FOREACH_REV (hm, hashmap, it, hm)
+ {
+ sumk += hm_iter_key(&it);
+ sumv += hm_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumk);
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ hm_free(hm);
+ });
+
+ CMC_CREATE_TEST(CMC, {
+ struct hashmultimap *hmm = hmm_new(10000, 0.6,
+ &(struct hashmultimap_fkey){ .cmp = cmc_size_cmp,
+ .cpy = NULL,
+ .str = cmc_size_str,
+ .free = NULL,
+ .hash = cmc_size_hash,
+ .pri = cmc_size_cmp },
+ &(struct hashmultimap_fval){ .cmp = cmc_size_cmp,
+ .cpy = NULL,
+ .str = cmc_size_str,
+ .free = NULL,
+ .hash = cmc_size_hash,
+ .pri = cmc_size_cmp });
+
+ for (size_t i = 1; i <= 10000; i++)
+ hmm_insert(hmm, i, i);
+
+ size_t sumk = 0;
+ size_t sumv = 0;
+ CMC_FOREACH (hmm, hashmultimap, it, hmm)
+ {
+ sumk += hmm_iter_key(&it);
+ sumv += hmm_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumk);
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ sumk = 0;
+ sumv = 0;
+ CMC_FOREACH_REV (hmm, hashmultimap, it, hmm)
+ {
+ sumk += hmm_iter_key(&it);
+ sumv += hmm_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumk);
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ hmm_free(hmm);
+ });
+
+ CMC_CREATE_TEST(CMC, {
+ struct hashmultiset *hms = hms_new(10000, 0.6,
+ &(struct hashmultiset_fval){ .cmp = cmc_size_cmp,
+ .cpy = NULL,
+ .str = cmc_size_str,
+ .free = NULL,
+ .hash = cmc_size_hash,
+ .pri = cmc_size_cmp });
+
+ for (size_t i = 1; i <= 10000; i++)
+ hms_insert_many(hms, i, i);
+
+ size_t sumk = 0;
+ size_t sumv = 0;
+ CMC_FOREACH (hms, hashmultiset, it, hms)
+ {
+ sumk += hms_iter_value(&it);
+ sumv += hms_iter_multiplicity(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumk);
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ sumk = 0;
+ sumv = 0;
+ CMC_FOREACH_REV (hms, hashmultiset, it, hms)
+ {
+ sumk += hms_iter_value(&it);
+ sumv += hms_iter_multiplicity(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumk);
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ hms_free(hms);
+ });
+
+ CMC_CREATE_TEST(CMC, {
+ struct hashset *hs = hs_new(10000, 0.6,
+ &(struct hashset_fval){ .cmp = cmc_size_cmp,
+ .cpy = NULL,
+ .str = cmc_size_str,
+ .free = NULL,
+ .hash = cmc_size_hash,
+ .pri = cmc_size_cmp });
+
+ for (size_t i = 1; i <= 10000; i++)
+ hs_insert(hs, i);
+
+ size_t sumv = 0;
+ CMC_FOREACH (hs, hashset, it, hs)
+ {
+ sumv += hs_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ sumv = 0;
+ CMC_FOREACH_REV (hs, hashset, it, hs)
+ {
+ sumv += hs_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ hs_free(hs);
+ });
+
+ CMC_CREATE_TEST(CMC, {
+ struct heap *h = h_new(10000, CMC_MAX_HEAP,
+ &(struct heap_fval){ .cmp = cmc_size_cmp,
+ .cpy = NULL,
+ .str = cmc_size_str,
+ .free = NULL,
+ .hash = cmc_size_hash,
+ .pri = cmc_size_cmp });
+
+ for (size_t i = 1; i <= 10000; i++)
+ h_insert(h, i);
+
+ size_t sumv = 0;
+ CMC_FOREACH (h, heap, it, h)
+ {
+ sumv += h_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ sumv = 0;
+ CMC_FOREACH_REV (h, heap, it, h)
+ {
+ sumv += h_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ h_free(h);
+ });
+
+ CMC_CREATE_TEST(CMC, {
+ struct intervalheap *ih = ih_new(10000, &(struct intervalheap_fval){ .cmp = cmc_size_cmp,
+ .cpy = NULL,
+ .str = cmc_size_str,
+ .free = NULL,
+ .hash = cmc_size_hash,
+ .pri = cmc_size_cmp });
+
+ for (size_t i = 1; i <= 10000; i++)
+ ih_insert(ih, i);
+
+ size_t sumv = 0;
+ CMC_FOREACH (ih, intervalheap, it, ih)
+ {
+ sumv += ih_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ sumv = 0;
+ CMC_FOREACH_REV (ih, intervalheap, it, ih)
+ {
+ sumv += ih_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ ih_free(ih);
+ });
+
+ CMC_CREATE_TEST(CMC, {
+ struct linkedlist *ll = ll_new(&(struct linkedlist_fval){ .cmp = cmc_size_cmp,
+ .cpy = NULL,
+ .str = cmc_size_str,
+ .free = NULL,
+ .hash = cmc_size_hash,
+ .pri = cmc_size_cmp });
+
+ for (size_t i = 1; i <= 10000; i++)
+ ll_push_back(ll, i);
+
+ size_t sumv = 0;
+ CMC_FOREACH (ll, linkedlist, it, ll)
+ {
+ sumv += ll_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ sumv = 0;
+ CMC_FOREACH_REV (ll, linkedlist, it, ll)
+ {
+ sumv += ll_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ ll_free(ll);
+ });
+
+ CMC_CREATE_TEST(CMC, {
+ struct list *l = l_new(10000, &(struct list_fval){ .cmp = cmc_size_cmp,
+ .cpy = NULL,
+ .str = cmc_size_str,
+ .free = NULL,
+ .hash = cmc_size_hash,
+ .pri = cmc_size_cmp });
+
+ for (size_t i = 1; i <= 10000; i++)
+ l_push_back(l, i);
+
+ size_t sumv = 0;
+ CMC_FOREACH (l, list, it, l)
+ {
+ sumv += l_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ sumv = 0;
+ CMC_FOREACH_REV (l, list, it, l)
+ {
+ sumv += l_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ l_free(l);
+ });
+
+ CMC_CREATE_TEST(CMC, {
+ struct queue *q = q_new(10000, &(struct queue_fval){ .cmp = cmc_size_cmp,
+ .cpy = NULL,
+ .str = cmc_size_str,
+ .free = NULL,
+ .hash = cmc_size_hash,
+ .pri = cmc_size_cmp });
+
+ for (size_t i = 1; i <= 10000; i++)
+ q_enqueue(q, i);
+
+ size_t sumv = 0;
+ CMC_FOREACH (q, queue, it, q)
+ {
+ sumv += q_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ sumv = 0;
+ CMC_FOREACH_REV (q, queue, it, q)
+ {
+ sumv += q_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ q_free(q);
+ });
+
+ CMC_CREATE_TEST(CMC, {
+ struct sortedlist *sl = sl_new(10000, &(struct sortedlist_fval){ .cmp = cmc_size_cmp,
+ .cpy = NULL,
+ .str = cmc_size_str,
+ .free = NULL,
+ .hash = cmc_size_hash,
+ .pri = cmc_size_cmp });
+
+ for (size_t i = 1; i <= 10000; i++)
+ sl_insert(sl, i);
+
+ size_t sumv = 0;
+ CMC_FOREACH (sl, sortedlist, it, sl)
+ {
+ sumv += sl_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ sumv = 0;
+ CMC_FOREACH_REV (sl, sortedlist, it, sl)
+ {
+ sumv += sl_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ sl_free(sl);
+ });
+
+ CMC_CREATE_TEST(CMC, {
+ struct stack *s = s_new(10000, &(struct stack_fval){ .cmp = cmc_size_cmp,
+ .cpy = NULL,
+ .str = cmc_size_str,
+ .free = NULL,
+ .hash = cmc_size_hash,
+ .pri = cmc_size_cmp });
+
+ for (size_t i = 1; i <= 10000; i++)
+ s_push(s, i);
+
+ size_t sumv = 0;
+ CMC_FOREACH (s, stack, it, s)
+ {
+ sumv += s_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ sumv = 0;
+ CMC_FOREACH_REV (s, stack, it, s)
+ {
+ sumv += s_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ s_free(s);
+ });
+
+ CMC_CREATE_TEST(CMC, {
+ struct treemap *tm = tm_new(&(struct treemap_fkey){ .cmp = cmc_size_cmp,
+ .cpy = NULL,
+ .str = cmc_size_str,
+ .free = NULL,
+ .hash = cmc_size_hash,
+ .pri = cmc_size_cmp },
+ &(struct treemap_fval){ .cmp = cmc_size_cmp,
+ .cpy = NULL,
+ .str = cmc_size_str,
+ .free = NULL,
+ .hash = cmc_size_hash,
+ .pri = cmc_size_cmp });
+
+ for (size_t i = 1; i <= 10000; i++)
+ tm_insert(tm, i, i);
+
+ size_t sumk = 0;
+ size_t sumv = 0;
+ CMC_FOREACH (tm, treemap, it, tm)
+ {
+ sumk += tm_iter_key(&it);
+ sumv += tm_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumk);
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ sumk = 0;
+ sumv = 0;
+ CMC_FOREACH_REV (tm, treemap, it, tm)
+ {
+ sumk += tm_iter_key(&it);
+ sumv += tm_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumk);
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ tm_free(tm);
+ });
+
+ CMC_CREATE_TEST(CMC, {
+ struct treeset *ts = ts_new(&(struct treeset_fval){ .cmp = cmc_size_cmp,
+ .cpy = NULL,
+ .str = cmc_size_str,
+ .free = NULL,
+ .hash = cmc_size_hash,
+ .pri = cmc_size_cmp });
+
+ for (size_t i = 1; i <= 10000; i++)
+ ts_insert(ts, i);
+
+ size_t sumv = 0;
+ CMC_FOREACH (ts, treeset, it, ts)
+ {
+ sumv += ts_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ sumv = 0;
+ CMC_FOREACH_REV (ts, treeset, it, ts)
+ {
+ sumv += ts_iter_value(&it);
+ }
+ cmc_assert_equals(size_t, 50005000, sumv);
+
+ ts_free(ts);
+ });
+});
+
+#endif /* CMC_TESTS_UNT_UTL_FOREACH_H */
diff --git a/tests/unt_hashbidimap.h b/tests/unt_hashbidimap.h
index 13db4ec..74a592c 100644
--- a/tests/unt_hashbidimap.h
+++ b/tests/unt_hashbidimap.h
@@ -7,9 +7,6 @@
#define K size_t
#define PFX hbm
#define SNAME hashbidimap
-#define CMC_EXT_HASHBIDIMAP_INIT
-#define CMC_EXT_HASHBIDIMAP_ITER
-#define CMC_EXT_HASHBIDIMAP_STR
#include "cmc/hashbidimap.h"
struct hashbidimap_fkey *hbm_fkey = &(struct hashbidimap_fkey){
diff --git a/tests/unt_hashmap.h b/tests/unt_hashmap.h
index 200d319..21741d4 100644
--- a/tests/unt_hashmap.h
+++ b/tests/unt_hashmap.h
@@ -7,9 +7,6 @@
#define K size_t
#define PFX hm
#define SNAME hashmap
-#define CMC_EXT_HASHMAP_INIT
-#define CMC_EXT_HASHMAP_ITER
-#define CMC_EXT_HASHMAP_STR
#include "cmc/hashmap.h"
struct hashmap_fkey *hm_fkey = &(struct hashmap_fkey){
diff --git a/tests/unt_hashmultimap.h b/tests/unt_hashmultimap.h
index 4613d27..d12efb4 100644
--- a/tests/unt_hashmultimap.h
+++ b/tests/unt_hashmultimap.h
@@ -7,9 +7,6 @@
#define K size_t
#define PFX hmm
#define SNAME hashmultimap
-#define CMC_EXT_HASHMULTIMAP_INIT
-#define CMC_EXT_HASHMULTIMAP_ITER
-#define CMC_EXT_HASHMULTIMAP_STR
#include "cmc/hashmultimap.h"
struct hashmultimap_fkey *hmm_fkey = &(struct hashmultimap_fkey){
diff --git a/tests/unt_hashmultiset.h b/tests/unt_hashmultiset.h
index a06cfe6..92538b7 100644
--- a/tests/unt_hashmultiset.h
+++ b/tests/unt_hashmultiset.h
@@ -6,10 +6,6 @@
#define V size_t
#define PFX hms
#define SNAME hashmultiset
-#define CMC_EXT_HASHMULTISET_INIT
-#define CMC_EXT_HASHMULTISET_ITER
-#define CMC_EXT_HASHMULTISET_SETF
-#define CMC_EXT_HASHMULTISET_STR
#include "cmc/hashmultiset.h"
struct hashmultiset_fval *hms_fval = &(struct hashmultiset_fval){
diff --git a/tests/unt_hashset.h b/tests/unt_hashset.h
index 119b66b..61c084d 100644
--- a/tests/unt_hashset.h
+++ b/tests/unt_hashset.h
@@ -6,10 +6,6 @@
#define V size_t
#define PFX hs
#define SNAME hashset
-#define CMC_EXT_HASHSET_INIT
-#define CMC_EXT_HASHSET_ITER
-#define CMC_EXT_HASHSET_SETF
-#define CMC_EXT_HASHSET_STR
#include "cmc/hashset.h"
struct hashset_fval *hs_fval = &(struct hashset_fval){
diff --git a/tests/unt_heap.h b/tests/unt_heap.h
index a2bebd7..b2d79fd 100644
--- a/tests/unt_heap.h
+++ b/tests/unt_heap.h
@@ -6,9 +6,6 @@
#define V size_t
#define PFX h
#define SNAME heap
-#define CMC_EXT_HEAP_INIT
-#define CMC_EXT_HEAP_ITER
-#define CMC_EXT_HEAP_STR
#include "cmc/heap.h"
struct heap_fval *h_fval = &(struct heap_fval){
diff --git a/tests/unt_intervalheap.h b/tests/unt_intervalheap.h
index 0621d3e..67d4a1b 100644
--- a/tests/unt_intervalheap.h
+++ b/tests/unt_intervalheap.h
@@ -6,9 +6,6 @@
#define V size_t
#define PFX ih
#define SNAME intervalheap
-#define CMC_EXT_INTERVALHEAP_INIT
-#define CMC_EXT_INTERVALHEAP_ITER
-#define CMC_EXT_INTERVALHEAP_STR
#include "cmc/intervalheap.h"
struct intervalheap_fval *ih_fval = &(struct intervalheap_fval){
diff --git a/tests/unt_linkedlist.h b/tests/unt_linkedlist.h
new file mode 100644
index 0000000..bdf2efb
--- /dev/null
+++ b/tests/unt_linkedlist.h
@@ -0,0 +1,817 @@
+#ifndef CMC_TESTS_UNT_LINKEDLIST_H
+#define CMC_TESTS_UNT_LINKEDLIST_H
+
+#include "utl.h"
+
+#define V size_t
+#define PFX ll
+#define SNAME linkedlist
+#include "cmc/linkedlist.h"
+
+struct linkedlist_fval *ll_fval = &(struct linkedlist_fval){
+ .cmp = cmc_size_cmp, .cpy = NULL, .str = cmc_size_str, .free = NULL, .hash = cmc_size_hash, .pri = cmc_size_cmp
+};
+
+CMC_CREATE_UNIT(CMCLinkedList, true, {
+ CMC_CREATE_TEST(new, {
+ struct linkedlist *ll = ll_new(ll_fval);
+
+ 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], {
+ struct linkedlist *ll = ll_new(ll_fval);
+
+ 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[count = 0], {
+ struct linkedlist *ll = ll_new(ll_fval);
+
+ 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], {
+ struct linkedlist *ll = ll_new(ll_fval);
+
+ 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], {
+ struct linkedlist *ll = ll_new(ll_fval);
+
+ 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);
+ });
+
+ CMC_CREATE_TEST(flags, {
+ struct linkedlist *ll = ll_new(ll_fval);
+
+ cmc_assert_not_equals(ptr, NULL, ll);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ll_flag(ll));
+
+ // clear
+ ll->flag = CMC_FLAG_ERROR;
+ ll_clear(ll);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ll_flag(ll));
+
+ // customize
+ ll->flag = CMC_FLAG_ERROR;
+ ll_customize(ll, NULL, NULL);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ll_flag(ll));
+
+ // push_front
+ ll->flag = CMC_FLAG_ERROR;
+ cmc_assert(ll_push_front(ll, 10));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ll_flag(ll));
+
+ // push_at
+ ll->flag = CMC_FLAG_ERROR;
+ cmc_assert(ll_push_at(ll, 10, 1));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ll_flag(ll));
+ cmc_assert(!ll_push_at(ll, 10, 300));
+ cmc_assert_equals(int32_t, CMC_FLAG_RANGE, ll_flag(ll));
+
+ // push_back
+ ll->flag = CMC_FLAG_ERROR;
+ cmc_assert(ll_push_back(ll, 10));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ll_flag(ll));
+
+ ll_clear(ll);
+
+ // pop_front
+ ll->flag = CMC_FLAG_ERROR;
+ cmc_assert(!ll_pop_front(ll));
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, ll_flag(ll));
+
+ cmc_assert(ll_push_back(ll, 10));
+ cmc_assert(ll_pop_front(ll));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ll_flag(ll));
+
+ // pop_at
+ cmc_assert(!ll_pop_at(ll, 0));
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, ll_flag(ll));
+ cmc_assert(ll_push_front(ll, 10));
+ cmc_assert(!ll_pop_at(ll, 1));
+ cmc_assert_equals(int32_t, CMC_FLAG_RANGE, ll_flag(ll));
+ cmc_assert(ll_pop_at(ll, 0));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ll_flag(ll));
+
+ // pop_back
+ ll->flag = CMC_FLAG_ERROR;
+ cmc_assert(!ll_pop_front(ll));
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, ll_flag(ll));
+
+ cmc_assert(ll_push_back(ll, 10));
+ cmc_assert(ll_pop_front(ll));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ll_flag(ll));
+
+ ll_clear(ll);
+
+ // front
+ ll_front(ll);
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, ll_flag(ll));
+ cmc_assert(ll_push_front(ll, 10));
+ ll->flag = CMC_FLAG_ERROR;
+ ll_front(ll);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ll_flag(ll));
+
+ ll_clear(ll);
+
+ // back
+ ll_back(ll);
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, ll_flag(ll));
+ cmc_assert(ll_push_front(ll, 10));
+ ll->flag = CMC_FLAG_ERROR;
+ ll_back(ll);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ll_flag(ll));
+
+ ll_clear(ll);
+
+ // get get_ref
+ ll_get(ll, 0);
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, ll_flag(ll));
+ ll->flag = CMC_FLAG_ERROR;
+ ll_get_ref(ll, 0);
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, ll_flag(ll));
+
+ cmc_assert(ll_push_at(ll, 10, 0));
+ ll->flag = CMC_FLAG_ERROR;
+ ll_get(ll, 0);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ll_flag(ll));
+ ll_get(ll, 1);
+ cmc_assert_equals(int32_t, CMC_FLAG_RANGE, ll_flag(ll));
+ ll_get_ref(ll, 0);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ll_flag(ll));
+ ll_get_ref(ll, 1);
+ cmc_assert_equals(int32_t, CMC_FLAG_RANGE, ll_flag(ll));
+
+ // contains
+ cmc_assert(ll_contains(ll, 10));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ll_flag(ll));
+
+ // copy_of
+ ll->flag = CMC_FLAG_ERROR;
+ struct linkedlist *ll2 = ll_copy_of(ll);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ll_flag(ll));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ll_flag(ll2));
+
+ // equals
+ ll->flag = CMC_FLAG_ERROR;
+ ll2->flag = CMC_FLAG_ERROR;
+ cmc_assert(ll_equals(ll, ll2));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ll_flag(ll));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ll_flag(ll2));
+
+ ll_clear(ll);
+
+ // get_node
+ struct linkedlist_node *n = ll_get_node(ll, 0);
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, ll_flag(ll));
+
+ cmc_assert(ll_push_at(ll, 10, 0));
+ n = ll_get_node(ll, 0);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ll_flag(ll));
+
+ n = ll_get_node(ll, 1);
+ cmc_assert_equals(int32_t, CMC_FLAG_RANGE, ll_flag(ll));
+
+ // functions relative to node
+ ll_clear(ll);
+ cmc_assert(ll_push_front(ll, 10));
+ n = ll_get_node(ll, 0);
+ cmc_assert_not_equals(ptr, NULL, n);
+
+ // add_next
+ ll->flag = CMC_FLAG_ERROR;
+ cmc_assert(ll_add_next(ll, n, 11));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ll_flag(ll));
+
+ // add_prev
+ ll->flag = CMC_FLAG_ERROR;
+ cmc_assert(ll_add_prev(ll, n, 9));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ll_flag(ll));
+
+ // del_next
+ n = ll_next_node(n);
+ cmc_assert(!ll_del_next(ll, n));
+ cmc_assert_equals(int32_t, CMC_FLAG_INVALID, ll_flag(ll));
+ n = ll_prev_node(n);
+ cmc_assert(ll_del_next(ll, n));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ll_flag(ll));
+
+ // del_prev
+ n = ll_prev_node(n);
+ cmc_assert(!ll_del_prev(ll, n));
+ cmc_assert_equals(int32_t, CMC_FLAG_INVALID, ll_flag(ll));
+ n = ll_next_node(n);
+ cmc_assert(ll_del_prev(ll, n));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ll_flag(ll));
+
+ // del_curr
+ ll->flag = CMC_FLAG_ERROR;
+ cmc_assert(ll_del_curr(ll, n));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ll_flag(ll));
+
+ ll_free(ll);
+ ll_free(ll2);
+ });
+
+ CMC_CREATE_TEST(callbacks, {
+ struct linkedlist *ll = ll_new_custom(ll_fval, NULL, callbacks);
+
+ cmc_assert_not_equals(ptr, NULL, ll);
+
+ total_create = 0;
+ total_read = 0;
+ total_update = 0;
+ total_delete = 0;
+ total_resize = 0;
+
+ cmc_assert(ll_push_front(ll, 10));
+ cmc_assert_equals(int32_t, 1, total_create);
+
+ cmc_assert(ll_push_back(ll, 10));
+ cmc_assert_equals(int32_t, 2, total_create);
+
+ cmc_assert(ll_push_at(ll, 10, 1));
+ cmc_assert_equals(int32_t, 3, total_create);
+
+ cmc_assert(ll_pop_at(ll, 1));
+ cmc_assert_equals(int32_t, 1, total_delete);
+
+ cmc_assert(ll_pop_front(ll));
+ cmc_assert_equals(int32_t, 2, total_delete);
+
+ cmc_assert(ll_pop_back(ll));
+ cmc_assert_equals(int32_t, 3, total_delete);
+
+ cmc_assert(ll_push_back(ll, 10));
+ cmc_assert_equals(int32_t, 4, total_create);
+
+ cmc_assert_equals(size_t, 10, ll_front(ll));
+ cmc_assert_equals(int32_t, 1, total_read);
+
+ cmc_assert_equals(size_t, 10, ll_back(ll));
+ cmc_assert_equals(int32_t, 2, total_read);
+
+ cmc_assert_equals(size_t, 10, ll_get(ll, 0));
+ cmc_assert_equals(int32_t, 3, total_read);
+
+ cmc_assert_not_equals(ptr, NULL, ll_get_ref(ll, 0));
+ cmc_assert_equals(int32_t, 4, total_read);
+
+ cmc_assert(ll_contains(ll, 10));
+ cmc_assert_equals(int32_t, 5, total_read);
+
+ cmc_assert_equals(int32_t, 4, total_create);
+ cmc_assert_equals(int32_t, 5, total_read);
+ cmc_assert_equals(int32_t, 0, total_update);
+ cmc_assert_equals(int32_t, 3, total_delete);
+ cmc_assert_equals(int32_t, 0, total_resize);
+
+ ll_customize(ll, NULL, NULL);
+
+ cmc_assert_equals(ptr, NULL, ll->callbacks);
+
+ ll_clear(ll);
+ cmc_assert(ll_push_front(ll, 10));
+ cmc_assert(ll_push_back(ll, 10));
+ cmc_assert(ll_push_at(ll, 10, 1));
+ cmc_assert(ll_pop_at(ll, 1));
+ cmc_assert(ll_pop_front(ll));
+ cmc_assert(ll_pop_back(ll));
+ cmc_assert(ll_push_back(ll, 10));
+ cmc_assert_equals(size_t, 10, ll_front(ll));
+ cmc_assert_equals(size_t, 10, ll_back(ll));
+ cmc_assert_equals(size_t, 10, ll_get(ll, 0));
+ cmc_assert_not_equals(ptr, NULL, ll_get_ref(ll, 0));
+ cmc_assert(ll_contains(ll, 10));
+
+ cmc_assert_equals(int32_t, 4, total_create);
+ cmc_assert_equals(int32_t, 5, total_read);
+ cmc_assert_equals(int32_t, 0, total_update);
+ cmc_assert_equals(int32_t, 3, total_delete);
+ cmc_assert_equals(int32_t, 0, total_resize);
+
+ cmc_assert_equals(ptr, NULL, ll->callbacks);
+
+ ll_free(ll);
+
+ total_create = 0;
+ total_read = 0;
+ total_update = 0;
+ total_delete = 0;
+ total_resize = 0;
+ });
+});
+
+CMC_CREATE_UNIT(CMCLinkedListIter, true, {
+ CMC_CREATE_TEST(PFX##_iter_start(), {
+ struct linkedlist *ll = ll_new(ll_fval);
+
+ cmc_assert_not_equals(ptr, NULL, ll);
+
+ struct linkedlist_iter it = ll_iter_start(ll);
+
+ cmc_assert_equals(ptr, ll, it.target);
+ cmc_assert_equals(ptr, NULL, it.cursor);
+ cmc_assert_equals(size_t, 0, it.index);
+ cmc_assert_equals(bool, true, it.start);
+ cmc_assert_equals(bool, true, it.end);
+
+ cmc_assert(ll_iter_at_start(&it));
+ cmc_assert(ll_iter_at_end(&it));
+
+ cmc_assert(ll_push_front(ll, 1));
+ cmc_assert(ll_push_front(ll, 2));
+
+ it = ll_iter_start(ll);
+
+ cmc_assert_equals(size_t, 0, it.index);
+ cmc_assert_equals(bool, false, it.end);
+ cmc_assert_equals(ptr, ll->head, it.cursor);
+
+ ll_free(ll);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_end(), {
+ struct linkedlist *ll = ll_new(ll_fval);
+
+ cmc_assert_not_equals(ptr, NULL, ll);
+
+ struct linkedlist_iter it = ll_iter_end(ll);
+
+ cmc_assert_equals(ptr, ll, it.target);
+ cmc_assert_equals(ptr, NULL, it.cursor);
+ cmc_assert_equals(size_t, 0, it.index);
+ cmc_assert_equals(bool, true, it.start);
+ cmc_assert_equals(bool, true, it.end);
+
+ cmc_assert(ll_iter_at_start(&it));
+ cmc_assert(ll_iter_at_end(&it));
+
+ cmc_assert(ll_push_back(ll, 1));
+ cmc_assert(ll_push_back(ll, 2));
+ cmc_assert(ll_push_back(ll, 3));
+
+ it = ll_iter_end(ll);
+
+ cmc_assert_equals(size_t, ll->count - 1, it.index);
+ cmc_assert_equals(ptr, ll->tail, it.cursor);
+ cmc_assert_equals(bool, false, it.start);
+
+ ll_free(ll);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_at_start(), {
+ struct linkedlist *ll = ll_new(ll_fval);
+
+ cmc_assert_not_equals(ptr, NULL, ll);
+
+ struct linkedlist_iter it = ll_iter_start(ll);
+
+ // Empty checks
+ cmc_assert(ll_iter_at_start(&it));
+ it = ll_iter_end(ll);
+ cmc_assert(ll_iter_at_start(&it));
+
+ // Non-empty checks
+ cmc_assert(ll_push_back(ll, 1));
+ it = ll_iter_end(ll);
+ cmc_assert(!ll_iter_at_start(&it));
+ it = ll_iter_start(ll);
+ cmc_assert(ll_iter_at_start(&it));
+
+ ll_clear(ll);
+
+ cmc_assert(ll_push_front(ll, 1));
+ it = ll_iter_end(ll);
+ cmc_assert(!ll_iter_at_start(&it));
+ it = ll_iter_start(ll);
+ cmc_assert(ll_iter_at_start(&it));
+
+ ll_free(ll);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_at_end(), {
+ struct linkedlist *ll = ll_new(ll_fval);
+
+ cmc_assert_not_equals(ptr, NULL, ll);
+
+ struct linkedlist_iter it = ll_iter_start(ll);
+
+ // Empty check
+ cmc_assert(ll_iter_at_end(&it));
+ it = ll_iter_end(ll);
+ cmc_assert(ll_iter_at_end(&it));
+
+ // Non-empty checks
+ cmc_assert(ll_push_back(ll, 1));
+ it = ll_iter_end(ll);
+ cmc_assert(ll_iter_at_end(&it));
+ it = ll_iter_start(ll);
+ cmc_assert(!ll_iter_at_end(&it));
+
+ ll_clear(ll);
+
+ cmc_assert(ll_push_front(ll, 1));
+ it = ll_iter_end(ll);
+ cmc_assert(ll_iter_at_end(&it));
+ it = ll_iter_start(ll);
+ cmc_assert(!ll_iter_at_end(&it));
+
+ ll_free(ll);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_to_start(), {
+ struct linkedlist *ll = ll_new(ll_fval);
+
+ cmc_assert_not_equals(ptr, NULL, ll);
+
+ struct linkedlist_iter it = ll_iter_start(ll);
+
+ cmc_assert(!ll_iter_to_start(&it));
+
+ for (size_t i = 1; i <= 100; i++)
+ {
+ if (i % 2 == 0)
+ ll_push_back(ll, i);
+ else
+ ll_push_front(ll, i);
+ }
+
+ cmc_assert_equals(size_t, 100, ll->count);
+
+ it = ll_iter_end(ll);
+
+ cmc_assert(!ll_iter_at_start(&it));
+ cmc_assert(ll_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 100, ll_iter_value(&it));
+
+ cmc_assert(ll_iter_to_start(&it));
+
+ cmc_assert(ll_iter_at_start(&it));
+ cmc_assert(!ll_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 99, ll_iter_value(&it));
+
+ ll_free(ll);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_to_end(), {
+ struct linkedlist *ll = ll_new(ll_fval);
+
+ cmc_assert_not_equals(ptr, NULL, ll);
+
+ struct linkedlist_iter it = ll_iter_end(ll);
+
+ cmc_assert(!ll_iter_to_end(&it));
+
+ for (size_t i = 1; i <= 100; i++)
+ {
+ if (i % 2 == 0)
+ ll_push_back(ll, i);
+ else
+ ll_push_front(ll, i);
+ }
+
+ it = ll_iter_start(ll);
+
+ cmc_assert(ll_iter_at_start(&it));
+ cmc_assert(!ll_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 99, ll_iter_value(&it));
+
+ cmc_assert(ll_iter_to_end(&it));
+
+ cmc_assert(!ll_iter_at_start(&it));
+ cmc_assert(ll_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 100, ll_iter_value(&it));
+
+ ll_free(ll);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_next(), {
+ struct linkedlist *ll = ll_new(ll_fval);
+
+ cmc_assert_not_equals(ptr, NULL, ll);
+
+ struct linkedlist_iter it = ll_iter_start(ll);
+
+ cmc_assert(!ll_iter_next(&it));
+
+ for (size_t i = 1; i <= 1000; i++)
+ {
+ if (i % 2 == 0)
+ ll_push_back(ll, i);
+ else
+ ll_push_front(ll, i);
+ }
+
+ size_t sum = 0;
+ for (it = ll_iter_start(ll); !ll_iter_at_end(&it); ll_iter_next(&it))
+ {
+ sum += ll_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+
+ ll_iter_to_start(&it);
+ do
+ {
+ sum += ll_iter_value(&it);
+ } while (ll_iter_next(&it));
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ ll_free(ll);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_prev(), {
+ struct linkedlist *ll = ll_new(ll_fval);
+
+ cmc_assert_not_equals(ptr, NULL, ll);
+
+ struct linkedlist_iter it = ll_iter_end(ll);
+
+ cmc_assert(!ll_iter_prev(&it));
+
+ for (size_t i = 1; i <= 1000; i++)
+ {
+ if (i % 2 == 0)
+ ll_push_back(ll, i);
+ else
+ ll_push_front(ll, i);
+ }
+
+ size_t sum = 0;
+ for (it = ll_iter_end(ll); !ll_iter_at_start(&it); ll_iter_prev(&it))
+ {
+ sum += ll_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+
+ ll_iter_to_end(&it);
+ do
+ {
+ sum += ll_iter_value(&it);
+ } while (ll_iter_prev(&it));
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ ll_free(ll);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_advance(), {
+ struct linkedlist *ll = ll_new(ll_fval);
+
+ cmc_assert_not_equals(ptr, NULL, ll);
+
+ struct linkedlist_iter it = ll_iter_start(ll);
+
+ cmc_assert(!ll_iter_advance(&it, 1));
+
+ for (size_t i = 0; i <= 1000; i++)
+ {
+ if (i % 2 == 0)
+ ll_push_back(ll, i); // will sum all even numbers
+ else
+ ll_push_back(ll, 0);
+ }
+
+ it = ll_iter_start(ll);
+
+ cmc_assert(!ll_iter_advance(&it, 0));
+ cmc_assert(!ll_iter_advance(&it, ll->count));
+
+ size_t sum = 0;
+ for (it = ll_iter_start(ll);;)
+ {
+ sum += ll_iter_value(&it);
+
+ if (!ll_iter_advance(&it, 2))
+ break;
+ }
+
+ cmc_assert_equals(size_t, 250500, sum);
+
+ ll_iter_to_start(&it);
+ cmc_assert(ll_iter_advance(&it, ll->count - 1));
+
+ ll_free(ll);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_rewind(), {
+ struct linkedlist *ll = ll_new(ll_fval);
+
+ cmc_assert_not_equals(ptr, NULL, ll);
+
+ struct linkedlist_iter it = ll_iter_end(ll);
+
+ cmc_assert(!ll_iter_rewind(&it, 1));
+
+ for (size_t i = 0; i <= 1000; i++)
+ {
+ if (i % 2 == 0)
+ ll_push_front(ll, i); // will sum all even numbers
+ else
+ ll_push_front(ll, 0);
+ }
+
+ it = ll_iter_end(ll);
+
+ cmc_assert(!ll_iter_rewind(&it, 0));
+ cmc_assert(!ll_iter_rewind(&it, ll->count));
+
+ size_t sum = 0;
+ for (it = ll_iter_end(ll);;)
+ {
+ sum += ll_iter_value(&it);
+
+ if (!ll_iter_rewind(&it, 2))
+ break;
+ }
+
+ cmc_assert_equals(size_t, 250500, sum);
+
+ ll_iter_to_end(&it);
+ cmc_assert(ll_iter_rewind(&it, ll->count - 1));
+
+ ll_free(ll);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_go_to(), {
+ struct linkedlist *ll = ll_new(ll_fval);
+
+ cmc_assert_not_equals(ptr, NULL, ll);
+
+ struct linkedlist_iter it = ll_iter_end(ll);
+ cmc_assert(!ll_iter_go_to(&it, 0));
+
+ it = ll_iter_start(ll);
+ cmc_assert(!ll_iter_go_to(&it, 0));
+
+ for (size_t i = 0; i <= 1000; i++)
+ ll_push_back(ll, i);
+
+ it = ll_iter_start(ll);
+
+ size_t sum = 0;
+ for (size_t i = 0; i < 1001; i++)
+ {
+ ll_iter_go_to(&it, i);
+
+ sum += ll_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+ for (size_t i = 1001; i > 0; i--)
+ {
+ cmc_assert(ll_iter_go_to(&it, i - 1));
+
+ sum += ll_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+ for (size_t i = 0; i < 1001; i += 100)
+ {
+ cmc_assert(ll_iter_go_to(&it, i));
+ cmc_assert_equals(size_t, i, ll_iter_index(&it));
+
+ sum += ll_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 5500, sum);
+
+ ll_free(ll);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_value(), {
+ struct linkedlist *ll = ll_new(ll_fval);
+
+ cmc_assert_not_equals(ptr, NULL, ll);
+
+ struct linkedlist_iter it = ll_iter_end(ll);
+
+ cmc_assert_equals(size_t, (size_t){ 0 }, ll_iter_value(&it));
+
+ cmc_assert(ll_push_back(ll, 10));
+
+ it = ll_iter_start(ll);
+
+ cmc_assert_equals(size_t, 10, ll_iter_value(&it));
+
+ ll_free(ll);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_rvalue(), {
+ struct linkedlist *ll = ll_new(ll_fval);
+
+ cmc_assert_not_equals(ptr, NULL, ll);
+
+ struct linkedlist_iter it = ll_iter_end(ll);
+
+ cmc_assert_equals(ptr, NULL, ll_iter_rvalue(&it));
+
+ cmc_assert(ll_push_back(ll, 10));
+
+ it = ll_iter_start(ll);
+
+ cmc_assert_not_equals(ptr, NULL, ll_iter_rvalue(&it));
+ cmc_assert_equals(size_t, 10, *ll_iter_rvalue(&it));
+
+ ll_free(ll);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_index(), {
+ struct linkedlist *ll = ll_new(ll_fval);
+
+ cmc_assert_not_equals(ptr, NULL, ll);
+
+ for (size_t i = 0; i <= 1000; i++)
+ ll_push_back(ll, i);
+
+ struct linkedlist_iter it = ll_iter_start(ll);
+
+ for (size_t i = 0; i < 1001; i++)
+ {
+ cmc_assert_equals(size_t, i, ll_iter_index(&it));
+ ll_iter_next(&it);
+ }
+
+ it = ll_iter_end(ll);
+ for (size_t i = 1001; i > 0; i--)
+ {
+ cmc_assert_equals(size_t, i - 1, ll_iter_index(&it));
+ ll_iter_prev(&it);
+ }
+
+ ll_free(ll);
+ });
+});
+
+#ifdef CMC_TEST_MAIN
+int main(void)
+{
+ int result = CMCLinkedList() + CMCLinkedListIter();
+
+ printf(" +---------------------------------------------------------------+");
+ printf("\n");
+ printf(" | CMCLinkedList Suit : %-43s |\n", result == 0 ? "PASSED" : "FAILED");
+ printf(" +---------------------------------------------------------------+");
+ printf("\n\n\n");
+
+ return result;
+}
+#endif
+
+#endif /* CMC_TESTS_UNT_CMC_INKEDLIST_H */
diff --git a/tests/unt_list.h b/tests/unt_list.h
index 2e2c22d..080038a 100644
--- a/tests/unt_list.h
+++ b/tests/unt_list.h
@@ -6,10 +6,6 @@
#define V size_t
#define PFX l
#define SNAME list
-#define CMC_EXT_LIST_INIT
-#define CMC_EXT_LIST_ITER
-#define CMC_EXT_LIST_SEQ
-#define CMC_EXT_LIST_STR
#include "cmc/list.h"
struct list_fval *l_fval = &(struct list_fval){
diff --git a/tests/unt_queue.h b/tests/unt_queue.h
index 07ba548..9f58648 100644
--- a/tests/unt_queue.h
+++ b/tests/unt_queue.h
@@ -6,9 +6,6 @@
#define V size_t
#define PFX q
#define SNAME queue
-#define CMC_EXT_QUEUE_INIT
-#define CMC_EXT_QUEUE_ITER
-#define CMC_EXT_QUEUE_STR
#include "cmc/queue.h"
struct queue_fval *q_fval = &(struct queue_fval){
diff --git a/tests/unt_sortedlist.h b/tests/unt_sortedlist.h
new file mode 100644
index 0000000..12630a8
--- /dev/null
+++ b/tests/unt_sortedlist.h
@@ -0,0 +1,717 @@
+#ifndef CMC_TESTS_UNT_SORTEDLIST_H
+#define CMC_TESTS_UNT_SORTEDLIST_H
+
+#include "utl.h"
+
+#define V size_t
+#define PFX sl
+#define SNAME sortedlist
+#include "cmc/sortedlist.h"
+
+struct sortedlist_fval *sl_fval = &(struct sortedlist_fval){
+ .cmp = cmc_size_cmp, .cpy = NULL, .str = cmc_size_str, .free = NULL, .hash = cmc_size_hash, .pri = cmc_size_cmp
+};
+
+CMC_CREATE_UNIT(CMCSortedList, true, {
+ CMC_CREATE_TEST(new, {
+ struct sortedlist *sl = sl_new(1000000, sl_fval);
+
+ 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);
+ });
+
+ CMC_CREATE_TEST(new[capacity = 0], {
+ struct sortedlist *sl = sl_new(0, sl_fval);
+
+ cmc_assert_equals(ptr, NULL, sl);
+ });
+
+ CMC_CREATE_TEST(new[capacity = UINT64_MAX], {
+ struct sortedlist *sl = sl_new(UINT64_MAX, sl_fval);
+
+ cmc_assert_equals(ptr, NULL, sl);
+ });
+
+ CMC_CREATE_TEST(clear[count capacity], {
+ struct sortedlist *sl = sl_new(100, sl_fval);
+
+ 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);
+
+ cmc_assert_equals(size_t, 0, sl_count(sl));
+ cmc_assert_equals(size_t, 100, sl_capacity(sl));
+
+ sl_free(sl);
+ });
+
+ CMC_CREATE_TEST(buffer_growth[capacity = 1], {
+ struct sortedlist *sl = sl_new(1, sl_fval);
+
+ 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, cmc_size_cmp, 0, sl->count - 1);
+
+ sl_free(sl);
+ });
+
+ CMC_CREATE_TEST(insert, {
+ struct sortedlist *sl = sl_new(100, sl_fval);
+
+ cmc_assert_not_equals(ptr, NULL, sl);
+
+ cmc_assert(sl_insert(sl, 1));
+
+ sl_free(sl);
+ });
+
+ CMC_CREATE_TEST(remove, {
+ struct sortedlist *sl = sl_new(100, sl_fval);
+
+ cmc_assert_not_equals(ptr, NULL, sl);
+
+ cmc_assert(sl_insert(sl, 32));
+
+ cmc_assert(sl_remove(sl, 0));
+
+ sl_free(sl);
+ });
+
+ CMC_CREATE_TEST(remove[count = 0], {
+ struct sortedlist *sl = sl_new(100, sl_fval);
+
+ cmc_assert_not_equals(ptr, NULL, sl);
+
+ cmc_assert(!sl_remove(sl, 0));
+
+ sl_free(sl);
+ });
+
+ CMC_CREATE_TEST(remove[out of range], {
+ struct sortedlist *sl = sl_new(100, sl_fval);
+
+ cmc_assert_not_equals(ptr, NULL, sl);
+
+ cmc_assert(sl_insert(sl, 32));
+
+ cmc_assert(!sl_remove(sl, 2));
+
+ sl_free(sl);
+ });
+
+ CMC_CREATE_TEST(index_of, {
+ struct sortedlist *sl = sl_new(1, sl_fval);
+
+ 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_index_of(sl, 2, true));
+ cmc_assert_equals(size_t, 5, sl_index_of(sl, 2, false));
+
+ cmc_assert_equals(size_t, 0, sl_index_of(sl, 0, true));
+ cmc_assert_equals(size_t, 1, sl_index_of(sl, 0, false));
+
+ cmc_assert(sl_remove(sl, 0));
+
+ cmc_assert_equals(size_t, 0, sl_index_of(sl, 0, true));
+ cmc_assert_equals(size_t, 0, sl_index_of(sl, 0, false));
+
+ cmc_assert(sl_remove(sl, 0));
+
+ cmc_assert_equals(size_t, sl_count(sl), sl_index_of(sl, 0, true));
+ cmc_assert_equals(size_t, sl_count(sl), sl_index_of(sl, 0, false));
+
+ sl_free(sl);
+ });
+
+ CMC_CREATE_TEST(flags, {
+ struct sortedlist *sl = sl_new(100, sl_fval);
+
+ cmc_assert_not_equals(ptr, NULL, sl);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, sl_flag(sl));
+
+ // clear
+ sl->flag = CMC_FLAG_ERROR;
+ sl_clear(sl);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, sl_flag(sl));
+
+ // customize
+ sl->flag = CMC_FLAG_ERROR;
+ sl_customize(sl, NULL, NULL);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, sl_flag(sl));
+
+ // insert
+ sl->flag = CMC_FLAG_ERROR;
+ cmc_assert(sl_insert(sl, 10));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, sl_flag(sl));
+
+ // remove
+ cmc_assert(!sl_remove(sl, 2));
+ cmc_assert_equals(int32_t, CMC_FLAG_RANGE, sl_flag(sl));
+
+ cmc_assert(sl_remove(sl, 0));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, sl_flag(sl));
+
+ cmc_assert(!sl_remove(sl, 0));
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, sl_flag(sl));
+
+ // max min
+ sl->flag = CMC_FLAG_ERROR;
+ cmc_assert_equals(size_t, (size_t){ 0 }, sl_max(sl));
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, sl_flag(sl));
+ sl->flag = CMC_FLAG_ERROR;
+ cmc_assert_equals(size_t, (size_t){ 0 }, sl_min(sl));
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, sl_flag(sl));
+
+ cmc_assert(sl_insert(sl, 1));
+ sl->flag = CMC_FLAG_ERROR;
+ cmc_assert_equals(size_t, 1, sl_max(sl));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, sl_flag(sl));
+ sl->flag = CMC_FLAG_ERROR;
+ cmc_assert_equals(size_t, 1, sl_min(sl));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, sl_flag(sl));
+
+ // get
+ sl->flag = CMC_FLAG_ERROR;
+ sl_get(sl, 1);
+ cmc_assert_equals(int32_t, CMC_FLAG_RANGE, sl_flag(sl));
+
+ sl_get(sl, 0);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, sl_flag(sl));
+
+ cmc_assert(sl_remove(sl, 0));
+ sl_get(sl, 0);
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, sl_flag(sl));
+
+ // index_of
+ cmc_assert(sl_insert(sl, 1));
+ sl_index_of(sl, 1, false);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, sl_flag(sl));
+
+ // contains
+ cmc_assert(sl_contains(sl, 1));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, sl_flag(sl));
+
+ // sort
+ sl->flag = CMC_FLAG_ERROR;
+ sl_sort(sl);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, sl_flag(sl));
+
+ // copy_of
+ sl->flag = CMC_FLAG_ERROR;
+ struct sortedlist *sl2 = sl_copy_of(sl);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, sl_flag(sl));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, sl_flag(sl2));
+
+ // equals
+ sl->flag = CMC_FLAG_ERROR;
+ sl2->flag = CMC_FLAG_ERROR;
+ cmc_assert(sl_equals(sl, sl2));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, sl_flag(sl));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, sl_flag(sl2));
+
+ sl_free(sl);
+ sl_free(sl2);
+ });
+
+ CMC_CREATE_TEST(callbacks, {
+ struct sortedlist *sl = sl_new_custom(100, sl_fval, NULL, callbacks);
+
+ cmc_assert_not_equals(ptr, NULL, sl);
+
+ total_create = 0;
+ total_read = 0;
+ total_update = 0;
+ total_delete = 0;
+ total_resize = 0;
+
+ cmc_assert(sl_insert(sl, 10));
+ cmc_assert_equals(int32_t, 1, total_create);
+
+ cmc_assert(sl_remove(sl, 0));
+ cmc_assert_equals(int32_t, 1, total_delete);
+
+ cmc_assert(sl_insert(sl, 1));
+ cmc_assert(sl_insert(sl, 0));
+ cmc_assert_equals(int32_t, 3, total_create);
+
+ cmc_assert_equals(size_t, 1, sl_max(sl));
+ cmc_assert_equals(int32_t, 1, total_read);
+
+ cmc_assert_equals(size_t, 0, sl_min(sl));
+ cmc_assert_equals(int32_t, 2, total_read);
+
+ cmc_assert_equals(size_t, 0, sl_get(sl, 0));
+ cmc_assert_equals(int32_t, 3, total_read);
+
+ cmc_assert_equals(size_t, 0, sl_index_of(sl, 0, true));
+ cmc_assert_equals(int32_t, 4, total_read);
+
+ cmc_assert(sl_contains(sl, 1));
+ cmc_assert_equals(int32_t, 5, total_read);
+
+ cmc_assert(sl_resize(sl, 1000));
+ cmc_assert_equals(int32_t, 1, total_resize);
+
+ cmc_assert(sl_resize(sl, 50));
+ cmc_assert_equals(int32_t, 2, total_resize);
+
+ cmc_assert_equals(int32_t, 3, total_create);
+ cmc_assert_equals(int32_t, 5, total_read);
+ cmc_assert_equals(int32_t, 0, total_update);
+ cmc_assert_equals(int32_t, 1, total_delete);
+ cmc_assert_equals(int32_t, 2, total_resize);
+
+ sl_customize(sl, NULL, NULL);
+
+ sl_clear(sl);
+ cmc_assert(sl_insert(sl, 10));
+ cmc_assert(sl_remove(sl, 0));
+ cmc_assert(sl_insert(sl, 1));
+ cmc_assert(sl_insert(sl, 0));
+ cmc_assert_equals(size_t, 1, sl_max(sl));
+ cmc_assert_equals(size_t, 0, sl_min(sl));
+ cmc_assert_equals(size_t, 0, sl_get(sl, 0));
+ cmc_assert_equals(size_t, 0, sl_index_of(sl, 0, true));
+ cmc_assert(sl_contains(sl, 1));
+
+ cmc_assert_equals(int32_t, 3, total_create);
+ cmc_assert_equals(int32_t, 5, total_read);
+ cmc_assert_equals(int32_t, 0, total_update);
+ cmc_assert_equals(int32_t, 1, total_delete);
+ cmc_assert_equals(int32_t, 2, total_resize);
+
+ cmc_assert_equals(ptr, NULL, sl->callbacks);
+
+ sl_free(sl);
+
+ total_create = 0;
+ total_read = 0;
+ total_update = 0;
+ total_delete = 0;
+ total_resize = 0;
+ });
+});
+
+CMC_CREATE_UNIT(CMCSortedListIter, true, {
+ CMC_CREATE_TEST(PFX##_iter_start(), {
+ struct sortedlist *sl = sl_new(100, sl_fval);
+
+ cmc_assert_not_equals(ptr, NULL, sl);
+
+ struct sortedlist_iter it = sl_iter_start(sl);
+
+ cmc_assert_equals(ptr, sl, it.target);
+ cmc_assert_equals(size_t, 0, it.cursor);
+ cmc_assert_equals(bool, true, it.start);
+ cmc_assert_equals(bool, true, it.end);
+
+ cmc_assert(sl_iter_at_start(&it));
+ cmc_assert(sl_iter_at_end(&it));
+
+ cmc_assert(sl_insert(sl, 1));
+ cmc_assert(sl_insert(sl, 2));
+
+ it = sl_iter_start(sl);
+
+ cmc_assert_equals(size_t, 0, it.cursor);
+ cmc_assert_equals(bool, false, it.end);
+
+ sl_free(sl);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_end(), {
+ struct sortedlist *sl = sl_new(100, sl_fval);
+
+ cmc_assert_not_equals(ptr, NULL, sl);
+
+ struct sortedlist_iter it = sl_iter_end(sl);
+
+ cmc_assert_equals(ptr, sl, it.target);
+ cmc_assert_equals(size_t, 0, it.cursor);
+ cmc_assert_equals(bool, true, it.start);
+ cmc_assert_equals(bool, true, it.end);
+
+ cmc_assert(sl_iter_at_start(&it));
+ cmc_assert(sl_iter_at_end(&it));
+
+ cmc_assert(sl_insert(sl, 1));
+ cmc_assert(sl_insert(sl, 2));
+ cmc_assert(sl_insert(sl, 3));
+
+ it = sl_iter_end(sl);
+
+ cmc_assert_equals(size_t, sl->count - 1, it.cursor);
+ cmc_assert_equals(bool, false, it.start);
+
+ sl_free(sl);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_at_start(), {
+ struct sortedlist *sl = sl_new(100, sl_fval);
+
+ cmc_assert_not_equals(ptr, NULL, sl);
+
+ struct sortedlist_iter it = sl_iter_start(sl);
+
+ // Empty checks
+ cmc_assert(sl_iter_at_start(&it));
+ it = sl_iter_end(sl);
+ cmc_assert(sl_iter_at_start(&it));
+
+ // Non-empty checks
+ cmc_assert(sl_insert(sl, 1));
+ it = sl_iter_end(sl);
+ cmc_assert(!sl_iter_at_start(&it));
+ it = sl_iter_start(sl);
+ cmc_assert(sl_iter_at_start(&it));
+
+ sl_free(sl);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_at_end(), {
+ struct sortedlist *sl = sl_new(100, sl_fval);
+
+ cmc_assert_not_equals(ptr, NULL, sl);
+
+ struct sortedlist_iter it = sl_iter_start(sl);
+
+ // Empty check
+ cmc_assert(sl_iter_at_end(&it));
+ it = sl_iter_end(sl);
+ cmc_assert(sl_iter_at_end(&it));
+
+ // Non-empty checks
+ cmc_assert(sl_insert(sl, 1));
+ it = sl_iter_end(sl);
+ cmc_assert(sl_iter_at_end(&it));
+ it = sl_iter_start(sl);
+ cmc_assert(!sl_iter_at_end(&it));
+
+ sl_free(sl);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_to_start(), {
+ struct sortedlist *sl = sl_new(100, sl_fval);
+
+ cmc_assert_not_equals(ptr, NULL, sl);
+
+ struct sortedlist_iter it = sl_iter_start(sl);
+
+ cmc_assert(!sl_iter_to_start(&it));
+
+ for (size_t i = 1; i <= 100; i++)
+ sl_insert(sl, i);
+
+ cmc_assert_equals(size_t, 100, sl->count);
+
+ it = sl_iter_end(sl);
+
+ cmc_assert(!sl_iter_at_start(&it));
+ cmc_assert(sl_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 100, sl_iter_value(&it));
+
+ cmc_assert(sl_iter_to_start(&it));
+
+ cmc_assert(sl_iter_at_start(&it));
+ cmc_assert(!sl_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 1, sl_iter_value(&it));
+
+ sl_free(sl);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_to_end(), {
+ struct sortedlist *sl = sl_new(100, sl_fval);
+
+ cmc_assert_not_equals(ptr, NULL, sl);
+
+ struct sortedlist_iter it = sl_iter_end(sl);
+
+ cmc_assert(!sl_iter_to_end(&it));
+
+ for (size_t i = 1; i <= 100; i++)
+ sl_insert(sl, i);
+
+ it = sl_iter_start(sl);
+
+ cmc_assert(sl_iter_at_start(&it));
+ cmc_assert(!sl_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 1, sl_iter_value(&it));
+
+ cmc_assert(sl_iter_to_end(&it));
+
+ cmc_assert(!sl_iter_at_start(&it));
+ cmc_assert(sl_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 100, sl_iter_value(&it));
+
+ sl_free(sl);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_next(), {
+ struct sortedlist *sl = sl_new(100, sl_fval);
+
+ cmc_assert_not_equals(ptr, NULL, sl);
+
+ struct sortedlist_iter it = sl_iter_start(sl);
+
+ cmc_assert(!sl_iter_next(&it));
+
+ for (size_t i = 1; i <= 1000; i++)
+ sl_insert(sl, i);
+
+ size_t sum = 0;
+ for (it = sl_iter_start(sl); !sl_iter_at_end(&it); sl_iter_next(&it))
+ {
+ sum += sl_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+
+ sl_iter_to_start(&it);
+ do
+ {
+ sum += sl_iter_value(&it);
+ } while (sl_iter_next(&it));
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sl_free(sl);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_prev(), {
+ struct sortedlist *sl = sl_new(100, sl_fval);
+
+ cmc_assert_not_equals(ptr, NULL, sl);
+
+ struct sortedlist_iter it = sl_iter_end(sl);
+
+ cmc_assert(!sl_iter_prev(&it));
+
+ for (size_t i = 1; i <= 1000; i++)
+ sl_insert(sl, i);
+
+ size_t sum = 0;
+ for (it = sl_iter_end(sl); !sl_iter_at_start(&it); sl_iter_prev(&it))
+ {
+ sum += sl_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+
+ sl_iter_to_end(&it);
+ do
+ {
+ sum += sl_iter_value(&it);
+ } while (sl_iter_prev(&it));
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sl_free(sl);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_advance(), {
+ struct sortedlist *sl = sl_new(100, sl_fval);
+
+ cmc_assert_not_equals(ptr, NULL, sl);
+
+ struct sortedlist_iter it = sl_iter_start(sl);
+
+ cmc_assert(!sl_iter_advance(&it, 1));
+
+ for (size_t i = 0; i <= 1000; i++)
+ sl_insert(sl, i);
+
+ it = sl_iter_start(sl);
+
+ cmc_assert(!sl_iter_advance(&it, 0));
+ cmc_assert(!sl_iter_advance(&it, sl->count));
+
+ size_t sum = 0;
+ for (it = sl_iter_start(sl);;)
+ {
+ sum += sl_iter_value(&it);
+
+ if (!sl_iter_advance(&it, 2))
+ break;
+ }
+
+ cmc_assert_equals(size_t, 250500, sum);
+
+ sl_iter_to_start(&it);
+ cmc_assert(sl_iter_advance(&it, sl->count - 1));
+
+ sl_free(sl);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_rewind(), {
+ struct sortedlist *sl = sl_new(100, sl_fval);
+
+ cmc_assert_not_equals(ptr, NULL, sl);
+
+ struct sortedlist_iter it = sl_iter_end(sl);
+
+ cmc_assert(!sl_iter_rewind(&it, 1));
+
+ for (size_t i = 0; i <= 1000; i++)
+ sl_insert(sl, i);
+
+ it = sl_iter_end(sl);
+
+ cmc_assert(!sl_iter_rewind(&it, 0));
+ cmc_assert(!sl_iter_rewind(&it, sl->count));
+
+ size_t sum = 0;
+ for (it = sl_iter_end(sl);;)
+ {
+ sum += sl_iter_value(&it);
+
+ if (!sl_iter_rewind(&it, 2))
+ break;
+ }
+
+ cmc_assert_equals(size_t, 250500, sum);
+
+ sl_iter_to_end(&it);
+ cmc_assert(sl_iter_rewind(&it, sl->count - 1));
+
+ sl_free(sl);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_go_to(), {
+ struct sortedlist *sl = sl_new(100, sl_fval);
+
+ cmc_assert_not_equals(ptr, NULL, sl);
+
+ struct sortedlist_iter it = sl_iter_end(sl);
+ cmc_assert(!sl_iter_go_to(&it, 0));
+
+ it = sl_iter_start(sl);
+ cmc_assert(!sl_iter_go_to(&it, 0));
+
+ for (size_t i = 0; i <= 1000; i++)
+ sl_insert(sl, i);
+
+ it = sl_iter_start(sl);
+
+ size_t sum = 0;
+ for (size_t i = 0; i < 1001; i++)
+ {
+ sl_iter_go_to(&it, i);
+
+ sum += sl_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+ for (size_t i = 1001; i > 0; i--)
+ {
+ cmc_assert(sl_iter_go_to(&it, i - 1));
+
+ sum += sl_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+ for (size_t i = 0; i < 1001; i += 100)
+ {
+ cmc_assert(sl_iter_go_to(&it, i));
+ cmc_assert_equals(size_t, i, sl_iter_index(&it));
+
+ sum += sl_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 5500, sum);
+
+ sl_free(sl);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_value(), {
+ struct sortedlist *sl = sl_new(100, sl_fval);
+
+ cmc_assert_not_equals(ptr, NULL, sl);
+
+ struct sortedlist_iter it = sl_iter_end(sl);
+
+ cmc_assert_equals(size_t, (size_t){ 0 }, sl_iter_value(&it));
+
+ cmc_assert(sl_insert(sl, 10));
+
+ it = sl_iter_start(sl);
+
+ cmc_assert_equals(size_t, 10, sl_iter_value(&it));
+
+ sl_free(sl);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_index(), {
+ struct sortedlist *sl = sl_new(100, sl_fval);
+
+ cmc_assert_not_equals(ptr, NULL, sl);
+
+ for (size_t i = 0; i <= 1000; i++)
+ sl_insert(sl, i);
+
+ struct sortedlist_iter it = sl_iter_start(sl);
+
+ for (size_t i = 0; i < 1001; i++)
+ {
+ cmc_assert_equals(size_t, i, sl_iter_index(&it));
+ sl_iter_next(&it);
+ }
+
+ it = sl_iter_end(sl);
+ for (size_t i = 1001; i > 0; i--)
+ {
+ cmc_assert_equals(size_t, i - 1, sl_iter_index(&it));
+ sl_iter_prev(&it);
+ }
+
+ sl_free(sl);
+ });
+});
+
+#ifdef CMC_TEST_MAIN
+int main(void)
+{
+ int result = CMCSortedList() + CMCSortedListIter();
+
+ printf(" +---------------------------------------------------------------+");
+ printf("\n");
+ printf(" | CMCSortedList Suit : %-43s |\n", result == 0 ? "PASSED" : "FAILED");
+ printf(" +---------------------------------------------------------------+");
+ printf("\n\n\n");
+
+ return result;
+}
+#endif
+
+#endif /* CMC_TESTS_UNT_SORTEDLIST_H */
diff --git a/tests/unt_stack.h b/tests/unt_stack.h
index 617a2fa..8756ff3 100644
--- a/tests/unt_stack.h
+++ b/tests/unt_stack.h
@@ -6,9 +6,6 @@
#define V size_t
#define PFX s
#define SNAME stack
-#define CMC_EXT_STACK_INIT
-#define CMC_EXT_STACK_ITER
-#define CMC_EXT_STACK_STR
#include "cmc/stack.h"
struct stack_fval *s_fval = &(struct stack_fval){
diff --git a/tests/unt_treemap.h b/tests/unt_treemap.h
new file mode 100644
index 0000000..f28f63a
--- /dev/null
+++ b/tests/unt_treemap.h
@@ -0,0 +1,674 @@
+#ifndef CMC_TESTS_UNT_TREEMAP_H
+#define CMC_TESTS_UNT_TREEMAP_H
+
+#include "utl.h"
+
+#define V size_t
+#define K size_t
+#define PFX tm
+#define SNAME treemap
+#include "cmc/treemap.h"
+
+struct treemap_fkey *tm_fkey = &(struct treemap_fkey){
+ .cmp = cmc_size_cmp, .cpy = NULL, .str = cmc_size_str, .free = NULL, .hash = cmc_size_hash, .pri = cmc_size_cmp
+};
+
+struct treemap_fval *tm_fval = &(struct treemap_fval){
+ .cmp = cmc_size_cmp, .cpy = NULL, .str = cmc_size_str, .free = NULL, .hash = cmc_size_hash, .pri = cmc_size_cmp
+};
+
+CMC_CREATE_UNIT(CMCTreeMap, true, {
+ CMC_CREATE_TEST(new, {
+ struct treemap *map = tm_new(tm_fkey, tm_fval);
+
+ cmc_assert_not_equals(ptr, NULL, map);
+
+ tm_free(map);
+ });
+
+ CMC_CREATE_TEST(clear[count], {
+ struct treemap *map = tm_new(tm_fkey, tm_fval);
+
+ 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);
+ });
+
+ CMC_CREATE_TEST(flags, {
+ struct treemap *map = tm_new(tm_fkey, tm_fval);
+
+ cmc_assert_not_equals(ptr, NULL, map);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, tm_flag(map));
+
+ // clear
+ map->flag = CMC_FLAG_ERROR;
+ tm_clear(map);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, tm_flag(map));
+
+ // insert
+ map->flag = CMC_FLAG_ERROR;
+ cmc_assert(tm_insert(map, 1, 1));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, tm_flag(map));
+
+ cmc_assert(!tm_insert(map, 1, 2));
+ cmc_assert_equals(int32_t, CMC_FLAG_DUPLICATE, tm_flag(map));
+
+ // update
+ cmc_assert(!tm_update(map, 2, 2, NULL));
+ cmc_assert_equals(int32_t, CMC_FLAG_NOT_FOUND, tm_flag(map));
+
+ cmc_assert(tm_update(map, 1, 2, NULL));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, tm_flag(map));
+
+ // remove
+ cmc_assert(!tm_remove(map, 2, NULL));
+ cmc_assert_equals(int32_t, CMC_FLAG_NOT_FOUND, tm_flag(map));
+
+ cmc_assert(tm_remove(map, 1, NULL));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, tm_flag(map));
+
+ cmc_assert(!tm_remove(map, 1, NULL));
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, tm_flag(map));
+
+ // max min
+ map->flag = CMC_FLAG_ERROR;
+ cmc_assert(!tm_max(map, NULL, NULL));
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, tm_flag(map));
+
+ map->flag = CMC_FLAG_ERROR;
+ cmc_assert(!tm_min(map, NULL, NULL));
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, tm_flag(map));
+
+ cmc_assert(tm_insert(map, 1, 1));
+ map->flag = CMC_FLAG_ERROR;
+ cmc_assert(tm_max(map, NULL, NULL));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, tm_flag(map));
+
+ map->flag = CMC_FLAG_ERROR;
+ cmc_assert(tm_min(map, NULL, NULL));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, tm_flag(map));
+
+ // get get_ref
+ tm_get(map, 2);
+ cmc_assert_equals(int32_t, CMC_FLAG_NOT_FOUND, tm_flag(map));
+
+ tm_get(map, 1);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, tm_flag(map));
+
+ tm_get_ref(map, 2);
+ cmc_assert_equals(int32_t, CMC_FLAG_NOT_FOUND, tm_flag(map));
+
+ tm_get_ref(map, 1);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, tm_flag(map));
+
+ cmc_assert(tm_remove(map, 1, NULL));
+ map->flag = CMC_FLAG_ERROR;
+ tm_get(map, 1);
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, tm_flag(map));
+
+ map->flag = CMC_FLAG_ERROR;
+ tm_get_ref(map, 1);
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, tm_flag(map));
+
+ for (size_t i = 0; i < 100; i++)
+ cmc_assert(tm_insert(map, i, i));
+
+ // copy_of
+ map->flag = CMC_FLAG_ERROR;
+ struct treemap *map2 = tm_copy_of(map);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, tm_flag(map));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, tm_flag(map2));
+
+ // equals
+ map->flag = CMC_FLAG_ERROR;
+ map2->flag = CMC_FLAG_ERROR;
+ cmc_assert(tm_equals(map, map2));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, tm_flag(map));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, tm_flag(map2));
+
+ tm_free(map);
+ tm_free(map2);
+ });
+
+ CMC_CREATE_TEST(callbacks, {
+ struct treemap *map = tm_new_custom(tm_fkey, tm_fval, NULL, callbacks);
+
+ cmc_assert_not_equals(ptr, NULL, map);
+
+ total_create = 0;
+ total_read = 0;
+ total_update = 0;
+ total_delete = 0;
+ total_resize = 0;
+
+ cmc_assert(tm_insert(map, 1, 10));
+ cmc_assert_equals(int32_t, 1, total_create);
+
+ cmc_assert(tm_update(map, 1, 2, NULL));
+ cmc_assert_equals(int32_t, 1, total_update);
+
+ cmc_assert(tm_remove(map, 1, NULL));
+ cmc_assert_equals(int32_t, 1, total_delete);
+
+ cmc_assert(tm_insert(map, 1, 2));
+ cmc_assert_equals(int32_t, 2, total_create);
+
+ cmc_assert(tm_max(map, NULL, NULL));
+ cmc_assert_equals(int32_t, 1, total_read);
+
+ cmc_assert(tm_min(map, NULL, NULL));
+ cmc_assert_equals(int32_t, 2, total_read);
+
+ cmc_assert_equals(size_t, 2, tm_get(map, 1));
+ cmc_assert_equals(int32_t, 3, total_read);
+
+ cmc_assert_not_equals(ptr, NULL, tm_get_ref(map, 1));
+ cmc_assert_equals(int32_t, 4, total_read);
+
+ cmc_assert(tm_contains(map, 1));
+ cmc_assert_equals(int32_t, 5, total_read);
+
+ cmc_assert_equals(int32_t, 2, total_create);
+ cmc_assert_equals(int32_t, 5, total_read);
+ cmc_assert_equals(int32_t, 1, total_update);
+ cmc_assert_equals(int32_t, 1, total_delete);
+ cmc_assert_equals(int32_t, 0, total_resize);
+
+ tm_customize(map, NULL, NULL);
+
+ tm_clear(map);
+ cmc_assert(tm_insert(map, 1, 10));
+ cmc_assert(tm_update(map, 1, 2, NULL));
+ cmc_assert(tm_remove(map, 1, NULL));
+ cmc_assert(tm_insert(map, 1, 2));
+ cmc_assert(tm_max(map, NULL, NULL));
+ cmc_assert(tm_min(map, NULL, NULL));
+ cmc_assert_equals(size_t, 2, tm_get(map, 1));
+ cmc_assert_not_equals(ptr, NULL, tm_get_ref(map, 1));
+ cmc_assert(tm_contains(map, 1));
+
+ cmc_assert_equals(int32_t, 2, total_create);
+ cmc_assert_equals(int32_t, 5, total_read);
+ cmc_assert_equals(int32_t, 1, total_update);
+ cmc_assert_equals(int32_t, 1, total_delete);
+ cmc_assert_equals(int32_t, 0, total_resize);
+
+ cmc_assert_equals(ptr, NULL, map->callbacks);
+
+ total_create = 0;
+ total_read = 0;
+ total_update = 0;
+ total_delete = 0;
+ total_resize = 0;
+
+ tm_free(map);
+ });
+});
+
+CMC_CREATE_UNIT(CMCTreeMapIter, true, {
+ CMC_CREATE_TEST(PFX##_iter_start(), {
+ struct treemap *map = tm_new(tm_fkey, tm_fval);
+
+ cmc_assert_not_equals(ptr, NULL, map);
+
+ struct treemap_iter it = tm_iter_start(map);
+
+ cmc_assert_equals(ptr, map, it.target);
+ cmc_assert_equals(ptr, NULL, it.cursor);
+ cmc_assert_equals(ptr, NULL, it.first);
+ cmc_assert_equals(ptr, NULL, it.last);
+ cmc_assert_equals(size_t, 0, it.index);
+ cmc_assert_equals(bool, true, it.start);
+ cmc_assert_equals(bool, true, it.end);
+
+ cmc_assert(tm_iter_at_start(&it));
+ cmc_assert(tm_iter_at_end(&it));
+
+ cmc_assert(tm_insert(map, 1, 1));
+ cmc_assert(tm_insert(map, 2, 2));
+ cmc_assert(tm_insert(map, 3, 3));
+
+ it = tm_iter_start(map);
+
+ cmc_assert_equals(size_t, 0, it.index);
+
+ cmc_assert_equals(size_t, 1, it.cursor->key);
+ cmc_assert_equals(size_t, 1, it.first->key);
+ cmc_assert_equals(size_t, 3, it.last->key);
+ cmc_assert_equals(bool, false, it.end);
+
+ tm_free(map);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_end(), {
+ struct treemap *map = tm_new(tm_fkey, tm_fval);
+
+ cmc_assert_not_equals(ptr, NULL, map);
+
+ struct treemap_iter it = tm_iter_end(map);
+
+ cmc_assert_equals(ptr, map, it.target);
+ cmc_assert_equals(ptr, NULL, it.cursor);
+ cmc_assert_equals(ptr, NULL, it.first);
+ cmc_assert_equals(ptr, NULL, it.last);
+ cmc_assert_equals(size_t, 0, it.index);
+ cmc_assert_equals(bool, true, it.start);
+ cmc_assert_equals(bool, true, it.end);
+
+ cmc_assert(tm_iter_at_start(&it));
+ cmc_assert(tm_iter_at_end(&it));
+
+ cmc_assert(tm_insert(map, 1, 1));
+ cmc_assert(tm_insert(map, 2, 2));
+ cmc_assert(tm_insert(map, 3, 3));
+
+ it = tm_iter_end(map);
+
+ cmc_assert_equals(size_t, map->count - 1, it.index);
+
+ cmc_assert_equals(size_t, 3, it.cursor->key);
+ cmc_assert_equals(size_t, 1, it.first->key);
+ cmc_assert_equals(size_t, 3, it.last->key);
+ cmc_assert_equals(bool, false, it.start);
+
+ tm_free(map);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_at_start(), {
+ struct treemap *map = tm_new(tm_fkey, tm_fval);
+
+ cmc_assert_not_equals(ptr, NULL, map);
+
+ struct treemap_iter it = tm_iter_start(map);
+
+ // Empty checks
+ cmc_assert(tm_iter_at_start(&it));
+ it = tm_iter_end(map);
+ cmc_assert(tm_iter_at_start(&it));
+
+ // Non-empty checks
+ cmc_assert(tm_insert(map, 1, 1));
+ cmc_assert(tm_insert(map, 2, 2));
+ it = tm_iter_end(map);
+ cmc_assert(!tm_iter_at_start(&it));
+ it = tm_iter_start(map);
+ cmc_assert(tm_iter_at_start(&it));
+
+ tm_free(map);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_at_end(), {
+ struct treemap *map = tm_new(tm_fkey, tm_fval);
+
+ cmc_assert_not_equals(ptr, NULL, map);
+
+ struct treemap_iter it = tm_iter_start(map);
+
+ // Empty check
+ cmc_assert(tm_iter_at_end(&it));
+ it = tm_iter_end(map);
+ cmc_assert(tm_iter_at_end(&it));
+
+ // Non-empty checks
+ cmc_assert(tm_insert(map, 1, 1));
+ cmc_assert(tm_insert(map, 2, 2));
+ it = tm_iter_end(map);
+ cmc_assert(tm_iter_at_end(&it));
+ it = tm_iter_start(map);
+ cmc_assert(!tm_iter_at_end(&it));
+
+ tm_free(map);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_to_start(), {
+ struct treemap *map = tm_new(tm_fkey, tm_fval);
+
+ cmc_assert_not_equals(ptr, NULL, map);
+
+ struct treemap_iter it = tm_iter_start(map);
+
+ cmc_assert(!tm_iter_to_start(&it));
+
+ for (size_t i = 1; i <= 100; i++)
+ tm_insert(map, i, i);
+
+ cmc_assert_equals(size_t, 100, map->count);
+
+ it = tm_iter_end(map);
+
+ cmc_assert(!tm_iter_at_start(&it));
+ cmc_assert(tm_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 100, tm_iter_value(&it));
+
+ cmc_assert(tm_iter_to_start(&it));
+
+ cmc_assert(tm_iter_at_start(&it));
+ cmc_assert(!tm_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 1, tm_iter_value(&it));
+
+ tm_free(map);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_to_end(), {
+ struct treemap *map = tm_new(tm_fkey, tm_fval);
+
+ cmc_assert_not_equals(ptr, NULL, map);
+
+ struct treemap_iter it = tm_iter_end(map);
+
+ cmc_assert(!tm_iter_to_end(&it));
+
+ for (size_t i = 1; i <= 100; i++)
+ tm_insert(map, i, i);
+
+ it = tm_iter_start(map);
+
+ cmc_assert(tm_iter_at_start(&it));
+ cmc_assert(!tm_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 1, tm_iter_value(&it));
+
+ cmc_assert(tm_iter_to_end(&it));
+
+ cmc_assert(!tm_iter_at_start(&it));
+ cmc_assert(tm_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 100, tm_iter_value(&it));
+
+ tm_free(map);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_next(), {
+ struct treemap *map = tm_new(tm_fkey, tm_fval);
+
+ cmc_assert_not_equals(ptr, NULL, map);
+
+ struct treemap_iter it = tm_iter_start(map);
+
+ cmc_assert(!tm_iter_next(&it));
+
+ for (size_t i = 1; i <= 1000; i++)
+ tm_insert(map, i, i);
+
+ size_t sum = 0;
+ for (it = tm_iter_start(map); !tm_iter_at_end(&it); tm_iter_next(&it))
+ {
+ sum += tm_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+
+ tm_iter_to_start(&it);
+ do
+ {
+ sum += tm_iter_value(&it);
+ } while (tm_iter_next(&it));
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ tm_free(map);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_prev(), {
+ struct treemap *map = tm_new(tm_fkey, tm_fval);
+
+ cmc_assert_not_equals(ptr, NULL, map);
+
+ struct treemap_iter it = tm_iter_end(map);
+
+ cmc_assert(!tm_iter_prev(&it));
+
+ for (size_t i = 1; i <= 1000; i++)
+ tm_insert(map, i, i);
+
+ size_t sum = 0;
+ for (it = tm_iter_end(map); !tm_iter_at_start(&it); tm_iter_prev(&it))
+ {
+ sum += tm_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+
+ tm_iter_to_end(&it);
+ do
+ {
+ sum += tm_iter_value(&it);
+ } while (tm_iter_prev(&it));
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ tm_free(map);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_advance(), {
+ struct treemap *map = tm_new(tm_fkey, tm_fval);
+
+ cmc_assert_not_equals(ptr, NULL, map);
+
+ struct treemap_iter it = tm_iter_start(map);
+
+ cmc_assert(!tm_iter_advance(&it, 1));
+
+ for (size_t i = 0; i <= 1000; i++)
+ tm_insert(map, i, i);
+
+ it = tm_iter_start(map);
+
+ cmc_assert(!tm_iter_advance(&it, 0));
+ cmc_assert(!tm_iter_advance(&it, map->count));
+
+ size_t sum = 0;
+ for (it = tm_iter_start(map);;)
+ {
+ sum += tm_iter_value(&it);
+
+ if (!tm_iter_advance(&it, 2))
+ break;
+ }
+
+ cmc_assert_equals(size_t, 250500, sum);
+
+ tm_iter_to_start(&it);
+ cmc_assert(tm_iter_advance(&it, map->count - 1));
+
+ tm_free(map);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_rewind(), {
+ struct treemap *map = tm_new(tm_fkey, tm_fval);
+
+ cmc_assert_not_equals(ptr, NULL, map);
+
+ struct treemap_iter it = tm_iter_end(map);
+
+ cmc_assert(!tm_iter_rewind(&it, 1));
+
+ for (size_t i = 0; i <= 1000; i++)
+ tm_insert(map, i, i);
+
+ it = tm_iter_end(map);
+
+ cmc_assert(!tm_iter_rewind(&it, 0));
+ cmc_assert(!tm_iter_rewind(&it, map->count));
+
+ size_t sum = 0;
+ for (it = tm_iter_end(map);;)
+ {
+ sum += tm_iter_value(&it);
+
+ if (!tm_iter_rewind(&it, 2))
+ break;
+ }
+
+ cmc_assert_equals(size_t, 250500, sum);
+
+ tm_iter_to_end(&it);
+ cmc_assert(tm_iter_rewind(&it, map->count - 1));
+
+ tm_free(map);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_go_to(), {
+ struct treemap *map = tm_new(tm_fkey, tm_fval);
+
+ cmc_assert_not_equals(ptr, NULL, map);
+
+ struct treemap_iter it = tm_iter_end(map);
+ cmc_assert(!tm_iter_go_to(&it, 0));
+
+ it = tm_iter_start(map);
+ cmc_assert(!tm_iter_go_to(&it, 0));
+
+ for (size_t i = 0; i <= 1000; i++)
+ tm_insert(map, i, i);
+
+ it = tm_iter_start(map);
+
+ size_t sum = 0;
+ for (size_t i = 0; i < 1001; i++)
+ {
+ tm_iter_go_to(&it, i);
+
+ sum += tm_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+ for (size_t i = 1001; i > 0; i--)
+ {
+ cmc_assert(tm_iter_go_to(&it, i - 1));
+
+ sum += tm_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+ for (size_t i = 0; i < 1001; i += 100)
+ {
+ cmc_assert(tm_iter_go_to(&it, i));
+ cmc_assert_equals(size_t, i, tm_iter_index(&it));
+
+ sum += tm_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 5500, sum);
+
+ tm_free(map);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_key(), {
+ struct treemap *map = tm_new(tm_fkey, tm_fval);
+
+ cmc_assert_not_equals(ptr, NULL, map);
+
+ struct treemap_iter it = tm_iter_end(map);
+
+ cmc_assert_equals(size_t, (size_t){ 0 }, tm_iter_key(&it));
+
+ cmc_assert(tm_insert(map, 10, 10));
+
+ it = tm_iter_start(map);
+
+ cmc_assert_equals(size_t, 10, tm_iter_key(&it));
+
+ tm_free(map);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_value(), {
+ struct treemap *map = tm_new(tm_fkey, tm_fval);
+
+ cmc_assert_not_equals(ptr, NULL, map);
+
+ struct treemap_iter it = tm_iter_end(map);
+
+ cmc_assert_equals(size_t, (size_t){ 0 }, tm_iter_value(&it));
+
+ cmc_assert(tm_insert(map, 10, 10));
+
+ it = tm_iter_start(map);
+
+ cmc_assert_equals(size_t, 10, tm_iter_value(&it));
+
+ tm_free(map);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_rvalue(), {
+ struct treemap *map = tm_new(tm_fkey, tm_fval);
+
+ cmc_assert_not_equals(ptr, NULL, map);
+
+ struct treemap_iter it = tm_iter_end(map);
+
+ cmc_assert_equals(ptr, NULL, tm_iter_rvalue(&it));
+
+ cmc_assert(tm_insert(map, 10, 10));
+
+ it = tm_iter_start(map);
+
+ cmc_assert_not_equals(ptr, NULL, tm_iter_rvalue(&it));
+ cmc_assert_equals(size_t, 10, *tm_iter_rvalue(&it));
+
+ tm_free(map);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_index(), {
+ struct treemap *map = tm_new(tm_fkey, tm_fval);
+
+ cmc_assert_not_equals(ptr, NULL, map);
+
+ for (size_t i = 0; i <= 1000; i++)
+ tm_insert(map, i, i);
+
+ struct treemap_iter it = tm_iter_start(map);
+
+ for (size_t i = 0; i < 1001; i++)
+ {
+ cmc_assert_equals(size_t, i, tm_iter_index(&it));
+ tm_iter_next(&it);
+ }
+
+ it = tm_iter_end(map);
+ for (size_t i = 1001; i > 0; i--)
+ {
+ cmc_assert_equals(size_t, i - 1, tm_iter_index(&it));
+ tm_iter_prev(&it);
+ }
+
+ tm_free(map);
+ });
+});
+
+#ifdef CMC_TEST_MAIN
+int main(void)
+{
+ int result = CMCTreeMap() + CMCTreeMapIter();
+
+ printf(" +---------------------------------------------------------------+");
+ printf("\n");
+ printf(" | CMCTreeMap Suit : %-46s |\n", result == 0 ? "PASSED" : "FAILED");
+ printf(" +---------------------------------------------------------------+");
+ printf("\n\n\n");
+
+ return result;
+}
+#endif
+
+#endif /* CMC_TESTS_UNT_TREEMAP_H */
diff --git a/tests/unt_treeset.h b/tests/unt_treeset.h
new file mode 100644
index 0000000..0f26c66
--- /dev/null
+++ b/tests/unt_treeset.h
@@ -0,0 +1,588 @@
+#ifndef CMC_TESTS_UNT_TREESET_H
+#define CMC_TESTS_UNT_TREESET_H
+
+#include "utl.h"
+
+#define V size_t
+#define PFX ts
+#define SNAME treeset
+#include "cmc/treeset.h"
+
+struct treeset_fval *ts_fval = &(struct treeset_fval){
+ .cmp = cmc_size_cmp, .cpy = NULL, .str = cmc_size_str, .free = NULL, .hash = cmc_size_hash, .pri = cmc_size_cmp
+};
+
+CMC_CREATE_UNIT(CMCTreeSet, true, {
+ CMC_CREATE_TEST(new, {
+ struct treeset *set = ts_new(ts_fval);
+
+ cmc_assert_not_equals(ptr, NULL, set);
+
+ ts_free(set);
+ });
+
+ CMC_CREATE_TEST(clear[count], {
+ struct treeset *set = ts_new(ts_fval);
+
+ 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);
+ });
+
+ CMC_CREATE_TEST(flags, {
+ struct treeset *set = ts_new(ts_fval);
+
+ cmc_assert_not_equals(ptr, NULL, set);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ts_flag(set));
+
+ // clear
+ set->flag = CMC_FLAG_ERROR;
+ ts_clear(set);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ts_flag(set));
+
+ // insert
+ set->flag = CMC_FLAG_ERROR;
+ cmc_assert(ts_insert(set, 1));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ts_flag(set));
+
+ cmc_assert(!ts_insert(set, 1));
+ cmc_assert_equals(int32_t, CMC_FLAG_DUPLICATE, ts_flag(set));
+
+ // remove
+ cmc_assert(!ts_remove(set, 2));
+ cmc_assert_equals(int32_t, CMC_FLAG_NOT_FOUND, ts_flag(set));
+
+ cmc_assert(ts_remove(set, 1));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ts_flag(set));
+
+ cmc_assert(!ts_remove(set, 1));
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, ts_flag(set));
+
+ // max min
+ set->flag = CMC_FLAG_ERROR;
+ cmc_assert(!ts_max(set, NULL));
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, ts_flag(set));
+
+ set->flag = CMC_FLAG_ERROR;
+ cmc_assert(!ts_min(set, NULL));
+ cmc_assert_equals(int32_t, CMC_FLAG_EMPTY, ts_flag(set));
+
+ cmc_assert(ts_insert(set, 1));
+ set->flag = CMC_FLAG_ERROR;
+ cmc_assert(ts_max(set, NULL));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ts_flag(set));
+
+ set->flag = CMC_FLAG_ERROR;
+ cmc_assert(ts_min(set, NULL));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ts_flag(set));
+
+ // copy_of
+ set->flag = CMC_FLAG_ERROR;
+ struct treeset *set2 = ts_copy_of(set);
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ts_flag(set));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ts_flag(set2));
+
+ // equals
+ set->flag = CMC_FLAG_ERROR;
+ set2->flag = CMC_FLAG_ERROR;
+ cmc_assert(ts_equals(set, set2));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ts_flag(set));
+ cmc_assert_equals(int32_t, CMC_FLAG_OK, ts_flag(set2));
+
+ ts_free(set);
+ ts_free(set2);
+ });
+
+ CMC_CREATE_TEST(callbacks, {
+ struct treeset *set = ts_new_custom(ts_fval, NULL, callbacks);
+
+ cmc_assert_not_equals(ptr, NULL, set);
+
+ total_create = 0;
+ total_read = 0;
+ total_update = 0;
+ total_delete = 0;
+ total_resize = 0;
+
+ cmc_assert(ts_insert(set, 10));
+ cmc_assert_equals(int32_t, 1, total_create);
+
+ cmc_assert(ts_remove(set, 10));
+ cmc_assert_equals(int32_t, 1, total_delete);
+
+ cmc_assert(ts_insert(set, 1));
+ cmc_assert_equals(int32_t, 2, total_create);
+
+ cmc_assert(ts_max(set, NULL));
+ cmc_assert_equals(int32_t, 1, total_read);
+
+ cmc_assert(ts_min(set, NULL));
+ cmc_assert_equals(int32_t, 2, total_read);
+
+ cmc_assert(ts_contains(set, 1));
+ cmc_assert_equals(int32_t, 3, total_read);
+
+ cmc_assert_equals(int32_t, 2, total_create);
+ cmc_assert_equals(int32_t, 3, total_read);
+ cmc_assert_equals(int32_t, 0, total_update);
+ cmc_assert_equals(int32_t, 1, total_delete);
+ cmc_assert_equals(int32_t, 0, total_resize);
+
+ ts_customize(set, NULL, NULL);
+
+ ts_clear(set);
+ cmc_assert(ts_insert(set, 10));
+ cmc_assert(ts_remove(set, 10));
+ cmc_assert(ts_insert(set, 1));
+ cmc_assert(ts_max(set, NULL));
+ cmc_assert(ts_min(set, NULL));
+ cmc_assert(ts_contains(set, 1));
+
+ cmc_assert_equals(int32_t, 2, total_create);
+ cmc_assert_equals(int32_t, 3, total_read);
+ cmc_assert_equals(int32_t, 0, total_update);
+ cmc_assert_equals(int32_t, 1, total_delete);
+ cmc_assert_equals(int32_t, 0, total_resize);
+
+ cmc_assert_equals(ptr, NULL, set->callbacks);
+
+ total_create = 0;
+ total_read = 0;
+ total_update = 0;
+ total_delete = 0;
+ total_resize = 0;
+
+ ts_free(set);
+ });
+});
+
+CMC_CREATE_UNIT(CMCTreeSetIter, true, {
+ CMC_CREATE_TEST(PFX##_iter_start(), {
+ struct treeset *set = ts_new(ts_fval);
+
+ cmc_assert_not_equals(ptr, NULL, set);
+
+ struct treeset_iter it = ts_iter_start(set);
+
+ cmc_assert_equals(ptr, set, it.target);
+ cmc_assert_equals(ptr, NULL, it.cursor);
+ cmc_assert_equals(ptr, NULL, it.first);
+ cmc_assert_equals(ptr, NULL, it.last);
+ cmc_assert_equals(size_t, 0, it.index);
+ cmc_assert_equals(bool, true, it.start);
+ cmc_assert_equals(bool, true, it.end);
+
+ cmc_assert(ts_iter_at_start(&it));
+ cmc_assert(ts_iter_at_end(&it));
+
+ cmc_assert(ts_insert(set, 1));
+ cmc_assert(ts_insert(set, 2));
+ cmc_assert(ts_insert(set, 3));
+
+ it = ts_iter_start(set);
+
+ cmc_assert_equals(size_t, 0, it.index);
+
+ cmc_assert_equals(size_t, 1, it.cursor->value);
+ cmc_assert_equals(size_t, 1, it.first->value);
+ cmc_assert_equals(size_t, 3, it.last->value);
+ cmc_assert_equals(bool, false, it.end);
+
+ ts_free(set);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_end(), {
+ struct treeset *set = ts_new(ts_fval);
+
+ cmc_assert_not_equals(ptr, NULL, set);
+
+ struct treeset_iter it = ts_iter_end(set);
+
+ cmc_assert_equals(ptr, set, it.target);
+ cmc_assert_equals(ptr, NULL, it.cursor);
+ cmc_assert_equals(ptr, NULL, it.first);
+ cmc_assert_equals(ptr, NULL, it.last);
+ cmc_assert_equals(size_t, 0, it.index);
+ cmc_assert_equals(bool, true, it.start);
+ cmc_assert_equals(bool, true, it.end);
+
+ cmc_assert(ts_iter_at_start(&it));
+ cmc_assert(ts_iter_at_end(&it));
+
+ cmc_assert(ts_insert(set, 1));
+ cmc_assert(ts_insert(set, 2));
+ cmc_assert(ts_insert(set, 3));
+
+ it = ts_iter_end(set);
+
+ cmc_assert_equals(size_t, set->count - 1, it.index);
+
+ cmc_assert_equals(size_t, 3, it.cursor->value);
+ cmc_assert_equals(size_t, 1, it.first->value);
+ cmc_assert_equals(size_t, 3, it.last->value);
+ cmc_assert_equals(bool, false, it.start);
+
+ ts_free(set);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_at_start(), {
+ struct treeset *set = ts_new(ts_fval);
+
+ cmc_assert_not_equals(ptr, NULL, set);
+
+ struct treeset_iter it = ts_iter_start(set);
+
+ // Empty checks
+ cmc_assert(ts_iter_at_start(&it));
+ it = ts_iter_end(set);
+ cmc_assert(ts_iter_at_start(&it));
+
+ // Non-empty checks
+ cmc_assert(ts_insert(set, 1));
+ cmc_assert(ts_insert(set, 2));
+ it = ts_iter_end(set);
+ cmc_assert(!ts_iter_at_start(&it));
+ it = ts_iter_start(set);
+ cmc_assert(ts_iter_at_start(&it));
+
+ ts_free(set);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_at_end(), {
+ struct treeset *set = ts_new(ts_fval);
+
+ cmc_assert_not_equals(ptr, NULL, set);
+
+ struct treeset_iter it = ts_iter_start(set);
+
+ // Empty check
+ cmc_assert(ts_iter_at_end(&it));
+ it = ts_iter_end(set);
+ cmc_assert(ts_iter_at_end(&it));
+
+ // Non-empty checks
+ cmc_assert(ts_insert(set, 1));
+ cmc_assert(ts_insert(set, 2));
+ it = ts_iter_end(set);
+ cmc_assert(ts_iter_at_end(&it));
+ it = ts_iter_start(set);
+ cmc_assert(!ts_iter_at_end(&it));
+
+ ts_free(set);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_to_start(), {
+ struct treeset *set = ts_new(ts_fval);
+
+ cmc_assert_not_equals(ptr, NULL, set);
+
+ struct treeset_iter it = ts_iter_start(set);
+
+ cmc_assert(!ts_iter_to_start(&it));
+
+ for (size_t i = 1; i <= 100; i++)
+ ts_insert(set, i);
+
+ cmc_assert_equals(size_t, 100, set->count);
+
+ it = ts_iter_end(set);
+
+ cmc_assert(!ts_iter_at_start(&it));
+ cmc_assert(ts_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 100, ts_iter_value(&it));
+
+ cmc_assert(ts_iter_to_start(&it));
+
+ cmc_assert(ts_iter_at_start(&it));
+ cmc_assert(!ts_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 1, ts_iter_value(&it));
+
+ ts_free(set);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_to_end(), {
+ struct treeset *set = ts_new(ts_fval);
+
+ cmc_assert_not_equals(ptr, NULL, set);
+
+ struct treeset_iter it = ts_iter_end(set);
+
+ cmc_assert(!ts_iter_to_end(&it));
+
+ for (size_t i = 1; i <= 100; i++)
+ ts_insert(set, i);
+
+ it = ts_iter_start(set);
+
+ cmc_assert(ts_iter_at_start(&it));
+ cmc_assert(!ts_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 1, ts_iter_value(&it));
+
+ cmc_assert(ts_iter_to_end(&it));
+
+ cmc_assert(!ts_iter_at_start(&it));
+ cmc_assert(ts_iter_at_end(&it));
+
+ cmc_assert_equals(size_t, 100, ts_iter_value(&it));
+
+ ts_free(set);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_next(), {
+ struct treeset *set = ts_new(ts_fval);
+
+ cmc_assert_not_equals(ptr, NULL, set);
+
+ struct treeset_iter it = ts_iter_start(set);
+
+ cmc_assert(!ts_iter_next(&it));
+
+ for (size_t i = 1; i <= 1000; i++)
+ ts_insert(set, i);
+
+ size_t sum = 0;
+ for (it = ts_iter_start(set); !ts_iter_at_end(&it); ts_iter_next(&it))
+ {
+ sum += ts_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+
+ ts_iter_to_start(&it);
+ do
+ {
+ sum += ts_iter_value(&it);
+ } while (ts_iter_next(&it));
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ ts_free(set);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_prev(), {
+ struct treeset *set = ts_new(ts_fval);
+
+ cmc_assert_not_equals(ptr, NULL, set);
+
+ struct treeset_iter it = ts_iter_end(set);
+
+ cmc_assert(!ts_iter_prev(&it));
+
+ for (size_t i = 1; i <= 1000; i++)
+ ts_insert(set, i);
+
+ size_t sum = 0;
+ for (it = ts_iter_end(set); !ts_iter_at_start(&it); ts_iter_prev(&it))
+ {
+ sum += ts_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+
+ ts_iter_to_end(&it);
+ do
+ {
+ sum += ts_iter_value(&it);
+ } while (ts_iter_prev(&it));
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ ts_free(set);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_advance(), {
+ struct treeset *set = ts_new(ts_fval);
+
+ cmc_assert_not_equals(ptr, NULL, set);
+
+ struct treeset_iter it = ts_iter_start(set);
+
+ cmc_assert(!ts_iter_advance(&it, 1));
+
+ for (size_t i = 0; i <= 1000; i++)
+ ts_insert(set, i);
+
+ it = ts_iter_start(set);
+
+ cmc_assert(!ts_iter_advance(&it, 0));
+ cmc_assert(!ts_iter_advance(&it, set->count));
+
+ size_t sum = 0;
+ for (it = ts_iter_start(set);;)
+ {
+ sum += ts_iter_value(&it);
+
+ if (!ts_iter_advance(&it, 2))
+ break;
+ }
+
+ cmc_assert_equals(size_t, 250500, sum);
+
+ ts_iter_to_start(&it);
+ cmc_assert(ts_iter_advance(&it, set->count - 1));
+
+ ts_free(set);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_rewind(), {
+ struct treeset *set = ts_new(ts_fval);
+
+ cmc_assert_not_equals(ptr, NULL, set);
+
+ struct treeset_iter it = ts_iter_end(set);
+
+ cmc_assert(!ts_iter_rewind(&it, 1));
+
+ for (size_t i = 0; i <= 1000; i++)
+ ts_insert(set, i);
+
+ it = ts_iter_end(set);
+
+ cmc_assert(!ts_iter_rewind(&it, 0));
+ cmc_assert(!ts_iter_rewind(&it, set->count));
+
+ size_t sum = 0;
+ for (it = ts_iter_end(set);;)
+ {
+ sum += ts_iter_value(&it);
+
+ if (!ts_iter_rewind(&it, 2))
+ break;
+ }
+
+ cmc_assert_equals(size_t, 250500, sum);
+
+ ts_iter_to_end(&it);
+ cmc_assert(ts_iter_rewind(&it, set->count - 1));
+
+ ts_free(set);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_go_to(), {
+ struct treeset *set = ts_new(ts_fval);
+
+ cmc_assert_not_equals(ptr, NULL, set);
+
+ struct treeset_iter it = ts_iter_end(set);
+ cmc_assert(!ts_iter_go_to(&it, 0));
+
+ it = ts_iter_start(set);
+ cmc_assert(!ts_iter_go_to(&it, 0));
+
+ for (size_t i = 0; i <= 1000; i++)
+ ts_insert(set, i);
+
+ it = ts_iter_start(set);
+
+ size_t sum = 0;
+ for (size_t i = 0; i < 1001; i++)
+ {
+ ts_iter_go_to(&it, i);
+
+ sum += ts_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+ for (size_t i = 1001; i > 0; i--)
+ {
+ cmc_assert(ts_iter_go_to(&it, i - 1));
+
+ sum += ts_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 500500, sum);
+
+ sum = 0;
+ for (size_t i = 0; i < 1001; i += 100)
+ {
+ cmc_assert(ts_iter_go_to(&it, i));
+ cmc_assert_equals(size_t, i, ts_iter_index(&it));
+
+ sum += ts_iter_value(&it);
+ }
+
+ cmc_assert_equals(size_t, 5500, sum);
+
+ ts_free(set);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_value(), {
+ struct treeset *set = ts_new(ts_fval);
+
+ cmc_assert_not_equals(ptr, NULL, set);
+
+ struct treeset_iter it = ts_iter_end(set);
+
+ cmc_assert_equals(size_t, (size_t){ 0 }, ts_iter_value(&it));
+
+ cmc_assert(ts_insert(set, 10));
+
+ it = ts_iter_start(set);
+
+ cmc_assert_equals(size_t, 10, ts_iter_value(&it));
+
+ ts_free(set);
+ });
+
+ CMC_CREATE_TEST(PFX##_iter_index(), {
+ struct treeset *set = ts_new(ts_fval);
+
+ cmc_assert_not_equals(ptr, NULL, set);
+
+ for (size_t i = 0; i <= 1000; i++)
+ ts_insert(set, i);
+
+ struct treeset_iter it = ts_iter_start(set);
+
+ for (size_t i = 0; i < 1001; i++)
+ {
+ cmc_assert_equals(size_t, i, ts_iter_index(&it));
+ ts_iter_next(&it);
+ }
+
+ it = ts_iter_end(set);
+ for (size_t i = 1001; i > 0; i--)
+ {
+ cmc_assert_equals(size_t, i - 1, ts_iter_index(&it));
+ ts_iter_prev(&it);
+ }
+
+ ts_free(set);
+ });
+});
+
+#ifdef CMC_TEST_MAIN
+int main(void)
+{
+ int result = CMCTreeSet() + CMCTreeSetIter();
+
+ printf(" +---------------------------------------------------------------+");
+ printf("\n");
+ printf(" | CMCTreeSet Suit : %-46s |\n", result == 0 ? "PASSED" : "FAILED");
+ printf(" +---------------------------------------------------------------+");
+ printf("\n\n\n");
+
+ return result;
+}
+#endif
+
+#endif /* CMC_TESTS_UNT_TREESET_H */