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 @@

LinkToRepo - Stars LinkToDocs

@@ -20,6 +19,12 @@ test_suit

+

+ Stars + loc + loc +

+ ## 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 | ![#9f3b94](https://via.placeholder.com/20/9f3b94/000000?text=+) | ![#9f3b94](https://via.placeholder.com/20/9f3b94/000000?text=+) | ![#497edd](https://via.placeholder.com/20/497edd/000000?text=+) | ![#00d3eb](https://via.placeholder.com/20/00d3eb/000000?text=+) | ![#2ef625](https://via.placeholder.com/20/2ef625/000000?text=+) | ![#2ef625](https://via.placeholder.com/20/2ef625/000000?text=+) | | HashMap | ![#b82b28](https://via.placeholder.com/20/b82b28/000000?text=+) | ![#9f3b94](https://via.placeholder.com/20/9f3b94/000000?text=+) | ![#497edd](https://via.placeholder.com/20/497edd/000000?text=+) | ![#00d3eb](https://via.placeholder.com/20/00d3eb/000000?text=+) | ![#b82b28](https://via.placeholder.com/20/b82b28/000000?text=+) | ![#2ef625](https://via.placeholder.com/20/2ef625/000000?text=+) | | HashBidiMap | ![#b82b28](https://via.placeholder.com/20/b82b28/000000?text=+) | ![#9f3b94](https://via.placeholder.com/20/9f3b94/000000?text=+) | ![#497edd](https://via.placeholder.com/20/497edd/000000?text=+) | ![#00d3eb](https://via.placeholder.com/20/00d3eb/000000?text=+) | ![#b82b28](https://via.placeholder.com/20/b82b28/000000?text=+) | ![#2ef625](https://via.placeholder.com/20/2ef625/000000?text=+) | @@ -257,8 +259,8 @@ The following table shows which functions are required, optional or never used f | TreeMap | ![#b82b28](https://via.placeholder.com/20/b82b28/000000?text=+) | ![#9f3b94](https://via.placeholder.com/20/9f3b94/000000?text=+) | ![#497edd](https://via.placeholder.com/20/497edd/000000?text=+) | ![#00d3eb](https://via.placeholder.com/20/00d3eb/000000?text=+) | ![#2ef625](https://via.placeholder.com/20/2ef625/000000?text=+) | ![#2ef625](https://via.placeholder.com/20/2ef625/000000?text=+) | | TreeSet | ![#b82b28](https://via.placeholder.com/20/b82b28/000000?text=+) | ![#9f3b94](https://via.placeholder.com/20/9f3b94/000000?text=+) | ![#497edd](https://via.placeholder.com/20/497edd/000000?text=+) | ![#00d3eb](https://via.placeholder.com/20/00d3eb/000000?text=+) | ![#2ef625](https://via.placeholder.com/20/2ef625/000000?text=+) | ![#2ef625](https://via.placeholder.com/20/2ef625/000000?text=+) | -| Color | Label | -| :------------------------------------------------------: | ----------------------------------------- | +| Color | Label | +| :-------------------------------------------------------------: | ----------------------------------------- | | ![#b82b28](https://via.placeholder.com/20/b82b28/000000?text=+) | Required for basic functionality. | | ![#9f3b94](https://via.placeholder.com/20/9f3b94/000000?text=+) | Required for specific functions. | | ![#497edd](https://via.placeholder.com/20/497edd/000000?text=+) | 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 */