]> Kevux Git Server - fll/commitdiff
Feature: Add f_abstruse project.
authorKevin Day <thekevinday@gmail.com>
Wed, 4 Oct 2023 02:00:19 +0000 (21:00 -0500)
committerKevin Day <thekevinday@gmail.com>
Wed, 4 Oct 2023 02:00:19 +0000 (21:00 -0500)
This is the initial design and may be subject to significant change as I begin to use it more.

The idea here is to provide a type that can act as a catch all for any sort of header of any specific type.
I use standard types and provide void pointer types for everything else.

I have some concerns about supporting void pointer types due to the special case of how to handle this allocation actions.
I have decided to withhold the "append" and similar standard functions for now until I get a better grasp on how this should be used.

A union is used to use the same memory space at the cost of the largest size.

A dynamic string is likely the most common case.

The resize and similar functions provide warnings that the caller needs to be careful about allocation and de-allocation.
This poses extra security concerns for when callers of these functions do not properly or safely handle the data.

I intend to use this in the FSS Simple Packet processing code, such as writing (building) the Simple Packet string.

47 files changed:
build/disable/about.txt
build/level_0/settings
build/monolithic/settings
build/scripts/bootstrap-example.sh
build/stand_alone/byte_dump.config.h
build/stand_alone/fake.config.h
build/stand_alone/fake.settings
build/stand_alone/firewall.config.h
build/stand_alone/utf8.config.h
level_0/f_abstruse/c/abstruse.c [new file with mode: 0644]
level_0/f_abstruse/c/abstruse.h [new file with mode: 0644]
level_0/f_abstruse/c/abstruse/abstruse.c [new file with mode: 0644]
level_0/f_abstruse/c/abstruse/abstruse.h [new file with mode: 0644]
level_0/f_abstruse/c/abstruse/enum.h [new file with mode: 0644]
level_0/f_abstruse/c/abstruse/map.c [new file with mode: 0644]
level_0/f_abstruse/c/abstruse/map.h [new file with mode: 0644]
level_0/f_abstruse/c/abstruse/private-abstruse.c [new file with mode: 0644]
level_0/f_abstruse/c/abstruse/private-abstruse.h [new file with mode: 0644]
level_0/f_abstruse/c/abstruse/type.h [new file with mode: 0644]
level_0/f_abstruse/data/build/defines [new file with mode: 0644]
level_0/f_abstruse/data/build/dependencies [new file with mode: 0644]
level_0/f_abstruse/data/build/dependencies-tests [new file with mode: 0644]
level_0/f_abstruse/data/build/fakefile [new file with mode: 0644]
level_0/f_abstruse/data/build/settings [new file with mode: 0644]
level_0/f_abstruse/data/build/settings-mocks [new file with mode: 0644]
level_0/f_abstruse/data/build/settings-tests [new file with mode: 0644]
level_0/f_abstruse/data/build/testfile [new file with mode: 0644]
level_0/f_abstruse/tests/unit/c/mock-abstruse.c [new file with mode: 0644]
level_0/f_abstruse/tests/unit/c/mock-abstruse.h [new file with mode: 0644]
level_0/f_abstruse/tests/unit/c/test-abstruse-maps_delete_callback.c [new file with mode: 0644]
level_0/f_abstruse/tests/unit/c/test-abstruse-maps_delete_callback.h [new file with mode: 0644]
level_0/f_abstruse/tests/unit/c/test-abstruse-maps_destroy_callback.c [new file with mode: 0644]
level_0/f_abstruse/tests/unit/c/test-abstruse-maps_destroy_callback.h [new file with mode: 0644]
level_0/f_abstruse/tests/unit/c/test-abstruse-mapss_delete_callback.c [new file with mode: 0644]
level_0/f_abstruse/tests/unit/c/test-abstruse-mapss_delete_callback.h [new file with mode: 0644]
level_0/f_abstruse/tests/unit/c/test-abstruse-mapss_destroy_callback.c [new file with mode: 0644]
level_0/f_abstruse/tests/unit/c/test-abstruse-mapss_destroy_callback.h [new file with mode: 0644]
level_0/f_abstruse/tests/unit/c/test-abstruse-s_delete_callback.c [new file with mode: 0644]
level_0/f_abstruse/tests/unit/c/test-abstruse-s_delete_callback.h [new file with mode: 0644]
level_0/f_abstruse/tests/unit/c/test-abstruse-s_destroy_callback.c [new file with mode: 0644]
level_0/f_abstruse/tests/unit/c/test-abstruse-s_destroy_callback.h [new file with mode: 0644]
level_0/f_abstruse/tests/unit/c/test-abstruse-ss_delete_callback.c [new file with mode: 0644]
level_0/f_abstruse/tests/unit/c/test-abstruse-ss_delete_callback.h [new file with mode: 0644]
level_0/f_abstruse/tests/unit/c/test-abstruse-ss_destroy_callback.c [new file with mode: 0644]
level_0/f_abstruse/tests/unit/c/test-abstruse-ss_destroy_callback.h [new file with mode: 0644]
level_0/f_abstruse/tests/unit/c/test-abstruse.c [new file with mode: 0644]
level_0/f_abstruse/tests/unit/c/test-abstruse.h [new file with mode: 0644]

index da3828dee2fd279b06f34402603de0f2497695ee..47ebd9b0bad40c5795b82072a5257bbe8c2a032b 100644 (file)
@@ -33,11 +33,11 @@ Consider the following example using the fake dependencies for the stand alone b
 # echo $(cat level_3/fake/data/build/dependencies)
 
 Which prints:
-  # fss-0000 f_type f_status f_memory f_type_array f_string f_utf f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_parse f_path f_pipe f_print f_rip f_signal f_thread f_time fl_control_group fl_conversion fl_directory fl_environment fl_execute fl_fss fl_iki fl_path fl_print fll_error fll_execute fll_file fll_fss fll_print fll_program
+  # fss-0000 f_type f_status f_memory f_type_array f_string f_utf f_abstruse f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_parse f_path f_pipe f_print f_rip f_signal f_thread f_time fl_control_group fl_conversion fl_directory fl_environment fl_execute fl_fss fl_iki fl_path fl_print fll_error fll_execute fll_file fll_fss fll_print fll_program
 
 From this list, build the level_0:
 
-# for i in f_type f_status f_memory f_type_array f_string f_utf f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_parse f_path f_pipe f_print f_rip f_signal f_thread f_time ; do if [[ -f build/disable/level_0/$i.h ]] ; then echo >> build/stand_alone/fake.config.h && cat build/disable/level_0/$i.h >> build/stand_alone/fake.config.h ; fi ; done
+# for i in f_type f_status f_memory f_type_array f_string f_utf f_abstruse f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_parse f_path f_pipe f_print f_rip f_signal f_thread f_time ; do if [[ -f build/disable/level_0/$i.h ]] ; then echo >> build/stand_alone/fake.config.h && cat build/disable/level_0/$i.h >> build/stand_alone/fake.config.h ; fi ; done
 
 From the list, build the level_1:
 
index 6208ea8fe833017e3de3543f4be181e1df254876..745f3c530174ec101b3d9643ac45742248599700 100644 (file)
@@ -33,6 +33,7 @@ build_language c
 
 build_libraries -lc -lcap
 
+build_sources_library abstruse.c abstruse/abstruse.c abstruse/map.c abstruse/private-abstruse.c
 build_sources_library account.c private-account.c account/accounts.c
 build_sources_library capability.c
 build_sources_library color.c private-color.c color/common.c
@@ -83,6 +84,7 @@ build_sources_library utf/private-dynamics.c utf/private-maps.c utf/private-map_
 
 build_sources_library-thread thread.c thread/attribute.c thread/barrier.c thread/barrier_attribute.c thread/condition.c thread/condition_attribute.c thread/id.c thread/key.c thread/lock.c thread/lock_attribute.c thread/mutex.c thread/mutex_attribute.c thread/once.c thread/semaphore.c thread/set.c thread/spin.c
 
+build_sources_headers abstruse.h abstruse/abstruse.h abstruse/enum.h abstruse/map.h abstruse/type.h
 build_sources_headers account.h account/accounts.h account/common.h
 build_sources_headers capability.h capability/common.h
 build_sources_headers color.h color/common.h
index 7eaf6badbfc59e564e725c0a5b242d537496ef85..bd861a140082c0505dad5afec80de619b3e05c10 100644 (file)
@@ -33,6 +33,7 @@ build_language c
 
 build_libraries -lc -lcap
 
+build_sources_library level_0/abstruse.c level_0/abstruse/abstruse.c level_0/abstruse/map.c level_0/abstruse/private-abstruse.c
 build_sources_library level_0/account.c level_0/private-account.c level_0/account/accounts.c
 build_sources_library level_0/capability.c
 build_sources_library level_0/color.c level_0/private-color.c level_0/color/common.c
@@ -104,6 +105,7 @@ build_sources_library level_2/program.c level_2/program/common.c level_2/program
 
 build_sources_library-thread level_0/thread.c level_0/thread/attribute.c level_0/thread/barrier.c level_0/thread/barrier_attribute.c level_0/thread/condition.c level_0/thread/condition_attribute.c level_0/thread/id.c level_0/thread/key.c level_0/thread/lock.c level_0/thread/lock_attribute.c level_0/thread/mutex.c level_0/thread/mutex_attribute.c level_0/thread/once.c level_0/thread/semaphore.c level_0/thread/set.c level_0/thread/spin.c
 
+build_sources_headers level_0/abstruse.h level_0/abstruse/abstruse.h level_0/abstruse/enum.h level_0/abstruse/map.h level_0/abstruse/type.h
 build_sources_headers level_0/account.h level_0/account/accounts.h level_0/account/common.h
 build_sources_headers level_0/capability.h level_0/capability/common.h
 build_sources_headers level_0/color.h level_0/color/common.h
index d2b36e09f636a1d0d3a8a804443e5613381b175f..07e1a572c8890f45bae30cb5e53c49ce841f1bf9 100644 (file)
@@ -130,7 +130,7 @@ if [[ ${1} == "individual" ]] ; then
   ${shell_command} build/scripts/package.sh ${verbose} ${color} rebuild -i
 
   if [[ ${?} -eq 0 ]] ; then
-    for i in f_type f_status f_memory f_type_array f_string f_utf f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_network f_parse f_path f_pipe f_print f_rip f_status_string f_serialize f_signal f_socket f_thread f_time fl_control_group fl_conversion fl_directory fl_environment fl_execute fl_fss fl_iki fl_path fl_print fl_status_string fl_utf_file fll_control_group fll_error fll_execute fll_file fll_fss fll_fss_status_string fll_iki fll_print fll_program ; do
+    for i in f_type f_status f_memory f_type_array f_string f_utf f_abstruse f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_network f_parse f_path f_pipe f_print f_rip f_status_string f_serialize f_signal f_socket f_thread f_time fl_control_group fl_conversion fl_directory fl_environment fl_execute fl_fss fl_iki fl_path fl_print fl_status_string fl_utf_file fll_control_group fll_error fll_execute fll_file fll_fss fll_fss_status_string fll_iki fll_print fll_program ; do
       echo && echo "Processing ${i}." &&
 
       cd package/individual/${i}-${version}/ &&
index 5c97d92f85f26f15dca1186ecd500957b1fc5778..979334d598074130634b75a1a8ea429b1984c5f4 100644 (file)
@@ -8,7 +8,7 @@
 //
 // Example:
 //   echo > /tmp/all.txt
-//   for i in f_type f_status f_memory f_type_array f_string f_utf f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_network f_parse f_path f_pipe f_print f_rip f_signal f_socket f_thread f_time ; do grep -horP '\b_di_f_\w*\b' level_0/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_0/$i/c >> /tmp/all.txt ; done
+//   for i in f_type f_status f_memory f_type_array f_string f_utf f_abstruse f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_network f_parse f_path f_pipe f_print f_rip f_signal f_socket f_thread f_time ; do grep -horP '\b_di_f_\w*\b' level_0/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_0/$i/c >> /tmp/all.txt ; done
 //   for i in fl_control_group fl_conversion fl_directory fl_environment fl_execute fl_fss fl_iki fl_path fl_print ; do grep -horP '\b_di_fl_\w*\b' level_1/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_1/$i/c >> /tmp/all.txt ; done
 //   for i in fll_error fll_execute fll_file fll_fss fll_print fll_program ; do grep -horP '\b_di_fll_\w*\b' level_2/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_2/$i/c >> /tmp/all.txt ; done
 //   sort /tmp/all.txt | uniq | sed -e 's|^_|#define &|g' > /tmp/sorted.txt
index fe96292ff32820bc7e1a865cf429dd77c1007200..848e7c205851b730440b6698f5f438a57dbe756e 100644 (file)
@@ -8,7 +8,7 @@
 //
 // Example:
 //   echo > /tmp/all.txt
-//   for i in f_type f_status f_memory f_type_array f_string f_utf f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_network f_parse f_path f_pipe f_print f_rip f_signal f_socket f_thread f_time ; do grep -horP '\b_di_f_\w*\b' level_0/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_0/$i/c >> /tmp/all.txt ; done
+//   for i in f_type f_status f_memory f_type_array f_string f_utf f_abstruse f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_network f_parse f_path f_pipe f_print f_rip f_signal f_socket f_thread f_time ; do grep -horP '\b_di_f_\w*\b' level_0/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_0/$i/c >> /tmp/all.txt ; done
 //   for i in fl_control_group fl_conversion fl_directory fl_environment fl_execute fl_fss fl_iki fl_path fl_print ; do grep -horP '\b_di_fl_\w*\b' level_1/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_1/$i/c >> /tmp/all.txt ; done
 //   for i in fll_error fll_execute fll_file fll_fss fll_print fll_program ; do grep -horP '\b_di_fll_\w*\b' level_2/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_2/$i/c >> /tmp/all.txt ; done
 //   sort /tmp/all.txt | uniq | sed -e 's|^_|#define &|g' > /tmp/sorted.txt
index 09a0f9e39560b889ab2d3d02ec9dbaf736cdd882..40876f0b5b7005c6c29bdc29069aeb544c7524e1 100644 (file)
@@ -31,6 +31,7 @@ build_language c
 
 build_libraries -lc -lcap
 
+build_sources_program fll/level_0/abstruse.c fll/level_0/abstruse/abstruse.c fll/level_0/abstruse/map.c fll/level_0/abstruse/private-abstruse.c
 build_sources_program fll/level_0/account.c fll/level_0/private-account.c fll/level_0/account/accounts.c
 build_sources_program fll/level_0/capability.c
 build_sources_program fll/level_0/color.c fll/level_0/private-color.c fll/level_0/color/common.c
index 5c97d92f85f26f15dca1186ecd500957b1fc5778..979334d598074130634b75a1a8ea429b1984c5f4 100644 (file)
@@ -8,7 +8,7 @@
 //
 // Example:
 //   echo > /tmp/all.txt
-//   for i in f_type f_status f_memory f_type_array f_string f_utf f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_network f_parse f_path f_pipe f_print f_rip f_signal f_socket f_thread f_time ; do grep -horP '\b_di_f_\w*\b' level_0/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_0/$i/c >> /tmp/all.txt ; done
+//   for i in f_type f_status f_memory f_type_array f_string f_utf f_abstruse f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_network f_parse f_path f_pipe f_print f_rip f_signal f_socket f_thread f_time ; do grep -horP '\b_di_f_\w*\b' level_0/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_0/$i/c >> /tmp/all.txt ; done
 //   for i in fl_control_group fl_conversion fl_directory fl_environment fl_execute fl_fss fl_iki fl_path fl_print ; do grep -horP '\b_di_fl_\w*\b' level_1/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_1/$i/c >> /tmp/all.txt ; done
 //   for i in fll_error fll_execute fll_file fll_fss fll_print fll_program ; do grep -horP '\b_di_fll_\w*\b' level_2/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_2/$i/c >> /tmp/all.txt ; done
 //   sort /tmp/all.txt | uniq | sed -e 's|^_|#define &|g' > /tmp/sorted.txt
index 5c97d92f85f26f15dca1186ecd500957b1fc5778..979334d598074130634b75a1a8ea429b1984c5f4 100644 (file)
@@ -8,7 +8,7 @@
 //
 // Example:
 //   echo > /tmp/all.txt
-//   for i in f_type f_status f_memory f_type_array f_string f_utf f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_network f_parse f_path f_pipe f_print f_rip f_signal f_socket f_thread f_time ; do grep -horP '\b_di_f_\w*\b' level_0/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_0/$i/c >> /tmp/all.txt ; done
+//   for i in f_type f_status f_memory f_type_array f_string f_utf f_abstruse f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_network f_parse f_path f_pipe f_print f_rip f_signal f_socket f_thread f_time ; do grep -horP '\b_di_f_\w*\b' level_0/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_0/$i/c >> /tmp/all.txt ; done
 //   for i in fl_control_group fl_conversion fl_directory fl_environment fl_execute fl_fss fl_iki fl_path fl_print ; do grep -horP '\b_di_fl_\w*\b' level_1/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_1/$i/c >> /tmp/all.txt ; done
 //   for i in fll_error fll_execute fll_file fll_fss fll_print fll_program ; do grep -horP '\b_di_fll_\w*\b' level_2/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_2/$i/c >> /tmp/all.txt ; done
 //   sort /tmp/all.txt | uniq | sed -e 's|^_|#define &|g' > /tmp/sorted.txt
diff --git a/level_0/f_abstruse/c/abstruse.c b/level_0/f_abstruse/c/abstruse.c
new file mode 100644 (file)
index 0000000..6277590
--- /dev/null
@@ -0,0 +1,9 @@
+#include "abstruse.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_abstruse/c/abstruse.h b/level_0/f_abstruse/c/abstruse.h
new file mode 100644 (file)
index 0000000..b7b274f
--- /dev/null
@@ -0,0 +1,50 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Abstruse
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Provides abstruse type definitions.
+ *
+ * An abstruse type is intended to act as a variable that can be passed and then later cast to the appropriate type.
+ * This produces behavior similar to an object-oriented design in a non-object-oriented language like C.
+ *
+ * This is not intended to handle all possible types but instead handle a set of common and core FLL types.
+ */
+#ifndef _F_abstruse_h
+#define _F_abstruse_h
+
+// Include pre-requirements.
+#ifndef _GNU_SOURCE
+  #define _GNU_SOURCE
+#endif // _GNU_SOURCE
+
+// Libc includes.
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+// FLL-0 includes.
+#include <fll/level_0/type.h>
+#include <fll/level_0/status.h>
+#include <fll/level_0/memory.h>
+#include <fll/level_0/type_array.h>
+#include <fll/level_0/string.h>
+
+// FLL-0 type includes.
+#include <fll/level_0/abstruse/enum.h>
+#include <fll/level_0/abstruse/type.h>
+#include <fll/level_0/abstruse/abstruse.h>
+#include <fll/level_0/abstruse/map.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _F_abstruse_h
diff --git a/level_0/f_abstruse/c/abstruse/abstruse.c b/level_0/f_abstruse/c/abstruse/abstruse.c
new file mode 100644 (file)
index 0000000..0587655
--- /dev/null
@@ -0,0 +1,102 @@
+#include "../abstruse.h"
+#include "private-abstruse.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_f_abstruses_delete_callback_
+  f_status_t f_abstruses_delete_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const void_array) {
+
+    {
+      f_abstruse_t * const array = (f_abstruse_t *) void_array;
+      f_status_t status = F_okay;
+
+      for (f_number_unsigned_t i = start; i < stop; ++i) {
+
+        status = private_f_abstruses_delete_switch(&array[i]);
+        if (F_status_is_error(status)) return status;
+      } // for
+    }
+
+    return F_okay;
+  }
+#endif // _di_f_abstruses_delete_callback_
+
+#ifndef _di_f_abstruses_destroy_callback_
+  f_status_t f_abstruses_destroy_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const void_array) {
+
+    {
+      f_abstruse_t * const array = (f_abstruse_t *) void_array;
+      f_status_t status = F_okay;
+
+      for (f_number_unsigned_t i = start; i < stop; ++i) {
+
+        status = private_f_abstruses_destroy_switch(&array[i]);
+        if (F_status_is_error(status)) return status;
+      } // for
+    }
+
+    return F_okay;
+  }
+#endif // _di_f_abstruses_destroy_callback_
+
+#ifndef _di_f_abstrusess_delete_callback_
+  f_status_t f_abstrusess_delete_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const void_array) {
+
+    {
+      f_abstruses_t * const array = (f_abstruses_t *) void_array;
+      f_status_t status = F_okay;
+      f_number_unsigned_t i = start;
+      f_number_unsigned_t j = 0;
+
+      for (; i < stop; ++i) {
+
+        if (array[i].size) {
+          for (j = 0; j < array[i].size; ++j) {
+
+            status = private_f_abstruses_delete_switch(&array[i].array[j]);
+            if (F_status_is_error(status)) return status;
+          } // for
+
+          status = f_memory_array_resize(0, sizeof(f_abstruse_t), (void **) &array[i].array, &array[i].used, &array[i].size);
+          if (F_status_is_error(status)) return status;
+        }
+      } // for
+    }
+
+    return F_okay;
+  }
+#endif // _di_f_abstrusess_delete_callback_
+
+#ifndef _di_f_abstrusess_destroy_callback_
+  f_status_t f_abstrusess_destroy_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const void_array) {
+
+    {
+      f_abstruses_t * const array = (f_abstruses_t *) void_array;
+      f_status_t status = F_okay;
+      f_number_unsigned_t i = start;
+      f_number_unsigned_t j = 0;
+
+      for (; i < stop; ++i) {
+
+        if (array[i].size) {
+          for (j = 0; j < array[i].size; ++j) {
+
+            status = private_f_abstruses_destroy_switch(&array[i].array[j]);
+            if (F_status_is_error(status)) return status;
+          } // for
+
+          status = f_memory_array_adjust(0, sizeof(f_abstruse_t), (void **) &array[i].array, &array[i].used, &array[i].size);
+          if (F_status_is_error(status)) return status;
+        }
+      } // for
+    }
+
+    return F_okay;
+  }
+#endif // _di_f_abstrusess_destroy_callback_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_abstruse/c/abstruse/abstruse.h b/level_0/f_abstruse/c/abstruse/abstruse.h
new file mode 100644 (file)
index 0000000..4dcfd78
--- /dev/null
@@ -0,0 +1,309 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Abstuse
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Defines abstruse data.
+ *
+ * This is auto-included by abstruse.h and should not need to be explicitly included.
+ */
+#ifndef _F_type_abstruse_abstruse_h
+#define _F_type_abstruse_abstruse_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * An abstruse a structure that represents different possible types.
+ *
+ * The type variable is used to designate the type within the f_abstruse_type_t union in use.
+ *
+ * De-allocation must be performed when swapping between types when the old type contains dynamically allocated data.
+ *
+ * It may be a good idea to use statically allocated data or dynamically allocated data managed elsewhere with this to avoid potential design complications with de-allocation.
+ *
+ * properties:
+ *   - type: The type in which the "is" property is, represented by f_abstruse_type_e.
+ *   - is:   The value, where "is" is chosen as a variable name so that when type is f_abstruse_type_unsigned_e, then accessing this would be done via "is.a_unsigned".
+ */
+#ifndef _di_f_abstruse_t_
+  typedef struct {
+    uint8_t type;
+
+    f_abstruse_type_t is;
+  } f_abstruse_t;
+
+  #define f_abstruse_t_initialize { 0, f_abstruse_type_t_initialize }
+
+  #define macro_f_abstruse_t_initialize_1(type, is) { type, is }
+  #define macro_f_abstruse_t_initialize_2(type) { type, f_abstruse_type_t_initialize }
+
+  #define macro_f_abstruse_t_clear(abstruse) \
+    abstruse.type = 0; \
+    macro_f_abstruse_type_t_clear(abstruse.is);
+#endif // _di_f_abstruse_t_
+
+/**
+ * An array of f_abstruse_t.
+ *
+ * Properties:
+ *   - array: The array of f_abstruse_t.
+ *   - size:  Total amount of allocated space.
+ *   - used:  Total number of allocated spaces used.
+ */
+#ifndef _di_f_abstruses_t_
+  typedef struct {
+    f_abstruse_t *array;
+
+    f_number_unsigned_t size;
+    f_number_unsigned_t used;
+  } f_abstruses_t;
+
+  #define f_abstruses_t_initialize { 0, 0, 0 }
+
+  #define macro_f_abstruses_t_initialize_1(array, size, used) { array, size, used }
+  #define macro_f_abstruses_t_initialize_2(array, length) { array, length, length }
+#endif // _di_f_abstruses_t_
+
+/**
+ * This holds an array of f_abstruses_t.
+ *
+ * Properties:
+ *   - array: The array of f_abstruse_t arrays.
+ *   - size:  Total amount of allocated space.
+ *   - used:  Total number of allocated spaces used.
+ */
+#ifndef _di_f_abstrusess_t_
+  typedef struct {
+    f_abstruses_t *array;
+
+    f_number_unsigned_t size;
+    f_number_unsigned_t used;
+  } f_abstrusess_t;
+
+  #define f_abstrusess_t_initialize { 0, 0, 0 }
+
+  #define macro_f_abstrusess_t_initialize_1(array, size, used) { array, size, used }
+  #define macro_f_abstrusess_t_initialize_2(array, length) { array, length, length }
+#endif // _di_f_abstrusess_t_
+
+/**
+ * A callback intended to be passed to f_memory_arrays_resize() for an f_abstruses_t structure.
+ *
+ * This callback only de-allocates the following:
+ *   - a_u8s
+ *   - a_u16s
+ *   - a_u32s
+ *   - a_u64s
+ *   - a_i8s
+ *   - a_i16s
+ *   - a_i32s
+ *   - a_i64s
+ *   - a_signeds
+ *   - a_unsigneds
+ *   - a_static (as an f_string_dynamic_t, if size > 0).
+ *   - a_statics (as an f_string_dynamics_t, if size > 0).
+ *   - a_map
+ *   - a_maps
+ *   - a_map_multi
+ *   - a_map_multis
+ *   - a_quantitys
+ *   - a_ranges
+ *   - a_triple
+ *   - a_triples
+ *
+ * For all other types, the caller must handle de-allocation to avoid memory leaks.
+ * Provide and use a custom callback if special handling of deallocation is needed.
+ *
+ * This is only called when shrinking the array and generally should perform deallocations.
+ *
+ * This does not do parameter checking.
+ *
+ * @param start
+ *   The inclusive start position in the array to start deleting.
+ * @param stop
+ *   The exclusive stop position in the array to stop deleting.
+ * @param array
+ *   The array structure to delete all values of.
+ *   Must not be NULL.
+ *
+ * @return
+ *   F_okay on success, including when nothing done due to no match against the type.
+ *
+ *   Errors (with error bit) from: f_memory_array_resize().
+ *   Errors (with error bit) from: f_memory_arrays_resize().
+ *
+ * @see f_memory_array_resize()
+ * @see f_memory_arrays_resize()
+ */
+#ifndef _di_f_abstruses_delete_callback_
+  extern f_status_t f_abstruses_delete_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const array);
+#endif // _di_f_abstruses_delete_callback_
+
+/**
+ * A callback intended to be passed to f_memory_arrays_adjust() for an f_abstruses_t structure.
+ *
+ * This callback only de-allocates the following:
+ *   - a_u8s
+ *   - a_u16s
+ *   - a_u32s
+ *   - a_u64s
+ *   - a_i8s
+ *   - a_i16s
+ *   - a_i32s
+ *   - a_i64s
+ *   - a_signeds
+ *   - a_unsigneds
+ *   - a_static (as an f_string_dynamic_t, if size > 0).
+ *   - a_statics (as an f_string_dynamics_t, if size > 0).
+ *   - a_map
+ *   - a_maps
+ *   - a_map_multi
+ *   - a_map_multis
+ *   - a_quantitys
+ *   - a_ranges
+ *   - a_triple
+ *   - a_triples
+ *
+ * For all other types, the caller must handle de-allocation to avoid memory leaks.
+ * Provide and use a custom callback if special handling of deallocation is needed.
+ *
+ * This is only called when shrinking the array and generally should perform deallocations.
+ *
+ * This does not do parameter checking.
+ *
+ * @param start
+ *   The inclusive start position in the array to start deleting.
+ * @param stop
+ *   The exclusive stop position in the array to stop deleting.
+ * @param array
+ *   The array structure to delete all values of.
+ *   Must not be NULL.
+ *
+ * @return
+ *   F_okay on success, including when nothing done due to no match against the type.
+ *
+ *   Errors (with error bit) from: f_memory_array_adjust().
+ *   Errors (with error bit) from: f_memory_arrays_adjust().
+ *
+ * @see f_memory_array_adjust()
+ * @see f_memory_arrays_adjust()
+ */
+#ifndef _di_f_abstruses_destroy_callback_
+  extern f_status_t f_abstruses_destroy_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const array);
+#endif // _di_f_abstruses_destroy_callback_
+
+/**
+ * A callback intended to be passed to f_memory_arrays_resize() for an f_abstrusess_t structure.
+ *
+ * This callback only de-allocates the following:
+ *   - a_u8s
+ *   - a_u16s
+ *   - a_u32s
+ *   - a_u64s
+ *   - a_i8s
+ *   - a_i16s
+ *   - a_i32s
+ *   - a_i64s
+ *   - a_signeds
+ *   - a_unsigneds
+ *   - a_static (as an f_string_dynamic_t, if size > 0).
+ *   - a_statics (as an f_string_dynamics_t, if size > 0).
+ *   - a_map
+ *   - a_maps
+ *   - a_map_multi
+ *   - a_map_multis
+ *   - a_quantitys
+ *   - a_ranges
+ *   - a_triple
+ *   - a_triples
+ *
+ * For all other types, the caller must handle de-allocation to avoid memory leaks.
+ * Provide and use a custom callback if special handling of deallocation is needed.
+ *
+ * This is only called when shrinking the array and generally should perform deallocations.
+ *
+ * This does not do parameter checking.
+ *
+ * @param start
+ *   The inclusive start position in the array to start deleting.
+ * @param stop
+ *   The exclusive stop position in the array to stop deleting.
+ * @param array
+ *   The array structure to delete all values of.
+ *   Must not be NULL.
+ *
+ * @return
+ *   F_okay on success.
+ *
+ *   Errors (with error bit) from: f_memory_array_resize().
+ *   Errors (with error bit) from: f_memory_arrays_resize().
+ *
+ * @see f_memory_array_resize()
+ * @see f_memory_arrays_resize()
+ */
+#ifndef _di_f_abstrusess_delete_callback_
+  extern f_status_t f_abstrusess_delete_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const array);
+#endif // _di_f_abstrusess_delete_callback_
+
+/**
+ * A callback intended to be passed to f_memory_arrays_adjust() for an f_abstrusess_t structure.
+ *
+ * This callback only de-allocates the following:
+ *   - a_u8s
+ *   - a_u16s
+ *   - a_u32s
+ *   - a_u64s
+ *   - a_i8s
+ *   - a_i16s
+ *   - a_i32s
+ *   - a_i64s
+ *   - a_signeds
+ *   - a_unsigneds
+ *   - a_static (as an f_string_dynamic_t, if size > 0).
+ *   - a_statics (as an f_string_dynamics_t, if size > 0).
+ *   - a_map
+ *   - a_maps
+ *   - a_map_multi
+ *   - a_map_multis
+ *   - a_quantitys
+ *   - a_ranges
+ *   - a_triple
+ *   - a_triples
+ *
+ * For all other types, the caller must handle de-allocation to avoid memory leaks.
+ * Provide and use a custom callback if special handling of deallocation is needed.
+ *
+ * This is only called when shrinking the array and generally should perform deallocations.
+ *
+ * This does not do parameter checking.
+ *
+ * @param start
+ *   The inclusive start position in the array to start deleting.
+ * @param stop
+ *   The exclusive stop position in the array to stop deleting.
+ * @param array
+ *   The array structure to delete all values of.
+ *   Must not be NULL.
+ *
+ * @return
+ *   F_okay on success.
+ *
+ *   Errors (with error bit) from: f_memory_array_adjust().
+ *   Errors (with error bit) from: f_memory_arrays_adjust().
+ *
+ * @see f_memory_array_adjust()
+ * @see f_memory_arrays_adjust()
+ */
+#ifndef _di_f_abstrusess_destroy_callback_
+  extern f_status_t f_abstrusess_destroy_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const array);
+#endif // _di_f_abstrusess_destroy_callback_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _F_type_abstruse_abstruse_h
diff --git a/level_0/f_abstruse/c/abstruse/enum.h b/level_0/f_abstruse/c/abstruse/enum.h
new file mode 100644 (file)
index 0000000..696d417
--- /dev/null
@@ -0,0 +1,117 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Type
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Defines abstruse type data.
+ *
+ * This is auto-included by abstruse.h and should not need to be explicitly included.
+ */
+#ifndef _F_type_abstruse_enum_h
+#define _F_type_abstruse_enum_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * An enumeration representing all standard abstruse union types.
+ *
+ * Generally, the types ending in "s" represent an array.
+ *
+ * f_abstruse_uint8:      Maps to uint8_t.
+ * f_abstruse_uint8s:     Maps to f_uint8s_t.
+ * f_abstruse_uint16:     Maps to uint16_t.
+ * f_abstruse_uint16s:    Maps to f_uint16s_t.
+ * f_abstruse_uint32:     Maps to uint32_t.
+ * f_abstruse_uint32s:    Maps to f_uint32s_t.
+ * f_abstruse_uint64:     Maps to uint64_t.
+ * f_abstruse_uint64s:    Maps to f_uint64s_t.
+ * f_abstruse_int8:       Maps to int8_t.
+ * f_abstruse_int8s:      Maps to f_int8_t.
+ * f_abstruse_int16:      Maps to int16_t.
+ * f_abstruse_int16s:     Maps to f_int16_t.
+ * f_abstruse_int32:      Maps to int32_t.
+ * f_abstruse_int32s:     Maps to f_int32s_t.
+ * f_abstruse_int64:      Maps to int64_t.
+ * f_abstruse_int64s:     Maps to f_int64_t.
+ * f_abstruse_signed:     Maps to f_number_singed_t.
+ * f_abstruse_signeds:    Maps to f_number_singeds_t.
+ * f_abstruse_unsigned:   Maps to f_number_unsinged_t.
+ * f_abstruse_unsigneds:  Maps to f_number_unsingeds_t.
+ * f_abstruse_char:       Maps to f_char_t.
+ * f_abstruse_string:     Maps to f_string_t (also: (f_char_t *)).
+ * f_abstruse_strings:    Maps to (f_string_t *).
+ * f_abstruse_dynamic:    Maps to f_string_dynamic_t (or f_string_static_t).
+ * f_abstruse_dynamics:   Maps to f_string_dynamics_t (or f_string_statics_t).
+ * f_abstruse_map:        Maps to f_string_map_t.
+ * f_abstruse_maps:       Maps to f_string_maps_t.
+ * f_abstruse_map_multi:  Maps to f_string_map_multi_t.
+ * f_abstruse_map_multis: Maps to f_string_map_multis_t.
+ * f_abstruse_quantity:   Maps to f_string_quantity_t.
+ * f_abstruse_quantitys:  Maps to f_string_quantitys_t.
+ * f_abstruse_range:      Maps to f_string_range_t.
+ * f_abstruse_ranges:     Maps to f_string_ranges_t.
+ * f_abstruse_triple:     Maps to f_string_triple_t.
+ * f_abstruse_triples:    Maps to f_string_triples_t.
+ * f_abstruse_void:       Maps to (void *).
+ * f_abstruse_voids:      Maps to (void **).
+ * f_abstruse_size:       Maps to size_t.
+ * f_abstruse_sizes:      Maps to (size_t *).
+ * f_abstruse_ssize:      Maps to ssize_t.
+ * f_abstruse_ssizes:     Maps to (ssize_t *).
+ */
+#ifndef _di_f_abstruse_e_
+  enum {
+    f_abstruse_none_e = 0,
+    f_abstruse_uint8_e,
+    f_abstruse_uint8s_e,
+    f_abstruse_uint16_e,
+    f_abstruse_uint16s_e,
+    f_abstruse_uint32_e,
+    f_abstruse_uint32s_e,
+    f_abstruse_uint64_e,
+    f_abstruse_uint64s_e,
+    f_abstruse_int8_e,
+    f_abstruse_int8s_e,
+    f_abstruse_int16_e,
+    f_abstruse_int16s_e,
+    f_abstruse_int32_e,
+    f_abstruse_int32s_e,
+    f_abstruse_int64_e,
+    f_abstruse_int64s_e,
+    f_abstruse_signed_e,
+    f_abstruse_signeds_e,
+    f_abstruse_unsigned_e,
+    f_abstruse_unsigneds_e,
+    f_abstruse_char_e,
+    f_abstruse_string_e,
+    f_abstruse_strings_e,
+    f_abstruse_dynamic_e,
+    f_abstruse_dynamics_e,
+    f_abstruse_map_e,
+    f_abstruse_maps_e,
+    f_abstruse_map_multi_e,
+    f_abstruse_map_multis_e,
+    f_abstruse_quantity_e,
+    f_abstruse_quantitys_e,
+    f_abstruse_range_e,
+    f_abstruse_ranges_e,
+    f_abstruse_triple_e,
+    f_abstruse_triples_e,
+    f_abstruse_void_e,
+    f_abstruse_voids_e,
+    f_abstruse_size_e,
+    f_abstruse_sizes_e,
+    f_abstruse_ssize_e,
+    f_abstruse_ssizes_e,
+  };
+#endif // _di_f_abstruse_e_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _F_type_abstruse_enum_h
diff --git a/level_0/f_abstruse/c/abstruse/map.c b/level_0/f_abstruse/c/abstruse/map.c
new file mode 100644 (file)
index 0000000..4b5e1a3
--- /dev/null
@@ -0,0 +1,114 @@
+#include "../abstruse.h"
+#include "private-abstruse.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_f_abstruse_maps_delete_callback_
+  f_status_t f_abstruse_maps_delete_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const void_array) {
+
+    {
+      f_abstruse_map_t * const array = (f_abstruse_map_t *) void_array;
+      f_status_t status = F_okay;
+
+      for (f_number_unsigned_t i = start; i < stop; ++i) {
+
+        status = f_memory_array_resize(0, sizeof(f_char_t), (void **) &array[i].key.string, &array[i].key.used, &array[i].key.size);
+        if (F_status_is_error(status)) return status;
+
+        status = private_f_abstruses_delete_switch(&array[i].value);
+        if (F_status_is_error(status)) return status;
+      } // for
+    }
+
+    return F_okay;
+  }
+#endif // _di_f_abstruse_maps_delete_callback_
+
+#ifndef _di_f_abstruse_maps_destroy_callback_
+  f_status_t f_abstruse_maps_destroy_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const void_array) {
+
+    {
+      f_abstruse_map_t * const array = (f_abstruse_map_t *) void_array;
+      f_status_t status = F_okay;
+
+      for (f_number_unsigned_t i = start; i < stop; ++i) {
+
+        status = f_memory_array_adjust(0, sizeof(f_char_t), (void **) &array[i].key.string, &array[i].key.used, &array[i].key.size);
+        if (F_status_is_error(status)) return status;
+
+        status = private_f_abstruses_destroy_switch(&array[i].value);
+        if (F_status_is_error(status)) return status;
+      } // for
+    }
+
+    return F_okay;
+  }
+#endif // _di_f_abstruse_maps_destroy_callback_
+
+#ifndef _di_f_abstruse_mapss_delete_callback_
+  f_status_t f_abstruse_mapss_delete_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const void_array) {
+
+    {
+      f_abstruse_maps_t * const array = (f_abstruse_maps_t *) void_array;
+      f_status_t status = F_okay;
+      f_number_unsigned_t i = start;
+      f_number_unsigned_t j = 0;
+
+      for (; i < stop; ++i) {
+
+        if (array[i].size) {
+          for (j = 0; j < array[i].size; ++j) {
+
+            status = f_memory_array_resize(0, sizeof(f_char_t), (void **) &array[i].array[j].key.string, &array[i].array[j].key.used, &array[i].array[j].key.size);
+            if (F_status_is_error(status)) return status;
+
+            status = private_f_abstruses_delete_switch(&array[i].array[j].value);
+            if (F_status_is_error(status)) return status;
+          } // for
+
+          status = f_memory_array_resize(0, sizeof(f_abstruse_map_t), (void **) &array[i].array, &array[i].used, &array[i].size);
+          if (F_status_is_error(status)) return status;
+        }
+      } // for
+    }
+
+    return F_okay;
+  }
+#endif // _di_f_abstruse_mapss_delete_callback_
+
+#ifndef _di_f_abstruse_mapss_destroy_callback_
+  f_status_t f_abstruse_mapss_destroy_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const void_array) {
+
+    {
+      f_abstruse_maps_t * const array = (f_abstruse_maps_t *) void_array;
+      f_status_t status = F_okay;
+      f_number_unsigned_t i = start;
+      f_number_unsigned_t j = 0;
+
+      for (; i < stop; ++i) {
+
+        if (array[i].size) {
+          for (j = 0; j < array[i].size; ++j) {
+
+            status = f_memory_array_adjust(0, sizeof(f_char_t), (void **) &array[i].array[j].key.string, &array[i].array[j].key.used, &array[i].array[j].key.size);
+            if (F_status_is_error(status)) return status;
+
+            status = private_f_abstruses_destroy_switch(&array[i].array[j].value);
+            if (F_status_is_error(status)) return status;
+          } // for
+
+          status = f_memory_array_adjust(0, sizeof(f_abstruse_map_t), (void **) &array[i].array, &array[i].used, &array[i].size);
+          if (F_status_is_error(status)) return status;
+        }
+      } // for
+    }
+
+    return F_okay;
+  }
+#endif // _di_f_abstruse_mapss_destroy_callback_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_abstruse/c/abstruse/map.h b/level_0/f_abstruse/c/abstruse/map.h
new file mode 100644 (file)
index 0000000..dce5e8d
--- /dev/null
@@ -0,0 +1,201 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Abstuse
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Defines abstruse map data.
+ *
+ * This is auto-included by abstruse.h and should not need to be explicitly included.
+ */
+#ifndef _F_type_abstruse_map_h
+#define _F_type_abstruse_map_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * A map of an abstruse as the value and a string as the key.
+ *
+ * properties:
+ *   - key:   The string mapping the abstruse.
+ *   - value: The abstruse being mapped by the key.
+ */
+#ifndef _di_f_abstruse_map_t_
+  typedef struct {
+    f_string_dynamic_t key;
+    f_abstruse_t value;
+  } f_abstruse_map_t;
+
+  #define f_abstruse_map_t_initialize { f_string_dynamic_t_initialize, f_abstruse_t_initialize }
+
+  #define macro_f_abstruse_map_t_initialize_1(key, value) { key, value }
+
+  #define macro_f_abstruse_map_t_clear(map) \
+    macro_f_string_dynamic_t_clear(map.key); \
+    macro_f_abstruse_t_clear(map.value);
+#endif // _di_f_abstruse_map_t_
+
+/**
+ * An array of f_abstruse_map_t.
+ *
+ * Properties:
+ *   - array: The array of f_abstruse_map_t.
+ *   - size:  Total amount of allocated space.
+ *   - used:  Total number of allocated spaces used.
+ */
+#ifndef _di_f_abstruse_maps_t_
+  typedef struct {
+    f_abstruse_map_t *array;
+
+    f_number_unsigned_t size;
+    f_number_unsigned_t used;
+  } f_abstruse_maps_t;
+
+  #define f_abstruses_t_initialize { 0, 0, 0 }
+
+  #define macro_f_abstruse_maps_t_initialize_1(array, size, used) { array, size, used }
+  #define macro_f_abstruse_maps_t_initialize_2(array, length) { array, length, length }
+#endif // _di_f_abstruse_maps_t_
+
+/**
+ * This holds an array of f_abstruse_map_maps_t.
+ *
+ * Properties:
+ *   - array: The array of f_abstruse_map_t arrays.
+ *   - size:  Total amount of allocated space.
+ *   - used:  Total number of allocated spaces used.
+ */
+#ifndef _di_f_abstruse_mapss_t_
+  typedef struct {
+    f_abstruse_maps_t *array;
+
+    f_number_unsigned_t size;
+    f_number_unsigned_t used;
+  } f_abstruse_mapss_t;
+
+  #define f_abstruse_mapss_t_initialize { 0, 0, 0 }
+
+  #define macro_f_abstruse_mapss_t_initialize_1(array, size, used) { array, size, used }
+  #define macro_f_abstruse_mapss_t_initialize_2(array, length) { array, length, length }
+#endif // _di_f_abstruse_mapss_t_
+
+/**
+ * A callback intended to be passed to f_memory_arrays_resize() for an f_abstruse_maps_t structure.
+ *
+ * This is only called when shrinking the array and generally should perform deallocations.
+ *
+ * This does not do parameter checking.
+ *
+ * @param start
+ *   The inclusive start position in the array to start deleting.
+ * @param stop
+ *   The exclusive stop position in the array to stop deleting.
+ * @param array
+ *   The array structure to delete all values of.
+ *   Must not be NULL.
+ *
+ * @return
+ *   F_okay on success, including when nothing done due to no match against the type.
+ *
+ *   Errors (with error bit) from: f_memory_array_resize().
+ *   Errors (with error bit) from: f_memory_arrays_resize().
+ *
+ * @see f_memory_array_resize()
+ * @see f_memory_arrays_resize()
+ */
+#ifndef _di_f_abstruse_maps_delete_callback_
+  extern f_status_t f_abstruse_maps_delete_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const array);
+#endif // _di_f_abstruse_maps_delete_callback_
+
+/**
+ * A callback intended to be passed to f_memory_arrays_adjust() for an f_abstruse_maps_t structure.
+ *
+ * This is only called when shrinking the array and generally should perform deallocations.
+ *
+ * This does not do parameter checking.
+ *
+ * @param start
+ *   The inclusive start position in the array to start deleting.
+ * @param stop
+ *   The exclusive stop position in the array to stop deleting.
+ * @param array
+ *   The array structure to delete all values of.
+ *   Must not be NULL.
+ *
+ * @return
+ *   F_okay on success, including when nothing done due to no match against the type.
+ *
+ *   Errors (with error bit) from: f_memory_array_adjust().
+ *   Errors (with error bit) from: f_memory_arrays_adjust().
+ *
+ * @see f_memory_array_adjust()
+ * @see f_memory_arrays_adjust()
+ */
+#ifndef _di_f_abstruse_maps_destroy_callback_
+  extern f_status_t f_abstruse_maps_destroy_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const array);
+#endif // _di_f_abstruse_maps_destroy_callback_
+
+/**
+ * A callback intended to be passed to f_memory_arrays_resize() for an f_abstruse_mapss_t structure.
+ *
+ * This is only called when shrinking the array and generally should perform deallocations.
+ *
+ * This does not do parameter checking.
+ *
+ * @param start
+ *   The inclusive start position in the array to start deleting.
+ * @param stop
+ *   The exclusive stop position in the array to stop deleting.
+ * @param array
+ *   The array structure to delete all values of.
+ *   Must not be NULL.
+ *
+ * @return
+ *   F_okay on success.
+ *
+ *   Errors (with error bit) from: f_memory_array_resize().
+ *   Errors (with error bit) from: f_memory_arrays_resize().
+ *
+ * @see f_memory_array_resize()
+ * @see f_memory_arrays_resize()
+ */
+#ifndef _di_f_abstruse_mapss_delete_callback_
+  extern f_status_t f_abstruse_mapss_delete_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const array);
+#endif // _di_f_abstruse_mapss_delete_callback_
+
+/**
+ * A callback intended to be passed to f_memory_arrays_adjust() for an f_abstruse_mapss_t structure.
+ *
+ * This is only called when shrinking the array and generally should perform deallocations.
+ *
+ * This does not do parameter checking.
+ *
+ * @param start
+ *   The inclusive start position in the array to start deleting.
+ * @param stop
+ *   The exclusive stop position in the array to stop deleting.
+ * @param array
+ *   The array structure to delete all values of.
+ *   Must not be NULL.
+ *
+ * @return
+ *   F_okay on success.
+ *
+ *   Errors (with error bit) from: f_memory_array_adjust().
+ *   Errors (with error bit) from: f_memory_arrays_adjust().
+ *
+ * @see f_memory_array_adjust()
+ * @see f_memory_arrays_adjust()
+ */
+#ifndef _di_f_abstruse_mapss_destroy_callback_
+  extern f_status_t f_abstruse_mapss_destroy_callback(const f_number_unsigned_t start, const f_number_unsigned_t stop, void * const array);
+#endif // _di_f_abstruse_mapss_destroy_callback_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _F_type_abstruse_map_h
diff --git a/level_0/f_abstruse/c/abstruse/private-abstruse.c b/level_0/f_abstruse/c/abstruse/private-abstruse.c
new file mode 100644 (file)
index 0000000..7753f1b
--- /dev/null
@@ -0,0 +1,346 @@
+#include "../abstruse.h"
+#include "private-abstruse.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(_di_f_abstruses_delete_callback_) || !defined(_di_f_abstrusess_delete_callback_) || !defined(_di_f_abstruse_maps_delete_callback_) || !defined(_di_f_abstruse_mapss_delete_callback_)
+  f_status_t private_f_abstruses_delete_switch(f_abstruse_t * const abstruse) {
+
+    switch (abstruse->type) {
+      case f_abstruse_uint8_e:
+        if (abstruse->is.a_u8s.size) {
+          return f_memory_array_resize(0, sizeof(uint8_t), (void **) &abstruse->is.a_u8s.array, &abstruse->is.a_u8s.used, &abstruse->is.a_u8s.size);
+        }
+
+        break;
+
+      case f_abstruse_uint16s_e:
+        if (abstruse->is.a_u16s.size) {
+          return f_memory_array_resize(0, sizeof(uint16_t), (void **) &abstruse->is.a_u16s.array, &abstruse->is.a_u16s.used, &abstruse->is.a_u16s.size);
+        }
+
+        break;
+
+      case f_abstruse_uint32s_e:
+        if (abstruse->is.a_u32s.size) {
+          return f_memory_array_resize(0, sizeof(uint32_t), (void **) &abstruse->is.a_u32s.array, &abstruse->is.a_u32s.used, &abstruse->is.a_u32s.size);
+        }
+
+        break;
+
+      case f_abstruse_uint64s_e:
+        if (abstruse->is.a_u64s.size) {
+          return f_memory_array_resize(0, sizeof(uint64_t), (void **) &abstruse->is.a_u64s.array, &abstruse->is.a_u64s.used, &abstruse->is.a_u64s.size);
+        }
+
+        break;
+
+      case f_abstruse_int8s_e:
+        if (abstruse->is.a_i8s.size) {
+          return f_memory_array_resize(0, sizeof(int8_t), (void **) &abstruse->is.a_i8s.array, &abstruse->is.a_i8s.used, &abstruse->is.a_i8s.size);
+        }
+
+        break;
+
+      case f_abstruse_int16s_e:
+        if (abstruse->is.a_i16s.size) {
+          return f_memory_array_resize(0, sizeof(int16_t), (void **) &abstruse->is.a_i16s.array, &abstruse->is.a_i16s.used, &abstruse->is.a_i16s.size);
+        }
+
+        break;
+
+      case f_abstruse_int32s_e:
+        if (abstruse->is.a_i32s.size) {
+          return f_memory_array_resize(0, sizeof(int32_t), (void **) &abstruse->is.a_i32s.array, &abstruse->is.a_i32s.used, &abstruse->is.a_i32s.size);
+        }
+
+        break;
+
+      case f_abstruse_int64s_e:
+        if (abstruse->is.a_i64s.size) {
+          return f_memory_array_resize(0, sizeof(int64_t), (void **) &abstruse->is.a_i64s.array, &abstruse->is.a_i64s.used, &abstruse->is.a_i64s.size);
+        }
+
+        break;
+
+      case f_abstruse_signeds_e:
+        if (abstruse->is.a_signeds.size) {
+          return f_memory_array_resize(0, sizeof(f_number_signed_t), (void **) &abstruse->is.a_signeds.array, &abstruse->is.a_signeds.used, &abstruse->is.a_signeds.size);
+        }
+
+        break;
+
+      case f_abstruse_unsigneds_e:
+        if (abstruse->is.a_unsigneds.size) {
+          return f_memory_array_resize(0, sizeof(f_number_unsigned_t), (void **) &abstruse->is.a_unsigneds.array, &abstruse->is.a_unsigneds.used, &abstruse->is.a_unsigneds.size);
+        }
+
+        break;
+
+      case f_abstruse_dynamic_e:
+        if (abstruse->is.a_dynamic.size) {
+          return f_memory_array_resize(0, sizeof(f_char_t), (void **) &abstruse->is.a_dynamic.string, &abstruse->is.a_dynamic.used, &abstruse->is.a_dynamic.size);
+        }
+
+        break;
+
+      case f_abstruse_dynamics_e:
+        if (abstruse->is.a_dynamics.size) {
+          return f_memory_arrays_resize(0, sizeof(f_string_dynamic_t), (void **) &abstruse->is.a_dynamics.array, &abstruse->is.a_dynamics.used, &abstruse->is.a_dynamics.size, &f_string_dynamics_delete_callback);
+        }
+
+        break;
+
+      case f_abstruse_map_e:
+        if (abstruse->is.a_map.name.size) {
+          return f_memory_array_resize(0, sizeof(f_char_t), (void **) &abstruse->is.a_map.name.string, &abstruse->is.a_map.name.used, &abstruse->is.a_map.name.size);
+        }
+
+        if (abstruse->is.a_map.value.size) {
+          return f_memory_array_resize(0, sizeof(f_char_t), (void **) &abstruse->is.a_map.value.string, &abstruse->is.a_map.value.used, &abstruse->is.a_map.value.size);
+        }
+
+        break;
+
+      case f_abstruse_maps_e:
+        if (abstruse->is.a_maps.size) {
+          return f_memory_arrays_resize(0, sizeof(f_string_map_t), (void **) &abstruse->is.a_maps.array, &abstruse->is.a_maps.used, &abstruse->is.a_maps.size, &f_string_maps_delete_callback);
+        }
+
+        break;
+
+      case f_abstruse_map_multi_e:
+        if (abstruse->is.a_map_multi.name.size) {
+          return f_memory_array_resize(0, sizeof(f_char_t), (void **) &abstruse->is.a_map_multi.name.string, &abstruse->is.a_map_multi.name.used, &abstruse->is.a_map_multi.name.size);
+        }
+
+        if (abstruse->is.a_map_multi.value.size) {
+          return f_memory_arrays_resize(0, sizeof(f_string_dynamic_t), (void **) &abstruse->is.a_map_multi.value.array, &abstruse->is.a_map_multi.value.used, &abstruse->is.a_map_multi.value.size, &f_string_dynamics_delete_callback);
+        }
+
+        break;
+
+      case f_abstruse_map_multis_e:
+        if (abstruse->is.a_map_multis.size) {
+          return f_memory_arrays_resize(0, sizeof(f_string_map_multi_t), (void **) &abstruse->is.a_map_multis.array, &abstruse->is.a_map_multis.used, &abstruse->is.a_map_multis.size, &f_string_map_multis_delete_callback);
+        }
+
+        break;
+
+      case f_abstruse_quantitys_e:
+        if (abstruse->is.a_quantitys.size) {
+          return f_memory_array_resize(0, sizeof(f_string_quantity_t), (void **) &abstruse->is.a_quantitys.array, &abstruse->is.a_quantitys.used, &abstruse->is.a_quantitys.size);
+        }
+
+        break;
+
+      case f_abstruse_ranges_e:
+        if (abstruse->is.a_quantitys.size) {
+          return f_memory_array_resize(0, sizeof(f_string_range_t), (void **) &abstruse->is.a_ranges.array, &abstruse->is.a_ranges.used, &abstruse->is.a_ranges.size);
+        }
+
+        break;
+
+      case f_abstruse_triple_e:
+        if (abstruse->is.a_triple.a.size) {
+          return f_memory_array_resize(0, sizeof(f_char_t), (void **) &abstruse->is.a_triple.a.string, &abstruse->is.a_triple.a.used, &abstruse->is.a_triple.a.size);
+        }
+
+        if (abstruse->is.a_triple.b.size) {
+          return f_memory_array_resize(0, sizeof(f_char_t), (void **) &abstruse->is.a_triple.b.string, &abstruse->is.a_triple.b.used, &abstruse->is.a_triple.b.size);
+        }
+
+        if (abstruse->is.a_triple.c.size) {
+          return f_memory_array_resize(0, sizeof(f_char_t), (void **) &abstruse->is.a_triple.c.string, &abstruse->is.a_triple.c.used, &abstruse->is.a_triple.c.size);
+        }
+
+        break;
+
+      case f_abstruse_triples_e:
+        if (abstruse->is.a_triples.size) {
+          return f_memory_arrays_resize(0, sizeof(f_string_triple_t), (void **) &abstruse->is.a_triples.array, &abstruse->is.a_triples.used, &abstruse->is.a_triples.size, &f_string_triples_delete_callback);
+        }
+
+        break;
+
+      default:
+        break;
+    };
+
+    return F_okay;
+  }
+#endif // !defined(_di_f_abstruses_delete_callback_) || !defined(_di_f_abstrusess_delete_callback_) || !defined(_di_f_abstruse_maps_delete_callback_) || !defined(_di_f_abstruse_mapss_delete_callback_)
+
+#if !defined(_di_f_abstruses_destroy_callback_) || !defined(_di_f_abstrusess_destroy_callback_) || !defined(_di_f_abstruse_maps_destroy_callback_) || !defined(_di_f_abstruse_mapss_destroy_callback_)
+  f_status_t private_f_abstruses_destroy_switch(f_abstruse_t * const abstruse) {
+
+    switch (abstruse->type) {
+      case f_abstruse_uint8_e:
+        if (abstruse->is.a_u8s.size) {
+          return f_memory_array_adjust(0, sizeof(uint8_t), (void **) &abstruse->is.a_u8s.array, &abstruse->is.a_u8s.used, &abstruse->is.a_u8s.size);
+        }
+
+        break;
+
+      case f_abstruse_uint16s_e:
+        if (abstruse->is.a_u16s.size) {
+          return f_memory_array_adjust(0, sizeof(uint16_t), (void **) &abstruse->is.a_u16s.array, &abstruse->is.a_u16s.used, &abstruse->is.a_u16s.size);
+        }
+
+        break;
+
+      case f_abstruse_uint32s_e:
+        if (abstruse->is.a_u32s.size) {
+          return f_memory_array_adjust(0, sizeof(uint32_t), (void **) &abstruse->is.a_u32s.array, &abstruse->is.a_u32s.used, &abstruse->is.a_u32s.size);
+        }
+
+        break;
+
+      case f_abstruse_uint64s_e:
+        if (abstruse->is.a_u64s.size) {
+          return f_memory_array_adjust(0, sizeof(uint64_t), (void **) &abstruse->is.a_u64s.array, &abstruse->is.a_u64s.used, &abstruse->is.a_u64s.size);
+        }
+
+        break;
+
+      case f_abstruse_int8s_e:
+        if (abstruse->is.a_i8s.size) {
+          return f_memory_array_adjust(0, sizeof(int8_t), (void **) &abstruse->is.a_i8s.array, &abstruse->is.a_i8s.used, &abstruse->is.a_i8s.size);
+        }
+
+        break;
+
+      case f_abstruse_int16s_e:
+        if (abstruse->is.a_i16s.size) {
+          return f_memory_array_adjust(0, sizeof(int16_t), (void **) &abstruse->is.a_i16s.array, &abstruse->is.a_i16s.used, &abstruse->is.a_i16s.size);
+        }
+
+        break;
+
+      case f_abstruse_int32s_e:
+        if (abstruse->is.a_i32s.size) {
+          return f_memory_array_adjust(0, sizeof(int32_t), (void **) &abstruse->is.a_i32s.array, &abstruse->is.a_i32s.used, &abstruse->is.a_i32s.size);
+        }
+
+        break;
+
+      case f_abstruse_int64s_e:
+        if (abstruse->is.a_i64s.size) {
+          return f_memory_array_adjust(0, sizeof(int64_t), (void **) &abstruse->is.a_i64s.array, &abstruse->is.a_i64s.used, &abstruse->is.a_i64s.size);
+        }
+
+        break;
+
+      case f_abstruse_signeds_e:
+        if (abstruse->is.a_signeds.size) {
+          return f_memory_array_adjust(0, sizeof(f_number_signed_t), (void **) &abstruse->is.a_signeds.array, &abstruse->is.a_signeds.used, &abstruse->is.a_signeds.size);
+        }
+
+        break;
+
+      case f_abstruse_unsigneds_e:
+        if (abstruse->is.a_unsigneds.size) {
+          return f_memory_array_adjust(0, sizeof(f_number_unsigned_t), (void **) &abstruse->is.a_unsigneds.array, &abstruse->is.a_unsigneds.used, &abstruse->is.a_unsigneds.size);
+        }
+
+        break;
+
+      case f_abstruse_dynamic_e:
+        if (abstruse->is.a_dynamic.size) {
+          return f_memory_array_adjust(0, sizeof(f_char_t), (void **) &abstruse->is.a_dynamic.string, &abstruse->is.a_dynamic.used, &abstruse->is.a_dynamic.size);
+        }
+
+        break;
+
+      case f_abstruse_dynamics_e:
+        if (abstruse->is.a_dynamics.size) {
+          return f_memory_arrays_adjust(0, sizeof(f_string_dynamic_t), (void **) &abstruse->is.a_dynamics.array, &abstruse->is.a_dynamics.used, &abstruse->is.a_dynamics.size, &f_string_dynamics_destroy_callback);
+        }
+
+        break;
+
+      case f_abstruse_map_e:
+        if (abstruse->is.a_map.name.size) {
+          return f_memory_array_adjust(0, sizeof(f_char_t), (void **) &abstruse->is.a_map.name.string, &abstruse->is.a_map.name.used, &abstruse->is.a_map.name.size);
+        }
+
+        if (abstruse->is.a_map.value.size) {
+          return f_memory_array_adjust(0, sizeof(f_char_t), (void **) &abstruse->is.a_map.value.string, &abstruse->is.a_map.value.used, &abstruse->is.a_map.value.size);
+        }
+
+        break;
+
+      case f_abstruse_maps_e:
+        if (abstruse->is.a_maps.size) {
+          return f_memory_arrays_adjust(0, sizeof(f_string_map_t), (void **) &abstruse->is.a_maps.array, &abstruse->is.a_maps.used, &abstruse->is.a_maps.size, &f_string_maps_destroy_callback);
+        }
+
+        break;
+
+      case f_abstruse_map_multi_e:
+        if (abstruse->is.a_map_multi.name.size) {
+          return f_memory_array_adjust(0, sizeof(f_char_t), (void **) &abstruse->is.a_map_multi.name.string, &abstruse->is.a_map_multi.name.used, &abstruse->is.a_map_multi.name.size);
+        }
+
+        if (abstruse->is.a_map_multi.value.size) {
+          return f_memory_arrays_adjust(0, sizeof(f_string_dynamic_t), (void **) &abstruse->is.a_map_multi.value.array, &abstruse->is.a_map_multi.value.used, &abstruse->is.a_map_multi.value.size, &f_string_dynamics_destroy_callback);
+        }
+
+        break;
+
+      case f_abstruse_map_multis_e:
+        if (abstruse->is.a_map_multis.size) {
+          return f_memory_arrays_adjust(0, sizeof(f_string_map_multi_t), (void **) &abstruse->is.a_map_multis.array, &abstruse->is.a_map_multis.used, &abstruse->is.a_map_multis.size, &f_string_map_multis_destroy_callback);
+        }
+
+        break;
+
+      case f_abstruse_quantitys_e:
+        if (abstruse->is.a_quantitys.size) {
+          return f_memory_array_adjust(0, sizeof(f_string_quantity_t), (void **) &abstruse->is.a_quantitys.array, &abstruse->is.a_quantitys.used, &abstruse->is.a_quantitys.size);
+        }
+
+        break;
+
+      case f_abstruse_ranges_e:
+        if (abstruse->is.a_quantitys.size) {
+          return f_memory_array_adjust(0, sizeof(f_string_range_t), (void **) &abstruse->is.a_ranges.array, &abstruse->is.a_ranges.used, &abstruse->is.a_ranges.size);
+        }
+
+        break;
+
+      case f_abstruse_triple_e:
+        if (abstruse->is.a_triple.a.size) {
+          return f_memory_array_adjust(0, sizeof(f_char_t), (void **) &abstruse->is.a_triple.a.string, &abstruse->is.a_triple.a.used, &abstruse->is.a_triple.a.size);
+        }
+
+        if (abstruse->is.a_triple.b.size) {
+          return f_memory_array_adjust(0, sizeof(f_char_t), (void **) &abstruse->is.a_triple.b.string, &abstruse->is.a_triple.b.used, &abstruse->is.a_triple.b.size);
+        }
+
+        if (abstruse->is.a_triple.c.size) {
+          return f_memory_array_adjust(0, sizeof(f_char_t), (void **) &abstruse->is.a_triple.c.string, &abstruse->is.a_triple.c.used, &abstruse->is.a_triple.c.size);
+        }
+
+        break;
+
+      case f_abstruse_triples_e:
+        if (abstruse->is.a_triples.size) {
+          return f_memory_arrays_adjust(0, sizeof(f_string_triple_t), (void **) &abstruse->is.a_triples.array, &abstruse->is.a_triples.used, &abstruse->is.a_triples.size, &f_string_triples_destroy_callback);
+        }
+
+        break;
+
+      default:
+        break;
+    };
+
+    return F_okay;
+  }
+#endif // !defined(_di_f_abstruses_destroy_callback_) || !defined(_di_f_abstrusess_destroy_callback_) || !defined(_di_f_abstruse_maps_destroy_callback_) || !defined(_di_f_abstruse_mapss_destroy_callback_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_abstruse/c/abstruse/private-abstruse.h b/level_0/f_abstruse/c/abstruse/private-abstruse.h
new file mode 100644 (file)
index 0000000..7d3d98f
--- /dev/null
@@ -0,0 +1,64 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Abstruse
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * These are provided for internal reduction in redundant code.
+ * These should not be exposed/used outside of this project.
+ */
+#ifndef _PRIVATE_F_abstruse_h
+#define _PRIVATE_F_abstruse_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Helper function for abstruse delete callbacks, performing the switch logic against the abstruse type.
+ *
+ * Intended to be shared to each of the different implementation variations.
+ *
+ * @param abstruse
+ *   The abstruse to perform the switch-based delete operation on.
+ *
+ * @return
+ *   F_okay on success, including when nothing done due to no match against the type.
+ *
+ *   Errors (with error bit) from: f_memory_array_resize().
+ *   Errors (with error bit) from: f_memory_arrays_resize().
+ *
+ * @see f_memory_array_resize()
+ * @see f_memory_arrays_resize()
+ */
+#if !defined(_di_f_abstruses_delete_callback_) || !defined(_di_f_abstrusess_delete_callback_) || !defined(_di_f_abstruse_maps_delete_callback_) || !defined(_di_f_abstruse_mapss_delete_callback_)
+  extern f_status_t private_f_abstruses_delete_switch(f_abstruse_t * const abstruse) F_attribute_visibility_internal_d;
+#endif // !defined(_di_f_abstruses_delete_callback_) || !defined(_di_f_abstrusess_delete_callback_) || !defined(_di_f_abstruse_maps_delete_callback_) || !defined(_di_f_abstruse_mapss_delete_callback_)
+
+/**
+ * Helper function for abstruse destroy callbacks, performing the switch logic against the abstruse type.
+ *
+ * Intended to be shared to each of the different implementation variations.
+ *
+ * @param abstruse
+ *   The abstruse to perform the switch-based destroy operation on.
+ *
+ * @return
+ *   F_okay on success, including when nothing done due to no match against the type.
+ *
+ *   Errors (with error bit) from: f_memory_array_adjust().
+ *   Errors (with error bit) from: f_memory_arrays_adjust().
+ *
+ * @see f_memory_array_adjust()
+ * @see f_memory_arrays_adjust()
+ */
+#if !defined(_di_f_abstruses_destroy_callback_) || !defined(_di_f_abstrusess_destroy_callback_) || !defined(_di_f_abstruse_maps_destroy_callback_) || !defined(_di_f_abstruse_mapss_destroy_callback_)
+  extern f_status_t private_f_abstruses_destroy_switch(f_abstruse_t * const abstruse) F_attribute_visibility_internal_d;
+#endif // !defined(_di_f_abstruses_destroy_callback_) || !defined(_di_f_abstrusess_destroy_callback_) || !defined(_di_f_abstruse_maps_destroy_callback_) || !defined(_di_f_abstruse_mapss_destroy_callback_)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _PRIVATE_F_abstruse_h
diff --git a/level_0/f_abstruse/c/abstruse/type.h b/level_0/f_abstruse/c/abstruse/type.h
new file mode 100644 (file)
index 0000000..be26152
--- /dev/null
@@ -0,0 +1,84 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Abstuse
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Defines abstruse type data.
+ *
+ * This is auto-included by abstruse.h and should not need to be explicitly included.
+ */
+#ifndef _F_type_abstruse_type_h
+#define _F_type_abstruse_type_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * An abstruse type is a union representing any particular set of common types.
+ *
+ * The common type property names are prefixed with "a_" followed by the type name without the suffix "_t".
+ *
+ * This must be specially handled when swapping between types that contain allocated data.
+ * Be sure to de-allocate all memory before swapping to a differrent type.
+ */
+#ifndef _di_f_abstruse_type_t_
+  typedef union {
+    uint8_t               a_u8;
+    f_uint8s_t            a_u8s;
+    uint16_t              a_u16;
+    f_uint16s_t           a_u16s;
+    uint32_t              a_u32;
+    f_uint32s_t           a_u32s;
+    uint64_t              a_u64;
+    f_uint64s_t           a_u64s;
+    int8_t                a_i8;
+    f_int8s_t             a_i8s;
+    int16_t               a_i16;
+    f_int16s_t            a_i16s;
+    int32_t               a_i32;
+    f_int32s_t            a_i32s;
+    int64_t               a_i64;
+    f_int64s_t            a_i64s;
+    f_number_signed_t     a_signed;
+    f_number_signeds_t    a_signeds;
+    f_number_unsigned_t   a_unsigned;
+    f_number_unsigneds_t  a_unsigneds;
+    f_char_t              a_char;
+    f_string_t            a_string;
+    f_string_t *          a_strings;
+    f_string_dynamic_t    a_dynamic;
+    f_string_dynamics_t   a_dynamics;
+    f_string_map_t        a_map;
+    f_string_maps_t       a_maps;
+    f_string_map_multi_t  a_map_multi;
+    f_string_map_multis_t a_map_multis;
+    f_string_quantity_t   a_quantity;
+    f_string_quantitys_t  a_quantitys;
+    f_string_range_t      a_range;
+    f_string_ranges_t     a_ranges;
+    f_string_triple_t     a_triple;
+    f_string_triples_t    a_triples;
+    void *                a_void;
+    void **               a_voids;
+    size_t                a_size;
+    size_t *              a_sizes;
+    ssize_t               a_ssize;
+    ssize_t *             a_ssizes;
+  } f_abstruse_type_t;
+
+  #define f_abstruse_type_t_initialize { 0 }
+
+  #define macro_f_abstruse_type_t_initialize_1(value) { value }
+
+  #define macro_f_abstruse_type_t_clear(abstruse_type) \
+    abstruse_type = 0;
+#endif // _di_f_abstruse_type_t_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _F_type_abstruse_type_h
diff --git a/level_0/f_abstruse/data/build/defines b/level_0/f_abstruse/data/build/defines
new file mode 100644 (file)
index 0000000..c665317
--- /dev/null
@@ -0,0 +1,2 @@
+# fss-0000
+
diff --git a/level_0/f_abstruse/data/build/dependencies b/level_0/f_abstruse/data/build/dependencies
new file mode 100644 (file)
index 0000000..d798245
--- /dev/null
@@ -0,0 +1,6 @@
+# fss-0000
+
+f_type
+f_status
+f_memory
+f_string
diff --git a/level_0/f_abstruse/data/build/dependencies-tests b/level_0/f_abstruse/data/build/dependencies-tests
new file mode 100644 (file)
index 0000000..dea3179
--- /dev/null
@@ -0,0 +1,3 @@
+# fss-0001
+
+cmocka 1.*
diff --git a/level_0/f_abstruse/data/build/fakefile b/level_0/f_abstruse/data/build/fakefile
new file mode 100644 (file)
index 0000000..90a7134
--- /dev/null
@@ -0,0 +1,12 @@
+# fss-0005 iki-0002
+
+settings:
+  fail exit
+  modes individual individual_thread level monolithic clang test fanalyzer thread threadless
+
+  environment PATH LD_LIBRARY_PATH
+  environment LANG LC_ALL LC_COLLATE LC_CTYPE LC_FASTMSG LC_MESSAGES LC_MONETARY LC_NUMERIC LC_TIME LOCPATH NLSPATH
+
+main:
+
+  build
diff --git a/level_0/f_abstruse/data/build/settings b/level_0/f_abstruse/data/build/settings
new file mode 100644 (file)
index 0000000..cc8c83a
--- /dev/null
@@ -0,0 +1,70 @@
+# fss-0001
+#
+# Modes:
+#   - individual:        Compile using per project (individual) libraries, does not handle thread or threadless cases.
+#   - individual_thread: This is required when compiling in individual mode with "thread" mode.
+#   - level:             Compile using per level libraries.
+#   - monolithic:        Compile using per monolithic libraries.
+#   - clang:             Use clang rather than the default, which is generally gcc.
+#   - test:              Compile for a test, such as unit testing.
+#   - fanalyzer:         Compile using GCC's -fanalyzer compile time option.
+#   - thread:            Compile with thread support.
+#   - threadless:        Compile without thread support.
+#
+
+build_name f_abstruse
+
+version_major 0
+version_minor 7
+version_micro 0
+version_file micro
+version_target minor
+
+modes individual individual_thread level monolithic clang test fanalyzer thread threadless
+modes_default individual individual_thread thread
+
+build_compiler gcc
+build_compiler-clang clang
+build_indexer ar
+build_indexer_arguments rcs
+build_language c
+
+build_libraries -lc
+build_libraries-individual -lf_memory -lf_string
+
+build_sources_library abstruse.c abstruse/abstruse.c abstruse/map.c abstruse/private-abstruse.c
+build_sources_headers abstruse.h abstruse/abstruse.h abstruse/enum.h abstruse/map.h abstruse/type.h
+
+build_script yes
+build_shared yes
+build_static no
+
+path_headers fll/level_0
+path_library_script script
+path_library_shared shared
+path_library_static static
+path_object_script script
+path_object_shared shared
+path_object_static static
+path_program_script script
+path_program_shared shared
+path_program_static static
+
+has_path_standard yes
+preserve_path_headers yes
+
+search_exclusive yes
+search_shared yes
+search_static yes
+
+environment PATH LD_LIBRARY_PATH
+environment LANG LC_ALL LC_COLLATE LC_CTYPE LC_FASTMSG LC_MESSAGES LC_MONETARY LC_NUMERIC LC_TIME LOCPATH NLSPATH
+
+flags -O2 -z now -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-parentheses
+flags-clang -Wno-logical-op-parentheses
+flags-test -O0 -fstack-protector -Wall
+flags-coverage -O0 --coverage -fprofile-abs-path -fprofile-dir=build/coverage/
+
+flags_library -fPIC
+flags_object -fPIC
+flags_program -fPIE
diff --git a/level_0/f_abstruse/data/build/settings-mocks b/level_0/f_abstruse/data/build/settings-mocks
new file mode 100644 (file)
index 0000000..bdf28dc
--- /dev/null
@@ -0,0 +1,69 @@
+# fss-0001
+#
+# Build the project with appropriate mocks linked in via the dynamic linker's "--wrap" functionality.
+#
+# The -Wl,--wrap does not work across shared files.
+# Therefore, this file is a work-around to inject the mocks into the library for testing purposes.
+# This should exactly match the "settings" file, except for the additional "-Wl,--wrap" parts and the additional mock source file.
+#
+# The flags -o0 must be passed to prevent the compiler from optimizing away any functions being mocked (which results in the mock not happening and a real function being called).
+# Alternatively, figure out which optimization that is disabled by -o0 and have that specific optimization disabled.
+#
+
+build_name f_abstruse
+
+version_major 0
+version_minor 7
+version_micro 0
+version_file micro
+version_target minor
+
+modes individual clang test coverage
+modes_default individual test
+
+build_compiler gcc
+build_compiler-clang clang
+build_indexer ar
+build_indexer_arguments rcs
+build_language c
+
+build_libraries -lc
+build_libraries-individual -lf_memory -lf_string
+
+build_sources_library abstruse.c abstruse/abstruse.c abstruse/map.c abstruse/private-abstruse.c
+build_sources_library ../../tests/unit/c/mock-abstruse.c
+
+build_sources_headers abstruse.h abstruse/abstruse.h abstruse/enum.h abstruse/map.h abstruse/type.h
+
+build_script yes
+build_shared yes
+build_static no
+
+path_headers fll/level_0
+path_library_script script
+path_library_shared shared
+path_library_static static
+
+has_path_standard yes
+preserve_path_headers yes
+
+search_exclusive yes
+search_shared yes
+search_static yes
+
+environment PATH LD_LIBRARY_PATH
+environment LANG LC_ALL LC_COLLATE LC_CTYPE LC_FASTMSG LC_MESSAGES LC_MONETARY LC_NUMERIC LC_TIME LOCPATH NLSPATH
+
+#defines -D_pthread_attr_unsupported_ -D_pthread_sigqueue_unsupported_
+defines -D_pthread_sigqueue_unsupported_
+
+flags -O0 -z now -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-parentheses
+flags-clang -Wno-logical-op-parentheses
+flags-test -fstack-protector -Wall
+flags-coverage --coverage -fprofile-abs-path -fprofile-dir=build/coverage/
+
+flags_library -fPIC
+
+# Inject mocks.
+flags -Wl,--wrap=f_memory_array_adjust
+flags -Wl,--wrap=f_memory_array_resize
diff --git a/level_0/f_abstruse/data/build/settings-tests b/level_0/f_abstruse/data/build/settings-tests
new file mode 100644 (file)
index 0000000..5bc01ca
--- /dev/null
@@ -0,0 +1,58 @@
+# fss-0001
+#
+# Builds a program that is links to the generated library and is executed to perform tests.
+#
+# Memory leaks in the test program can be checked for by running valgrind with this executable.
+#
+
+build_name test-f_abstruse
+
+version_major 0
+version_minor 7
+version_micro 0
+version_file major
+version_target major
+
+modes individual clang test coverage
+modes_default individual test
+
+build_compiler gcc
+build_compiler-clang clang
+build_indexer ar
+build_indexer_arguments rcs
+build_language c
+
+build_libraries -lc -lcmocka
+build_libraries-individual -lf_memory -lf_string -lf_abstruse
+
+build_sources_program test-abstruse-s_delete_callback.c test-abstruse-s_destroy_callback.c test-abstruse-ss_delete_callback.c test-abstruse-ss_destroy_callback.c
+build_sources_program test-abstruse-maps_delete_callback.c test-abstruse-maps_destroy_callback.c test-abstruse-mapss_delete_callback.c test-abstruse-mapss_destroy_callback.c
+build_sources_program test-abstruse.c
+
+build_script no
+build_shared yes
+build_static no
+
+path_headers tests/unit/c
+path_sources tests/unit/c
+
+has_path_standard no
+preserve_path_headers yes
+
+search_exclusive yes
+search_shared yes
+search_static yes
+
+environment PATH LD_LIBRARY_PATH
+environment LANG LC_ALL LC_COLLATE LC_CTYPE LC_FASTMSG LC_MESSAGES LC_MONETARY LC_NUMERIC LC_TIME LOCPATH NLSPATH
+
+defines -Ibuild/includes
+defines_static -Lbuild/libraries/static
+defines_shared -Lbuild/libraries/shared
+
+flags -O2 -z now -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-parentheses
+flags-clang -Wno-logical-op-parentheses
+flags-test -fstack-protector -Wall
+flags-coverage -O0 --coverage -fprofile-abs-path -fprofile-dir=build/coverage/
+
+flags_program -fPIE
diff --git a/level_0/f_abstruse/data/build/testfile b/level_0/f_abstruse/data/build/testfile
new file mode 100644 (file)
index 0000000..dbeaf4f
--- /dev/null
@@ -0,0 +1,63 @@
+# fss-0005 abstruse-0002
+
+settings:
+  load_build yes
+  fail exit
+
+  environment PATH LD_LIBRARY_PATH
+  environment LANG LC_ALL LC_COLLATE LC_CTYPE LC_FASTMSG LC_MESSAGES LC_MONETARY LC_NUMERIC LC_TIME LOCPATH NLSPATH
+  environment CMOCKA_XML_FILE CMOCKA_MESSAGE_OUTPUT CMOCKA_TEST_ABORT
+
+  # Cmocka is not fully thread-safe, set this to "1" to have cmocka call abort() on a test failure.
+  #CMOCKA_TEST_ABORT 1
+
+  # One of: STDOUT, SUBUNIT, TAP, or XML.
+  #define CMOCKA_MESSAGE_OUTPUT STDOUT
+
+  # When in "XML" output mode, output to this file rather than stdout.
+  #define CMOCKA_XML_FILE ./out.xml
+
+main:
+  build settings-mocks individual test
+  build settings-tests individual test
+
+  operate build_path
+  operate ld_library_path
+
+  if exist parameter:"build_path"programs/shared/test-f_abstruse
+    shell parameter:"build_path"programs/shared/test-f_abstruse
+
+  if exist parameter:"build_path"programs/static/test-f_abstruse
+    shell parameter:"build_path"programs/static/test-f_abstruse
+
+  if not exist parameter:"build_path"programs/shared/test-f_abstruse
+  and not exist parameter:"build_path"programs/static/test-f_abstruse
+    operate not_created
+
+not_created:
+  print
+  print 'context:"error"Failed to test due to being unable to find either a shared or static test binary to perform tests. context:"reset"'
+
+  exit failure
+
+build_path:
+  parameter build_path build/
+
+  if parameter build:value
+    parameter build_path parameter:"build:value"
+
+ld_library_path:
+  if define LD_LIBRARY_PATH
+  and parameter work:value
+    define LD_LIBRARY_PATH 'parameter:"build_path"libraries/shared:parameter:"work:value"libraries/shared:define:"LD_LIBRARY_PATH"'
+
+  else
+  if define LD_LIBRARY_PATH
+    define LD_LIBRARY_PATH 'parameter:"build_path"libraries/shared:define:"LD_LIBRARY_PATH"'
+
+  else
+  if parameter work:value
+    define LD_LIBRARY_PATH 'parameter:"build_path"libraries/shared:parameter:"work:value"libraries/shared'
+
+  else
+    define LD_LIBRARY_PATH 'parameter:"build_path"libraries/shared'
diff --git a/level_0/f_abstruse/tests/unit/c/mock-abstruse.c b/level_0/f_abstruse/tests/unit/c/mock-abstruse.c
new file mode 100644 (file)
index 0000000..a1455b4
--- /dev/null
@@ -0,0 +1,46 @@
+#include "mock-abstruse.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int mock_unwrap = 0;
+int mock_unwrap_f_memory = 1;
+
+f_status_t __wrap_f_memory_array_adjust(const f_number_unsigned_t length, const size_t width, void ** const array, f_number_unsigned_t * const used, f_number_unsigned_t * const size) {
+
+  if (mock_unwrap_f_memory) {
+    return __real_f_memory_array_adjust(length, width, array, used, size);
+  }
+
+  if (!array || !used || !size) return F_status_set_error(F_parameter_not);
+
+  const bool failure = mock_type(bool);
+
+  if (failure) return mock_type(f_status_t);
+
+  *size = length;
+
+  return mock_type(f_status_t);
+}
+
+f_status_t __wrap_f_memory_array_resize(const f_number_unsigned_t length, const size_t width, void ** const array, f_number_unsigned_t * const used, f_number_unsigned_t * const size) {
+
+  if (mock_unwrap_f_memory) {
+    return __real_f_memory_array_resize(length, width, array, used, size);
+  }
+
+  if (!array || !used || !size) return F_status_set_error(F_parameter_not);
+
+  const bool failure = mock_type(bool);
+
+  if (failure) return mock_type(f_status_t);
+
+  *size = length;
+
+  return mock_type(f_status_t);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_abstruse/tests/unit/c/mock-abstruse.h b/level_0/f_abstruse/tests/unit/c/mock-abstruse.h
new file mode 100644 (file)
index 0000000..4dcb9f0
--- /dev/null
@@ -0,0 +1,45 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: IKI
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the abstruse project.
+ */
+#ifndef _MOCK__abstruse_h
+#define _MOCK__abstruse_h
+
+// Libc includes.
+#include <semaphore.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+
+// cmocka includes.
+#include <cmocka.h>
+
+// FLL-0 includes.
+#include <fll/level_0/abstruse.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const static int mock_errno_generic = 32767;
+
+extern int mock_unwrap;
+extern int mock_unwrap_f_memory;
+
+extern f_status_t __real_f_memory_array_adjust(const f_number_unsigned_t length, const size_t width, void ** array, f_number_unsigned_t * const used, f_number_unsigned_t * const size);
+extern f_status_t __real_f_memory_array_resize(const f_number_unsigned_t length, const size_t width, void ** array, f_number_unsigned_t * const used, f_number_unsigned_t * const size);
+
+extern f_status_t __wrap_f_memory_array_adjust(const f_number_unsigned_t length, const size_t width, void ** array, f_number_unsigned_t * const used, f_number_unsigned_t * const size);
+extern f_status_t __wrap_f_memory_array_resize(const f_number_unsigned_t length, const size_t width, void ** array, f_number_unsigned_t * const used, f_number_unsigned_t * const size);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _MOCK__abstruse_h
diff --git a/level_0/f_abstruse/tests/unit/c/test-abstruse-maps_delete_callback.c b/level_0/f_abstruse/tests/unit/c/test-abstruse-maps_delete_callback.c
new file mode 100644 (file)
index 0000000..3014452
--- /dev/null
@@ -0,0 +1,119 @@
+#include "test-abstruse.h"
+#include "test-abstruse-maps_delete_callback.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_abstruse_maps_delete_callback__fails(void **state) {
+
+  mock_unwrap = 0;
+  mock_unwrap_f_memory = 0;
+
+  f_string_t a_string = "example";
+  f_string_range_t a_range = macro_f_string_range_t_initialize_1(1, 2);
+  f_string_static_t a_static = macro_f_string_static_t_initialize_1(a_string, 0, 7);
+  f_string_dynamic_t a_dynamic = f_string_dynamic_t_initialize;
+
+  f_abstruse_t value_0 = { .type = f_abstruse_range_e, .is.a_range = a_range };
+  f_abstruse_t value_1 = { .type = f_abstruse_string_e, .is.a_string = a_string };
+  f_abstruse_t value_2 = { .type = f_abstruse_dynamic_e, .is.a_dynamic = a_static };
+  f_abstruse_t value_3 = { .type = f_abstruse_dynamic_e, .is.a_dynamic = a_dynamic };
+
+  f_string_static_t key_0 = macro_f_string_static_t_initialize_2("key_0", 5);
+  f_string_static_t key_1 = macro_f_string_static_t_initialize_2("key_1", 5);
+  f_string_static_t key_2 = macro_f_string_static_t_initialize_2("key_2", 5);
+  f_string_static_t key_3 = macro_f_string_static_t_initialize_2("key_3", 5);
+
+  f_abstruse_map_t data_0 = macro_f_abstruse_map_t_initialize_1(key_0, value_0);
+  f_abstruse_map_t data_1 = macro_f_abstruse_map_t_initialize_1(key_1, value_1);
+  f_abstruse_map_t data_2 = macro_f_abstruse_map_t_initialize_1(key_2, value_2);
+  f_abstruse_map_t data_3 = macro_f_abstruse_map_t_initialize_1(key_3, value_3);
+
+  f_abstruse_map_t data_array[] = { data_0, data_1, data_2, data_3 };
+
+  const f_number_unsigned_t length = 4;
+
+  {
+    will_return(__wrap_f_memory_array_resize, true);
+    will_return(__wrap_f_memory_array_resize, F_status_set_error(F_failure));
+
+    const f_status_t status = f_abstruse_maps_delete_callback(0, length, (void *) data_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+
+  free((void *) a_dynamic.string);
+}
+
+void test__f_abstruse_maps_delete_callback__works(void **state) {
+
+  mock_unwrap = 0;
+  mock_unwrap_f_memory = 1;
+
+  f_string_t a_string = "example";
+  f_string_range_t a_range = macro_f_string_range_t_initialize_1(1, 2);
+  f_string_static_t a_static = macro_f_string_static_t_initialize_1(a_string, 0, 7);
+  f_string_dynamic_t a_dynamic = f_string_dynamic_t_initialize;
+
+  f_abstruse_t value_0 = { .type = f_abstruse_range_e, .is.a_range = a_range };
+  f_abstruse_t value_1 = { .type = f_abstruse_string_e, .is.a_string = a_string };
+  f_abstruse_t value_2 = { .type = f_abstruse_dynamic_e, .is.a_dynamic = a_static };
+  f_abstruse_t value_3 = { .type = f_abstruse_dynamic_e, .is.a_dynamic = a_dynamic };
+
+  f_string_dynamic_t key_0 = f_string_static_t_initialize;
+  f_string_dynamic_t key_1 = f_string_static_t_initialize;
+  f_string_dynamic_t key_2 = f_string_static_t_initialize;
+  f_string_dynamic_t key_3 = f_string_static_t_initialize;
+
+  f_abstruse_map_t data_0 = macro_f_abstruse_map_t_initialize_1(key_0, value_0);
+  f_abstruse_map_t data_1 = macro_f_abstruse_map_t_initialize_1(key_1, value_1);
+  f_abstruse_map_t data_2 = macro_f_abstruse_map_t_initialize_1(key_2, value_2);
+  f_abstruse_map_t data_3 = macro_f_abstruse_map_t_initialize_1(key_3, value_3);
+
+  f_abstruse_map_t data_array[] = { data_0, data_1, data_2, data_3 };
+
+  const f_number_unsigned_t length = 4;
+
+  f_abstruse_maps_t datas = macro_f_abstruse_maps_t_initialize_2(data_array, length);
+
+  {
+    f_status_t status = f_string_append("key_0", 5, &datas.array[0].key);
+    assert_int_equal(status, F_okay);
+
+    status = f_string_append("key_1", 5, &datas.array[1].key);
+    assert_int_equal(status, F_okay);
+
+    status = f_string_append("key_2", 5, &datas.array[2].key);
+    assert_int_equal(status, F_okay);
+
+    status = f_string_append("key_3", 5, &datas.array[3].key);
+    assert_int_equal(status, F_okay);
+
+    status = f_string_append("a", 1, &datas.array[3].value.is.a_dynamic);
+    assert_int_equal(status, F_okay);
+  }
+
+  {
+    const f_status_t status = f_abstruse_maps_delete_callback(0, length, (void *) datas.array);
+
+    assert_int_equal(status, F_okay);
+
+    assert_int_equal(datas.array[0].key.size, 0);
+    assert_int_equal(datas.array[1].key.size, 0);
+    assert_int_equal(datas.array[2].key.size, 0);
+
+    assert_int_equal(datas.array[3].key.size, 0);
+    assert_int_equal(datas.array[3].value.is.a_dynamic.size, 0);
+  }
+
+  free((void *) key_0.string);
+  free((void *) key_1.string);
+  free((void *) key_2.string);
+  free((void *) key_3.string);
+  free((void *) a_dynamic.string);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_abstruse/tests/unit/c/test-abstruse-maps_delete_callback.h b/level_0/f_abstruse/tests/unit/c/test-abstruse-maps_delete_callback.h
new file mode 100644 (file)
index 0000000..9158496
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Abstruse
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the abstract project.
+ */
+#ifndef _TEST__F_abstruse__maps_delete_callback
+#define _TEST__F_abstruse__maps_delete_callback
+
+/**
+ * Test that the function fails.
+ *
+ * @see f_abstruse_maps_delete_callback()
+ */
+extern void test__f_abstruse_maps_delete_callback__fails(void **state);
+
+/**
+ * Test that the function works.
+ *
+ * @see f_abstruse_maps_delete_callback()
+ */
+extern void test__f_abstruse_maps_delete_callback__works(void **state);
+
+#endif // _TEST__F_abstruse__maps_delete_callback
diff --git a/level_0/f_abstruse/tests/unit/c/test-abstruse-maps_destroy_callback.c b/level_0/f_abstruse/tests/unit/c/test-abstruse-maps_destroy_callback.c
new file mode 100644 (file)
index 0000000..c8ae558
--- /dev/null
@@ -0,0 +1,119 @@
+#include "test-abstruse.h"
+#include "test-abstruse-maps_destroy_callback.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_abstruse_maps_destroy_callback__fails(void **state) {
+
+  mock_unwrap = 0;
+  mock_unwrap_f_memory = 0;
+
+  f_string_t a_string = "example";
+  f_string_range_t a_range = macro_f_string_range_t_initialize_1(1, 2);
+  f_string_static_t a_static = macro_f_string_static_t_initialize_1(a_string, 0, 7);
+  f_string_dynamic_t a_dynamic = f_string_dynamic_t_initialize;
+
+  f_abstruse_t value_0 = { .type = f_abstruse_range_e, .is.a_range = a_range };
+  f_abstruse_t value_1 = { .type = f_abstruse_string_e, .is.a_string = a_string };
+  f_abstruse_t value_2 = { .type = f_abstruse_dynamic_e, .is.a_dynamic = a_static };
+  f_abstruse_t value_3 = { .type = f_abstruse_dynamic_e, .is.a_dynamic = a_dynamic };
+
+  f_string_static_t key_0 = macro_f_string_static_t_initialize_2("key_0", 5);
+  f_string_static_t key_1 = macro_f_string_static_t_initialize_2("key_1", 5);
+  f_string_static_t key_2 = macro_f_string_static_t_initialize_2("key_2", 5);
+  f_string_static_t key_3 = macro_f_string_static_t_initialize_2("key_3", 5);
+
+  f_abstruse_map_t data_0 = macro_f_abstruse_map_t_initialize_1(key_0, value_0);
+  f_abstruse_map_t data_1 = macro_f_abstruse_map_t_initialize_1(key_1, value_1);
+  f_abstruse_map_t data_2 = macro_f_abstruse_map_t_initialize_1(key_2, value_2);
+  f_abstruse_map_t data_3 = macro_f_abstruse_map_t_initialize_1(key_3, value_3);
+
+  f_abstruse_map_t data_array[] = { data_0, data_1, data_2, data_3 };
+
+  const f_number_unsigned_t length = 4;
+
+  {
+    will_return(__wrap_f_memory_array_adjust, true);
+    will_return(__wrap_f_memory_array_adjust, F_status_set_error(F_failure));
+
+    const f_status_t status = f_abstruse_maps_destroy_callback(0, length, (void *) data_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+
+  free((void *) a_dynamic.string);
+}
+
+void test__f_abstruse_maps_destroy_callback__works(void **state) {
+
+  mock_unwrap = 0;
+  mock_unwrap_f_memory = 1;
+
+  f_string_t a_string = "example";
+  f_string_range_t a_range = macro_f_string_range_t_initialize_1(1, 2);
+  f_string_static_t a_static = macro_f_string_static_t_initialize_1(a_string, 0, 7);
+  f_string_dynamic_t a_dynamic = f_string_dynamic_t_initialize;
+
+  f_abstruse_t value_0 = { .type = f_abstruse_range_e, .is.a_range = a_range };
+  f_abstruse_t value_1 = { .type = f_abstruse_string_e, .is.a_string = a_string };
+  f_abstruse_t value_2 = { .type = f_abstruse_dynamic_e, .is.a_dynamic = a_static };
+  f_abstruse_t value_3 = { .type = f_abstruse_dynamic_e, .is.a_dynamic = a_dynamic };
+
+  f_string_dynamic_t key_0 = f_string_static_t_initialize;
+  f_string_dynamic_t key_1 = f_string_static_t_initialize;
+  f_string_dynamic_t key_2 = f_string_static_t_initialize;
+  f_string_dynamic_t key_3 = f_string_static_t_initialize;
+
+  f_abstruse_map_t data_0 = macro_f_abstruse_map_t_initialize_1(key_0, value_0);
+  f_abstruse_map_t data_1 = macro_f_abstruse_map_t_initialize_1(key_1, value_1);
+  f_abstruse_map_t data_2 = macro_f_abstruse_map_t_initialize_1(key_2, value_2);
+  f_abstruse_map_t data_3 = macro_f_abstruse_map_t_initialize_1(key_3, value_3);
+
+  f_abstruse_map_t data_array[] = { data_0, data_1, data_2, data_3 };
+
+  const f_number_unsigned_t length = 4;
+
+  f_abstruse_maps_t datas = macro_f_abstruse_maps_t_initialize_2(data_array, length);
+
+  {
+    f_status_t status = f_string_append("key_0", 5, &datas.array[0].key);
+    assert_int_equal(status, F_okay);
+
+    status = f_string_append("key_1", 5, &datas.array[1].key);
+    assert_int_equal(status, F_okay);
+
+    status = f_string_append("key_2", 5, &datas.array[2].key);
+    assert_int_equal(status, F_okay);
+
+    status = f_string_append("key_3", 5, &datas.array[3].key);
+    assert_int_equal(status, F_okay);
+
+    status = f_string_append("a", 1, &datas.array[3].value.is.a_dynamic);
+    assert_int_equal(status, F_okay);
+  }
+
+  {
+    const f_status_t status = f_abstruse_maps_destroy_callback(0, length, (void *) datas.array);
+
+    assert_int_equal(status, F_okay);
+
+    assert_int_equal(datas.array[0].key.size, 0);
+    assert_int_equal(datas.array[1].key.size, 0);
+    assert_int_equal(datas.array[2].key.size, 0);
+
+    assert_int_equal(datas.array[3].key.size, 0);
+    assert_int_equal(datas.array[3].value.is.a_dynamic.size, 0);
+  }
+
+  free((void *) key_0.string);
+  free((void *) key_1.string);
+  free((void *) key_2.string);
+  free((void *) key_3.string);
+  free((void *) a_dynamic.string);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_abstruse/tests/unit/c/test-abstruse-maps_destroy_callback.h b/level_0/f_abstruse/tests/unit/c/test-abstruse-maps_destroy_callback.h
new file mode 100644 (file)
index 0000000..8005562
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Abstruse
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the abstract project.
+ */
+#ifndef _TEST__F_abstruse__maps_destroy_callback
+#define _TEST__F_abstruse__maps_destroy_callback
+
+/**
+ * Test that the function fails.
+ *
+ * @see f_abstruse_maps_destroy_callback()
+ */
+extern void test__f_abstruse_maps_destroy_callback__fails(void **state);
+
+/**
+ * Test that the function works.
+ *
+ * @see f_abstruse_maps_destroy_callback()
+ */
+extern void test__f_abstruse_maps_destroy_callback__works(void **state);
+
+#endif // _TEST__F_abstruse__maps_destroy_callback
diff --git a/level_0/f_abstruse/tests/unit/c/test-abstruse-mapss_delete_callback.c b/level_0/f_abstruse/tests/unit/c/test-abstruse-mapss_delete_callback.c
new file mode 100644 (file)
index 0000000..bd4b58d
--- /dev/null
@@ -0,0 +1,85 @@
+#include "test-abstruse.h"
+#include "test-abstruse-mapss_delete_callback.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_abstruse_mapss_delete_callback__fails(void **state) {
+
+  mock_unwrap = 0;
+  mock_unwrap_f_memory = 0;
+
+  f_string_t a_string = "example";
+  f_string_range_t a_range = macro_f_string_range_t_initialize_1(1, 2);
+  f_string_static_t a_static = macro_f_string_static_t_initialize_1(a_string, 0, 7);
+  f_string_dynamic_t a_dynamic = f_string_dynamic_t_initialize;
+
+  f_abstruse_t value_0 = { .type = f_abstruse_range_e, .is.a_range = a_range };
+  f_abstruse_t value_1 = { .type = f_abstruse_string_e, .is.a_string = a_string };
+  f_abstruse_t value_2 = { .type = f_abstruse_dynamic_e, .is.a_dynamic = a_static };
+  f_abstruse_t value_3 = { .type = f_abstruse_dynamic_e, .is.a_dynamic = a_dynamic };
+
+  f_string_static_t key_0 = macro_f_string_static_t_initialize_2("key_0", 5);
+  f_string_static_t key_1 = macro_f_string_static_t_initialize_2("key_1", 5);
+  f_string_static_t key_2 = macro_f_string_static_t_initialize_2("key_2", 5);
+  f_string_static_t key_3 = macro_f_string_static_t_initialize_2("key_3", 5);
+
+  f_abstruse_map_t data_0 = macro_f_abstruse_map_t_initialize_1(key_0, value_0);
+  f_abstruse_map_t data_1 = macro_f_abstruse_map_t_initialize_1(key_1, value_1);
+  f_abstruse_map_t data_2 = macro_f_abstruse_map_t_initialize_1(key_2, value_2);
+  f_abstruse_map_t data_3 = macro_f_abstruse_map_t_initialize_1(key_3, value_3);
+
+  f_abstruse_map_t data_array[] = { data_0, data_1, data_2, data_3 };
+
+  f_abstruse_maps_t datas = { .array = data_array, .used = 1, .size = 1 };
+  f_abstruse_maps_t datas_array[] = { datas };
+
+  {
+    will_return(__wrap_f_memory_array_resize, true);
+    will_return(__wrap_f_memory_array_resize, F_status_set_error(F_failure));
+
+    const f_status_t status = f_abstruse_mapss_delete_callback(0, 1, (void *) datas_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+}
+
+void test__f_abstruse_mapss_delete_callback__works(void **state) {
+
+  mock_unwrap = 0;
+  mock_unwrap_f_memory = 1;
+
+  const f_number_unsigned_t length = 1;
+
+  f_abstruse_mapss_t datass = f_abstruse_mapss_t_initialize;
+
+  {
+    f_status_t status = f_memory_array_resize(length, sizeof(f_abstruse_maps_t), (void **) &datass.array, &datass.used, &datass.size);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_array_resize(1, sizeof(f_abstruse_map_t), (void **) &datass.array[0].array, &datass.array[0].used, &datass.array[0].size);
+    assert_int_equal(status, F_okay);
+
+    status = f_string_append("key_0", 5, &datass.array[0].array[0].key);
+    assert_int_equal(status, F_okay);
+
+    status = f_string_append("a", 1, &datass.array[0].array[0].value.is.a_dynamic);
+    assert_int_equal(status, F_okay);
+
+    datass.array[0].array[0].value.type = f_abstruse_dynamic_e;
+  }
+
+  {
+    const f_status_t status = f_abstruse_mapss_delete_callback(0, length, (void *) datass.array);
+
+    assert_int_equal(status, F_okay);
+    assert_int_equal(datass.array[0].size, 0);
+  }
+
+  free((void *) datass.array);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_abstruse/tests/unit/c/test-abstruse-mapss_delete_callback.h b/level_0/f_abstruse/tests/unit/c/test-abstruse-mapss_delete_callback.h
new file mode 100644 (file)
index 0000000..0712dff
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Abstruse
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the abstract project.
+ */
+#ifndef _TEST__F_abstruse__mapss_delete_callback
+#define _TEST__F_abstruse__mapss_delete_callback
+
+/**
+ * Test that the function fails.
+ *
+ * @see f_abstruse_mapss_delete_callback()
+ */
+extern void test__f_abstruse_mapss_delete_callback__fails(void **state);
+
+/**
+ * Test that the function works.
+ *
+ * @see f_abstruse_mapss_delete_callback()
+ */
+extern void test__f_abstruse_mapss_delete_callback__works(void **state);
+
+#endif // _TEST__F_abstruse__mapss_delete_callback
diff --git a/level_0/f_abstruse/tests/unit/c/test-abstruse-mapss_destroy_callback.c b/level_0/f_abstruse/tests/unit/c/test-abstruse-mapss_destroy_callback.c
new file mode 100644 (file)
index 0000000..9104f24
--- /dev/null
@@ -0,0 +1,85 @@
+#include "test-abstruse.h"
+#include "test-abstruse-mapss_destroy_callback.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_abstruse_mapss_destroy_callback__fails(void **state) {
+
+  mock_unwrap = 0;
+  mock_unwrap_f_memory = 0;
+
+  f_string_t a_string = "example";
+  f_string_range_t a_range = macro_f_string_range_t_initialize_1(1, 2);
+  f_string_static_t a_static = macro_f_string_static_t_initialize_1(a_string, 0, 7);
+  f_string_dynamic_t a_dynamic = f_string_dynamic_t_initialize;
+
+  f_abstruse_t value_0 = { .type = f_abstruse_range_e, .is.a_range = a_range };
+  f_abstruse_t value_1 = { .type = f_abstruse_string_e, .is.a_string = a_string };
+  f_abstruse_t value_2 = { .type = f_abstruse_dynamic_e, .is.a_dynamic = a_static };
+  f_abstruse_t value_3 = { .type = f_abstruse_dynamic_e, .is.a_dynamic = a_dynamic };
+
+  f_string_static_t key_0 = macro_f_string_static_t_initialize_2("key_0", 5);
+  f_string_static_t key_1 = macro_f_string_static_t_initialize_2("key_1", 5);
+  f_string_static_t key_2 = macro_f_string_static_t_initialize_2("key_2", 5);
+  f_string_static_t key_3 = macro_f_string_static_t_initialize_2("key_3", 5);
+
+  f_abstruse_map_t data_0 = macro_f_abstruse_map_t_initialize_1(key_0, value_0);
+  f_abstruse_map_t data_1 = macro_f_abstruse_map_t_initialize_1(key_1, value_1);
+  f_abstruse_map_t data_2 = macro_f_abstruse_map_t_initialize_1(key_2, value_2);
+  f_abstruse_map_t data_3 = macro_f_abstruse_map_t_initialize_1(key_3, value_3);
+
+  f_abstruse_map_t data_array[] = { data_0, data_1, data_2, data_3 };
+
+  f_abstruse_maps_t datas = { .array = data_array, .used = 1, .size = 1 };
+  f_abstruse_maps_t datas_array[] = { datas };
+
+  {
+    will_return(__wrap_f_memory_array_adjust, true);
+    will_return(__wrap_f_memory_array_adjust, F_status_set_error(F_failure));
+
+    const f_status_t status = f_abstruse_mapss_destroy_callback(0, 1, (void *) datas_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+}
+
+void test__f_abstruse_mapss_destroy_callback__works(void **state) {
+
+  mock_unwrap = 0;
+  mock_unwrap_f_memory = 1;
+
+  const f_number_unsigned_t length = 1;
+
+  f_abstruse_mapss_t datass = f_abstruse_mapss_t_initialize;
+
+  {
+    f_status_t status = f_memory_array_resize(length, sizeof(f_abstruse_maps_t), (void **) &datass.array, &datass.used, &datass.size);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_array_resize(1, sizeof(f_abstruse_map_t), (void **) &datass.array[0].array, &datass.array[0].used, &datass.array[0].size);
+    assert_int_equal(status, F_okay);
+
+    status = f_string_append("key_0", 5, &datass.array[0].array[0].key);
+    assert_int_equal(status, F_okay);
+
+    status = f_string_append("a", 1, &datass.array[0].array[0].value.is.a_dynamic);
+    assert_int_equal(status, F_okay);
+
+    datass.array[0].array[0].value.type = f_abstruse_dynamic_e;
+  }
+
+  {
+    const f_status_t status = f_abstruse_mapss_destroy_callback(0, length, (void *) datass.array);
+
+    assert_int_equal(status, F_okay);
+    assert_int_equal(datass.array[0].size, 0);
+  }
+
+  free((void *) datass.array);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_abstruse/tests/unit/c/test-abstruse-mapss_destroy_callback.h b/level_0/f_abstruse/tests/unit/c/test-abstruse-mapss_destroy_callback.h
new file mode 100644 (file)
index 0000000..6b9de5b
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Abstruse
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the abstract project.
+ */
+#ifndef _TEST__F_abstruse__mapss_destroy_callback
+#define _TEST__F_abstruse__mapss_destroy_callback
+
+/**
+ * Test that the function fails.
+ *
+ * @see f_abstruse_mapss_destroy_callback()
+ */
+extern void test__f_abstruse_mapss_destroy_callback__fails(void **state);
+
+/**
+ * Test that the function works.
+ *
+ * @see f_abstruse_mapss_destroy_callback()
+ */
+extern void test__f_abstruse_mapss_destroy_callback__works(void **state);
+
+#endif // _TEST__F_abstruse__mapss_destroy_callback
diff --git a/level_0/f_abstruse/tests/unit/c/test-abstruse-s_delete_callback.c b/level_0/f_abstruse/tests/unit/c/test-abstruse-s_delete_callback.c
new file mode 100644 (file)
index 0000000..4153479
--- /dev/null
@@ -0,0 +1,80 @@
+#include "test-abstruse.h"
+#include "test-abstruse-s_delete_callback.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_abstruse_s_delete_callback__fails(void **state) {
+
+  mock_unwrap = 0;
+  mock_unwrap_f_memory = 0;
+
+  f_string_t a_string = "example";
+  f_string_range_t a_range = macro_f_string_range_t_initialize_1(1, 2);
+  f_string_static_t a_static = macro_f_string_static_t_initialize_1(a_string, 0, 7);
+  f_string_dynamic_t a_dynamic = f_string_dynamic_t_initialize;
+
+  f_abstruse_t data_0 = { .type = f_abstruse_range_e, .is.a_range = a_range };
+  f_abstruse_t data_1 = { .type = f_abstruse_string_e, .is.a_string = a_string };
+  f_abstruse_t data_2 = { .type = f_abstruse_dynamic_e, .is.a_dynamic = a_static };
+  f_abstruse_t data_3 = { .type = f_abstruse_dynamic_e, .is.a_dynamic = a_dynamic };
+  f_abstruse_t data_array[] = { data_0, data_1, data_2, data_3 };
+
+  const f_number_unsigned_t length = 4;
+
+  {
+    const f_status_t status = f_string_append("a", 1, &data_array[3].is.a_dynamic);
+    assert_int_equal(status, F_okay);
+  }
+
+  {
+    will_return(__wrap_f_memory_array_resize, true);
+    will_return(__wrap_f_memory_array_resize, F_status_set_error(F_failure));
+
+    const f_status_t status = f_abstruses_delete_callback(0, length, (void *) data_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+
+  free((void *) data_array[3].is.a_dynamic.string);
+}
+
+void test__f_abstruse_s_delete_callback__works(void **state) {
+
+  mock_unwrap = 0;
+  mock_unwrap_f_memory = 1;
+
+  f_string_t a_string = "example";
+  f_string_range_t a_range = macro_f_string_range_t_initialize_1(1, 2);
+  f_string_static_t a_static = macro_f_string_static_t_initialize_1(a_string, 0, 7);
+  f_string_dynamic_t a_dynamic = f_string_dynamic_t_initialize;
+
+  f_abstruse_t data_0 = { .type = f_abstruse_range_e, .is.a_range = a_range };
+  f_abstruse_t data_1 = { .type = f_abstruse_string_e, .is.a_string = a_string };
+  f_abstruse_t data_2 = { .type = f_abstruse_dynamic_e, .is.a_dynamic = a_static };
+  f_abstruse_t data_3 = { .type = f_abstruse_dynamic_e, .is.a_dynamic = a_dynamic };
+  f_abstruse_t data_array[] = { data_0, data_1, data_2, data_3 };
+
+  const f_number_unsigned_t length = 4;
+
+  f_abstruses_t datas = macro_f_abstruses_t_initialize_2(data_array, length);
+
+  {
+    const f_status_t status = f_string_append("a", 1, &datas.array[3].is.a_dynamic);
+    assert_int_equal(status, F_okay);
+  }
+
+  {
+    const f_status_t status = f_abstruses_delete_callback(0, length, (void *) datas.array);
+
+    assert_int_equal(status, F_okay);
+    assert_int_equal(datas.array[3].is.a_dynamic.size, 0);
+  }
+
+  free((void *) datas.array[3].is.a_dynamic.string);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_abstruse/tests/unit/c/test-abstruse-s_delete_callback.h b/level_0/f_abstruse/tests/unit/c/test-abstruse-s_delete_callback.h
new file mode 100644 (file)
index 0000000..0ff9040
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Abstruse
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the abstract project.
+ */
+#ifndef _TEST__F_abstruse__s_delete_callback
+#define _TEST__F_abstruse__s_delete_callback
+
+/**
+ * Test that the function fails.
+ *
+ * @see f_abstruse_s_delete_callback()
+ */
+extern void test__f_abstruse_s_delete_callback__fails(void **state);
+
+/**
+ * Test that the function works.
+ *
+ * @see f_abstruse_s_delete_callback()
+ */
+extern void test__f_abstruse_s_delete_callback__works(void **state);
+
+#endif // _TEST__F_abstruse__s_delete_callback
diff --git a/level_0/f_abstruse/tests/unit/c/test-abstruse-s_destroy_callback.c b/level_0/f_abstruse/tests/unit/c/test-abstruse-s_destroy_callback.c
new file mode 100644 (file)
index 0000000..4481c89
--- /dev/null
@@ -0,0 +1,80 @@
+#include "test-abstruse.h"
+#include "test-abstruse-s_destroy_callback.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_abstruse_s_destroy_callback__fails(void **state) {
+
+  mock_unwrap = 0;
+  mock_unwrap_f_memory = 0;
+
+  f_string_t a_string = "example";
+  f_string_range_t a_range = macro_f_string_range_t_initialize_1(1, 2);
+  f_string_static_t a_static = macro_f_string_static_t_initialize_1(a_string, 0, 7);
+  f_string_dynamic_t a_dynamic = f_string_dynamic_t_initialize;
+
+  f_abstruse_t data_0 = { .type = f_abstruse_range_e, .is.a_range = a_range };
+  f_abstruse_t data_1 = { .type = f_abstruse_string_e, .is.a_string = a_string };
+  f_abstruse_t data_2 = { .type = f_abstruse_dynamic_e, .is.a_dynamic = a_static };
+  f_abstruse_t data_3 = { .type = f_abstruse_dynamic_e, .is.a_dynamic = a_dynamic };
+  f_abstruse_t data_array[] = { data_0, data_1, data_2, data_3 };
+
+  const f_number_unsigned_t length = 4;
+
+  {
+    const f_status_t status = f_string_append("a", 1, &data_array[3].is.a_dynamic);
+    assert_int_equal(status, F_okay);
+  }
+
+  {
+    will_return(__wrap_f_memory_array_adjust, true);
+    will_return(__wrap_f_memory_array_adjust, F_status_set_error(F_failure));
+
+    const f_status_t status = f_abstruses_destroy_callback(0, length, (void *) data_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+
+  free((void *) data_array[3].is.a_dynamic.string);
+}
+
+void test__f_abstruse_s_destroy_callback__works(void **state) {
+
+  mock_unwrap = 0;
+  mock_unwrap_f_memory = 1;
+
+  f_string_t a_string = "example";
+  f_string_range_t a_range = macro_f_string_range_t_initialize_1(1, 2);
+  f_string_static_t a_static = macro_f_string_static_t_initialize_1(a_string, 0, 7);
+  f_string_dynamic_t a_dynamic = f_string_dynamic_t_initialize;
+
+  f_abstruse_t data_0 = { .type = f_abstruse_range_e, .is.a_range = a_range };
+  f_abstruse_t data_1 = { .type = f_abstruse_string_e, .is.a_string = a_string };
+  f_abstruse_t data_2 = { .type = f_abstruse_dynamic_e, .is.a_dynamic = a_static };
+  f_abstruse_t data_3 = { .type = f_abstruse_dynamic_e, .is.a_dynamic = a_dynamic };
+  f_abstruse_t data_array[] = { data_0, data_1, data_2, data_3 };
+
+  const f_number_unsigned_t length = 4;
+
+  f_abstruses_t datas = macro_f_abstruses_t_initialize_2(data_array, length);
+
+  {
+    const f_status_t status = f_string_append("a", 1, &datas.array[3].is.a_dynamic);
+    assert_int_equal(status, F_okay);
+  }
+
+  {
+    const f_status_t status = f_abstruses_destroy_callback(0, length, (void *) datas.array);
+
+    assert_int_equal(status, F_okay);
+    assert_int_equal(datas.array[3].is.a_dynamic.size, 0);
+  }
+
+  free((void *) datas.array[3].is.a_dynamic.string);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_abstruse/tests/unit/c/test-abstruse-s_destroy_callback.h b/level_0/f_abstruse/tests/unit/c/test-abstruse-s_destroy_callback.h
new file mode 100644 (file)
index 0000000..25f7123
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Abstruse
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the abstract project.
+ */
+#ifndef _TEST__F_abstruse__s_destroy_callback
+#define _TEST__F_abstruse__s_destroy_callback
+
+/**
+ * Test that the function fails.
+ *
+ * @see f_abstruse_s_destroy_callback()
+ */
+extern void test__f_abstruse_s_destroy_callback__fails(void **state);
+
+/**
+ * Test that the function works.
+ *
+ * @see f_abstruse_s_destroy_callback()
+ */
+extern void test__f_abstruse_s_destroy_callback__works(void **state);
+
+#endif // _TEST__F_abstruse__s_destroy_callback
diff --git a/level_0/f_abstruse/tests/unit/c/test-abstruse-ss_delete_callback.c b/level_0/f_abstruse/tests/unit/c/test-abstruse-ss_delete_callback.c
new file mode 100644 (file)
index 0000000..4e112da
--- /dev/null
@@ -0,0 +1,71 @@
+#include "test-abstruse.h"
+#include "test-abstruse-ss_delete_callback.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_abstruse_ss_delete_callback__fails(void **state) {
+
+  mock_unwrap = 0;
+  mock_unwrap_f_memory = 0;
+
+  f_string_t a_string = "example";
+  f_string_range_t a_range = macro_f_string_range_t_initialize_1(1, 2);
+  f_string_static_t a_static = macro_f_string_static_t_initialize_1(a_string, 0, 7);
+  f_string_dynamic_t a_dynamic = f_string_dynamic_t_initialize;
+
+  f_abstruse_t data_0 = { .type = f_abstruse_range_e, .is.a_range = a_range };
+  f_abstruse_t data_1 = { .type = f_abstruse_string_e, .is.a_string = a_string };
+  f_abstruse_t data_2 = { .type = f_abstruse_dynamic_e, .is.a_dynamic = a_static };
+  f_abstruse_t data_3 = { .type = f_abstruse_dynamic_e, .is.a_dynamic = a_dynamic };
+  f_abstruse_t data_array[] = { data_0, data_1, data_2, data_3 };
+
+  f_abstruses_t datas = { .array = data_array, .used = 1, .size = 1 };
+  f_abstruses_t datas_array[] = { datas };
+
+  {
+    will_return(__wrap_f_memory_array_resize, true);
+    will_return(__wrap_f_memory_array_resize, F_status_set_error(F_failure));
+
+    const f_status_t status = f_abstrusess_delete_callback(0, 1, (void *) datas_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+}
+
+void test__f_abstruse_ss_delete_callback__works(void **state) {
+
+  mock_unwrap = 0;
+  mock_unwrap_f_memory = 1;
+
+  const f_number_unsigned_t length = 1;
+
+  f_abstrusess_t datass = f_abstrusess_t_initialize;
+
+  {
+    f_status_t status = f_memory_array_resize(length, sizeof(f_abstruse_t), (void **) &datass.array, &datass.used, &datass.size);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_array_resize(1, sizeof(f_abstruse_t), (void **) &datass.array[0].array, &datass.array[0].used, &datass.array[0].size);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_array_resize(1, sizeof(f_string_t), (void **) &datass.array[0].array[0].is.a_dynamic, &datass.array[0].array[0].is.a_dynamic.used, &datass.array[0].array[0].is.a_dynamic.size);
+    assert_int_equal(status, F_okay);
+
+    datass.array[0].array[0].type = f_abstruse_dynamic_e;
+  }
+
+  {
+    const f_status_t status = f_abstrusess_delete_callback(0, length, (void *) datass.array);
+
+    assert_int_equal(status, F_okay);
+    assert_int_equal(datass.array[0].size, 0);
+  }
+
+  free((void *) datass.array);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_abstruse/tests/unit/c/test-abstruse-ss_delete_callback.h b/level_0/f_abstruse/tests/unit/c/test-abstruse-ss_delete_callback.h
new file mode 100644 (file)
index 0000000..8058151
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Abstruse
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the abstract project.
+ */
+#ifndef _TEST__F_abstruse__ss_delete_callback
+#define _TEST__F_abstruse__ss_delete_callback
+
+/**
+ * Test that the function fails.
+ *
+ * @see f_abstruse_ss_delete_callback()
+ */
+extern void test__f_abstruse_ss_delete_callback__fails(void **state);
+
+/**
+ * Test that the function works.
+ *
+ * @see f_abstruse_ss_delete_callback()
+ */
+extern void test__f_abstruse_ss_delete_callback__works(void **state);
+
+#endif // _TEST__F_abstruse__ss_delete_callback
diff --git a/level_0/f_abstruse/tests/unit/c/test-abstruse-ss_destroy_callback.c b/level_0/f_abstruse/tests/unit/c/test-abstruse-ss_destroy_callback.c
new file mode 100644 (file)
index 0000000..5b5e47d
--- /dev/null
@@ -0,0 +1,71 @@
+#include "test-abstruse.h"
+#include "test-abstruse-ss_destroy_callback.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_abstruse_ss_destroy_callback__fails(void **state) {
+
+  mock_unwrap = 0;
+  mock_unwrap_f_memory = 0;
+
+  f_string_t a_string = "example";
+  f_string_range_t a_range = macro_f_string_range_t_initialize_1(1, 2);
+  f_string_static_t a_static = macro_f_string_static_t_initialize_1(a_string, 0, 7);
+  f_string_dynamic_t a_dynamic = f_string_dynamic_t_initialize;
+
+  f_abstruse_t data_0 = { .type = f_abstruse_range_e, .is.a_range = a_range };
+  f_abstruse_t data_1 = { .type = f_abstruse_string_e, .is.a_string = a_string };
+  f_abstruse_t data_2 = { .type = f_abstruse_dynamic_e, .is.a_dynamic = a_static };
+  f_abstruse_t data_3 = { .type = f_abstruse_dynamic_e, .is.a_dynamic = a_dynamic };
+  f_abstruse_t data_array[] = { data_0, data_1, data_2, data_3 };
+
+  f_abstruses_t datas = { .array = data_array, .used = 1, .size = 1 };
+  f_abstruses_t datas_array[] = { datas };
+
+  {
+    will_return(__wrap_f_memory_array_adjust, true);
+    will_return(__wrap_f_memory_array_adjust, F_status_set_error(F_failure));
+
+    const f_status_t status = f_abstrusess_destroy_callback(0, 1, (void *) datas_array);
+
+    assert_int_equal(status, F_status_set_error(F_failure));
+  }
+}
+
+void test__f_abstruse_ss_destroy_callback__works(void **state) {
+
+  mock_unwrap = 0;
+  mock_unwrap_f_memory = 1;
+
+  const f_number_unsigned_t length = 1;
+
+  f_abstrusess_t datass = f_abstrusess_t_initialize;
+
+  {
+    f_status_t status = f_memory_array_resize(length, sizeof(f_abstruses_t), (void **) &datass.array, &datass.used, &datass.size);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_array_resize(1, sizeof(f_abstruse_t), (void **) &datass.array[0].array, &datass.array[0].used, &datass.array[0].size);
+    assert_int_equal(status, F_okay);
+
+    status = f_memory_array_resize(1, sizeof(f_string_t), (void **) &datass.array[0].array[0].is.a_dynamic, &datass.array[0].array[0].is.a_dynamic.used, &datass.array[0].array[0].is.a_dynamic.size);
+    assert_int_equal(status, F_okay);
+
+    datass.array[0].array[0].type = f_abstruse_dynamic_e;
+  }
+
+  {
+    const f_status_t status = f_abstrusess_destroy_callback(0, length, (void *) datass.array);
+
+    assert_int_equal(status, F_okay);
+    assert_int_equal(datass.array[0].size, 0);
+  }
+
+  free((void *) datass.array);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_abstruse/tests/unit/c/test-abstruse-ss_destroy_callback.h b/level_0/f_abstruse/tests/unit/c/test-abstruse-ss_destroy_callback.h
new file mode 100644 (file)
index 0000000..75ca862
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Abstruse
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the abstract project.
+ */
+#ifndef _TEST__F_abstruse__ss_destroy_callback
+#define _TEST__F_abstruse__ss_destroy_callback
+
+/**
+ * Test that the function fails.
+ *
+ * @see f_abstruse_ss_destroy_callback()
+ */
+extern void test__f_abstruse_ss_destroy_callback__fails(void **state);
+
+/**
+ * Test that the function works.
+ *
+ * @see f_abstruse_ss_destroy_callback()
+ */
+extern void test__f_abstruse_ss_destroy_callback__works(void **state);
+
+#endif // _TEST__F_abstruse__ss_destroy_callback
diff --git a/level_0/f_abstruse/tests/unit/c/test-abstruse.c b/level_0/f_abstruse/tests/unit/c/test-abstruse.c
new file mode 100644 (file)
index 0000000..2dbde80
--- /dev/null
@@ -0,0 +1,60 @@
+#include "test-abstruse.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int setup(void **state) {
+
+  return 0;
+}
+
+int setdown(void **state) {
+
+  errno = 0;
+
+  return 0;
+}
+
+int main(void) {
+
+  const struct CMUnitTest tests[] = {
+    cmocka_unit_test(test__f_abstruse_s_delete_callback__fails),
+    cmocka_unit_test(test__f_abstruse_s_destroy_callback__fails),
+    cmocka_unit_test(test__f_abstruse_ss_destroy_callback__fails),
+    cmocka_unit_test(test__f_abstruse_ss_delete_callback__fails),
+
+    cmocka_unit_test(test__f_abstruse_s_delete_callback__works),
+    cmocka_unit_test(test__f_abstruse_s_destroy_callback__works),
+    cmocka_unit_test(test__f_abstruse_ss_delete_callback__works),
+    cmocka_unit_test(test__f_abstruse_ss_destroy_callback__works),
+
+    cmocka_unit_test(test__f_abstruse_maps_delete_callback__fails),
+    cmocka_unit_test(test__f_abstruse_maps_destroy_callback__fails),
+    cmocka_unit_test(test__f_abstruse_mapss_destroy_callback__fails),
+    cmocka_unit_test(test__f_abstruse_mapss_delete_callback__fails),
+
+    cmocka_unit_test(test__f_abstruse_maps_delete_callback__works),
+    cmocka_unit_test(test__f_abstruse_maps_destroy_callback__works),
+    cmocka_unit_test(test__f_abstruse_mapss_delete_callback__works),
+    cmocka_unit_test(test__f_abstruse_mapss_destroy_callback__works),
+
+    #ifndef _di_level_0_parameter_checking_
+      // f_abstruse_maps_destroy_callback() doesn't use parameter checking.
+      // f_abstruse_maps_delete_callback() doesn't use parameter checking.
+      // f_abstruse_mapss_destroy_callback() doesn't use parameter checking.
+      // f_abstruse_mapss_delete_callback() doesn't use parameter checking.
+
+      // f_abstruse_s_destroy_callback() doesn't use parameter checking.
+      // f_abstruse_s_delete_callback() doesn't use parameter checking.
+      // f_abstruse_ss_destroy_callback() doesn't use parameter checking.
+      // f_abstruse_ss_delete_callback() doesn't use parameter checking.
+    #endif // _di_level_0_parameter_checking_
+  };
+
+  return cmocka_run_group_tests(tests, setup, setdown);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_abstruse/tests/unit/c/test-abstruse.h b/level_0/f_abstruse/tests/unit/c/test-abstruse.h
new file mode 100644 (file)
index 0000000..d0e7e61
--- /dev/null
@@ -0,0 +1,79 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Abstruse
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the abstruse project.
+ */
+#ifndef _TEST__F_abstruse_h
+#define _TEST__F_abstruse_h
+
+// Libc includes.
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+
+// cmocka includes.
+#include <cmocka.h>
+
+// FLL-0 includes.
+#include <fll/level_0/abstruse.h>
+
+// Mock includes.
+#include "mock-abstruse.h"
+
+// Test includes.
+#include "test-abstruse-maps_delete_callback.h"
+#include "test-abstruse-maps_destroy_callback.h"
+#include "test-abstruse-mapss_delete_callback.h"
+#include "test-abstruse-mapss_destroy_callback.h"
+#include "test-abstruse-s_delete_callback.h"
+#include "test-abstruse-s_destroy_callback.h"
+#include "test-abstruse-ss_delete_callback.h"
+#include "test-abstruse-ss_destroy_callback.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform any setup operations.
+ *
+ * @param state
+ *   The test state.
+ *
+ * @return
+ *   The status of this function, where 0 means success.
+ */
+extern int setup(void **state);
+
+/**
+ * Peform any setdown operations.
+ *
+ * @param state
+ *   The test state.
+ *
+ * @return
+ *   The status of this function, where 0 means success.
+ */
+extern int setdown(void **state);
+
+/**
+ * Run all tests.
+ *
+ * @return
+ *   The final result of the tests.
+ *
+ * @see cmocka_run_group_tests()
+ * @see cmocka_unit_test()
+ */
+extern int main(void);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _TEST__F_abstruse_h