]> Kevux Git Server - fll/commitdiff
Progress: Continue adding FSS Payload processing code.
authorKevin Day <thekevinday@gmail.com>
Fri, 19 Jan 2024 03:54:52 +0000 (21:54 -0600)
committerKevin Day <thekevinday@gmail.com>
Fri, 19 Jan 2024 03:54:52 +0000 (21:54 -0600)
This also adds the beginnings of unit tests for the fl_fss project, specifically for the fl_fss_payload_header_map() function.
The tests for fl_fss_payload_header_map() will be rather complex and so I will likely break the tests for fl_fss_payload_header_map() into multiple files.

15 files changed:
level_0/f_abstruse/c/abstruse/map.h
level_0/f_abstruse/tests/unit/c/mock-abstruse.h
level_0/f_fss/c/fss/payload.h
level_1/fl_fss/c/fss/payload.c
level_1/fl_fss/c/fss/payload.h
level_1/fl_fss/c/fss/payload/define.h
level_1/fl_fss/c/fss/payload/type.h
level_1/fl_fss/c/fss/private-payload.c
level_1/fl_fss/c/fss/private-payload.h
level_1/fl_fss/data/build/dependencies-tests [new file with mode: 0644]
level_1/fl_fss/data/build/settings-tests [new file with mode: 0644]
level_1/fl_fss/tests/unit/c/test-fss-payload_header_map.c [new file with mode: 0644]
level_1/fl_fss/tests/unit/c/test-fss-payload_header_map.h [new file with mode: 0644]
level_1/fl_fss/tests/unit/c/test-fss.c [new file with mode: 0644]
level_1/fl_fss/tests/unit/c/test-fss.h [new file with mode: 0644]

index dce5e8dda60dad1be67ac5ac88ea8f300ea5eed2..39e1f5a15dec79adb939c942881c68a619718fa5 100644 (file)
@@ -54,7 +54,7 @@ extern "C" {
     f_number_unsigned_t used;
   } f_abstruse_maps_t;
 
-  #define f_abstruses_t_initialize { 0, 0, 0 }
+  #define f_abstruse_maps_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 }
index 4dcb9f0e8a3109f19de14a108d130087bd04432c..f1458653b19f06b3c3de7230b0a3ea69a5c45e32 100644 (file)
@@ -1,7 +1,7 @@
 /**
  * FLL - Level 0
  *
- * Project: IKI
+ * Project: Abstruse
  * API Version: 0.7
  * Licenses: lgpl-2.1-or-later
  *
index 906e08b7064f815533c491d9342be6b210c0daf4..6992f39d035bdd3256c3925516581faa6e5dcde7 100644 (file)
@@ -22,53 +22,57 @@ extern "C" {
  * When both *_split_range_e and *_split_ranges_e are set, then both the individual ranges and the range sets are split into separate Content (separate columns).
  *
  * Values of f_fss_payload_header_map_flag_*_e:
- *   - none:           No flag set.
- *   - join_digits:    Types of digits are combined into a single Content (single column).
- *   - join_dynamics:  Types of dynamics are combined into a single Content (single column).
- *   - join_map:       Types of map are combined into a single Content (single column), example: "key1 value1" "key2 value2" as opposed to "key1" "value1" "key2" "value2".
- *   - join_maps:      Types of maps are combined into a single Content (single column), example: "key1 value1 key2 value2" as opposed to "key1 value1" "key2 value2" or "key1" "value1" "key2" "value2".
- *   - join_range:     Types of range are combined into a single Content (single column).
- *   - join_ranges:    Types of ranges are combined into a single Content (single column) (this effectively forces join_range to always be treated as set).
- *   - join_strings:   Types of strings are combined into a single Content (single column).
- *   - join_triple:    Types of triple are combined into a single Content (single column), example: "a b c" "d e f" as opposed to "a" "b" "c" "d" "e" "f".
- *   - join_triples:   Types of triples are combined into a single Content (single column), example: "a b c d e f" as opposed to "a b c" "d e f" or "a" "b" "c" "d" "e" "f".
- *   - null:           When the key has no header Content (header value.used is 0), still add the Object (header key) (When this is not set then the Object (header key) is not added).
- *   - null_dynamic:   Types of dynamic and dynamics have empty strings (such as "") added for NULL values (used is 0).
- *   - null_map_key:   Types of map and maps has empty strings (such as "") added for NULL values (used is 0) for the map key.
- *   - null_map_value: Types of map and maps has empty strings (such as "") added for NULL values (used is 0) for the map value.
- *   - null_maps:      Types of dynamic and dynamics have empty strings (such as "") added for when null_map_key and null_map_value are not set and both map key and map value have NULL values (used is 0).
- *   - null_string:    Types of string and strings have empty strings (such as "") for NULL values.
- *   - null_triple_a:  Types of triple and triples has empty strings (such as "") added for NULL values (used is 0) for the "a" property.
- *   - null_triple_b:  Types of triple and triples has empty strings (such as "") added for NULL values (used is 0) for the "b" property.
- *   - null_triple_c:  Types of triple and triples has empty strings (such as "") added for NULL values (used is 0) for the "c" property.
- *   - quote_double:   Use double quotes (U+0022) when quoting strings.
- *   - quote_grave:    Use grave (U+0060) when quoting strings.
- *   - quote_single:   Use single quotes (U+0027) when quoting strings.
- *   - last:           This does nothing and is provided to be used as a starting point for anything extending this (there should be a max total of 64 bits allowed).
+ *   - none:                No flag set.
+ *   - join_digits:         Types of digits are combined into a single Content (single column).
+ *   - join_dynamics:       Types of dynamics are combined into a single Content (single column).
+ *   - join_map:            Types of map are combined into a single Content (single column), example: "key1 value1" "key2 value2" as opposed to "key1" "value1" "key2" "value2".
+ *   - join_maps:           Types of maps are combined into a single Content (single column), example: "key1 value1 key2 value2" as opposed to "key1 value1" "key2 value2" or "key1" "value1" "key2" "value2".
+ *   - join_range:          Types of range are combined into a single Content (single column).
+ *   - join_ranges:         Types of ranges are combined into a single Content (single column) (this effectively forces join_range to always be treated as set).
+ *   - join_strings:        Types of strings are combined into a single Content (single column).
+ *   - join_triple:         Types of triple are combined into a single Content (single column), example: "a b c" "d e f" as opposed to "a" "b" "c" "d" "e" "f".
+ *   - join_triples:        Types of triples are combined into a single Content (single column), example: "a b c d e f" as opposed to "a b c" "d e f" or "a" "b" "c" "d" "e" "f".
+ *   - null:                When the key has no header Content (header value.used is 0), still add the Object (header key) (When this is not set then the Object (header key) is not added).
+ *   - null_dynamic:        Types of dynamic and dynamics have empty strings (such as "") added for NULL values (used is 0).
+ *   - null_map_name:       Types of map and maps has empty strings (such as "") added for NULL values (used is 0) for the map key.
+ *   - null_map_value:      Types of map and maps has empty strings (such as "") added for NULL values (used is 0) for the map value.
+ *   - null_map_name_value: An enumeration value representing both null_map_name and null_map_value keys being set.
+ *   - null_maps:           Types of dynamic and dynamics have empty strings (such as "") added for when null_map_key and null_map_value are not set and both map key and map value have NULL values (used is 0).
+ *   - null_string:         Types of string and strings have empty strings (such as "") for NULL values.
+ *   - null_triple_a:       Types of triple and triples has empty strings (such as "") added for NULL values (used is 0) for the "a" property.
+ *   - null_triple_b:       Types of triple and triples has empty strings (such as "") added for NULL values (used is 0) for the "b" property.
+ *   - null_triple_c:       Types of triple and triples has empty strings (such as "") added for NULL values (used is 0) for the "c" property.
+ *   - quote_double:        Use double quotes (U+0022) when quoting strings.
+ *   - quote_grave:         Use grave (U+0060) when quoting strings.
+ *   - quote_single:        Use single quotes (U+0027) when quoting strings.
+ *   - last:                This does nothing and is provided to be used as a starting point for anything extending this (there should be a max total of 64 bits allowed).
  */
 #ifndef _di_f_fss_payload_header_map_flag_e_
   enum {
-    f_fss_payload_header_map_flag_none_e           = 0x0,
-    f_fss_payload_header_map_flag_join_digits_e    = 0x1,
-    f_fss_payload_header_map_flag_join_dynamics_e  = 0x2,
-    f_fss_payload_header_map_flag_join_range_e     = 0x4,
-    f_fss_payload_header_map_flag_join_ranges_e    = 0x8,
-    f_fss_payload_header_map_flag_join_strings_e   = 0x10,
-    f_fss_payload_header_map_flag_join_triple_e    = 0x20,
-    f_fss_payload_header_map_flag_join_triples_e   = 0x40,
-    f_fss_payload_header_map_flag_null_e           = 0x80,
-    f_fss_payload_header_map_flag_null_dynamic_e   = 0x100,
-    f_fss_payload_header_map_flag_null_map_key_e   = 0x200,
-    f_fss_payload_header_map_flag_null_map_value_e = 0x400,
-    f_fss_payload_header_map_flag_null_maps_e      = 0x800,
-    f_fss_payload_header_map_flag_null_triple_a_e  = 0x1000,
-    f_fss_payload_header_map_flag_null_triple_b_e  = 0x2000,
-    f_fss_payload_header_map_flag_null_triple_c_e  = 0x4000,
-    f_fss_payload_header_map_flag_null_string_e    = 0x8000,
-    f_fss_payload_header_map_flag_quote_double_e   = 0x10000,
-    f_fss_payload_header_map_flag_quote_grave_e    = 0x20000,
-    f_fss_payload_header_map_flag_quote_single_e   = 0x40000,
-    f_fss_payload_header_map_flag_last_e           = 0x80000,
+    f_fss_payload_header_map_flag_none_e                = 0x0,
+    f_fss_payload_header_map_flag_join_digits_e         = 0x1,
+    f_fss_payload_header_map_flag_join_dynamics_e       = 0x2,
+    f_fss_payload_header_map_flag_join_map_e            = 0x4,
+    f_fss_payload_header_map_flag_join_maps_e           = 0x8,
+    f_fss_payload_header_map_flag_join_range_e          = 0x10,
+    f_fss_payload_header_map_flag_join_ranges_e         = 0x20,
+    f_fss_payload_header_map_flag_join_strings_e        = 0x40,
+    f_fss_payload_header_map_flag_join_triple_e         = 0x80,
+    f_fss_payload_header_map_flag_join_triples_e        = 0x100,
+    f_fss_payload_header_map_flag_null_e                = 0x200,
+    f_fss_payload_header_map_flag_null_dynamic_e        = 0x400,
+    f_fss_payload_header_map_flag_null_map_name_e       = 0x800,
+    f_fss_payload_header_map_flag_null_map_value_e      = 0x1000,
+    f_fss_payload_header_map_flag_null_map_name_value_e = 0x2000,
+    f_fss_payload_header_map_flag_null_maps_e           = 0x4000,
+    f_fss_payload_header_map_flag_null_triple_a_e       = 0x8000,
+    f_fss_payload_header_map_flag_null_triple_b_e       = 0x10000,
+    f_fss_payload_header_map_flag_null_triple_c_e       = 0x20000,
+    f_fss_payload_header_map_flag_null_string_e         = 0x40000,
+    f_fss_payload_header_map_flag_quote_double_e        = 0x80000,
+    f_fss_payload_header_map_flag_quote_grave_e         = 0x100000,
+    f_fss_payload_header_map_flag_quote_single_e        = 0x200000,
+    f_fss_payload_header_map_flag_last_e                = 0x400000,
   }; // enum
 #endif // _di_f_fss_payload_header_flag_map_e_
 
index b397e812e7e842c70d0c4d761d0b5aa6e81798e2..4974adc8da5df30dacb53d3207653505ed3f2e2d 100644 (file)
@@ -45,13 +45,23 @@ extern "C" {
     internal.j = 0;
     internal.k = 0;
     internal.l = 0;
-    internal.quote = f_fss_payload_header_map_flag_quote_double_e
-      ? f_string_ascii_quote_double_s.string[0]
-      : f_fss_payload_header_map_flag_quote_single_e
-        ? f_string_ascii_quote_single_s.string[0]
-        : f_fss_payload_header_map_flag_quote_grave_e
-          ? f_string_ascii_grave_s.string[0]
-          : 0;
+
+    if (data->flag & f_fss_payload_header_map_flag_quote_double_e) {
+      internal.quote = f_string_ascii_quote_double_s.string[0];
+      internal.quote_null = f_fss_quote_double_null_s;
+    }
+    else if (data->flag & f_fss_payload_header_map_flag_quote_single_e) {
+      internal.quote = f_string_ascii_quote_single_s.string[0];
+      internal.quote_null = f_fss_quote_single_null_s;
+    }
+    else if (data->flag & f_fss_payload_header_map_flag_quote_grave_e) {
+      internal.quote = f_string_ascii_grave_s.string[0];
+      internal.quote_null = f_fss_quote_grave_null_s;
+    }
+    else {
+      internal.quote = 0;
+      internal.quote_null = f_fss_quote_double_null_s;
+    }
 
     state->status = f_memory_array_increase_by(headers.used, sizeof(f_string_map_t), (void **) &destinations->array, &destinations->used, &destinations->size);
 
@@ -183,10 +193,7 @@ extern "C" {
                 private_fl_payload_header_map_strings(data, state, &internal, headers.array[internal.i].value.is.a_strings, destinations);
               }
               else if (data->flag & f_fss_payload_header_map_flag_null_string_e) {
-                state->status = f_memory_array_increase_by(2, sizeof(f_char_t), (void **) &destinations->array[destinations->used].value.string, &destinations->array[destinations->used].value.used, &destinations->array[destinations->used].value.size);
-                if (F_status_is_error(state->status)) break;
-
-                private_fl_payload_header_map_null_add(internal, &destinations->array[destinations->used].value);
+                state->status = f_string_dynamic_append(internal.quote_null, &destinations->array[destinations->used].value);
                 if (F_status_is_error(state->status)) break;
 
                 ++destinations->used;
@@ -211,116 +218,65 @@ extern "C" {
               if (headers.array[internal.i].value.is.a_dynamics.used) {
                 private_fl_payload_header_map_dynamics(data, state, &internal, &headers.array[internal.i].value.is.a_dynamics, destinations);
               }
+              else if (data->flag & f_fss_payload_header_map_flag_null_dynamic_e) {
+                state->status = f_string_dynamic_append(internal.quote_null, &destinations->array[destinations->used].value);
+                if (F_status_is_error(state->status)) break;
+
+                ++destinations->used;
+              }
               else if (data->flag & f_fss_payload_header_map_flag_null_e) {
                 ++destinations->used;
               }
 
               break;
 
-// @todo resume here.
             case f_abstruse_map_e:
-              data->cache->used = 0;
-              internal.k = f_fss_extended_next_s.used;
-
-              if (headers.array[internal.i].value.is.a_map.name.used) {
-                internal.k += headers.array[internal.i].value.is.a_map.name.used;
-                internal.k += headers.array[internal.i].value.is.a_map.value.used ? headers.array[internal.i].value.is.a_map.value.used : (f_string_ascii_quote_double_s.used * 2);
-              }
-              else if (headers.array[internal.i].value.is.a_map.value.used) {
-                internal.k += (f_string_ascii_quote_double_s.used * 2) + headers.array[internal.i].value.is.a_map.value.used;
-              }
-              else {
-                internal.k += f_string_ascii_quote_double_s.used * 4;
+              if (headers.array[internal.i].value.is.a_map.name.used || headers.array[internal.i].value.is.a_map.value.used) {
+                private_fl_payload_header_map_map(data, state, &internal, &headers.array[internal.i].value.is.a_map, destinations);
               }
+              else if (data->flag & f_fss_payload_header_map_flag_null_map_name_value_e) {
+                if (data->flag & f_fss_payload_header_map_flag_join_map_e) {
+                  state->status = f_string_dynamic_append(internal.quote_null, &destinations->array[destinations->used].value);
+                  if (F_status_is_error(state->status)) break;
 
-              state->status = f_memory_array_increase_by(internal.k, sizeof(f_char_t), (void **) &data->cache->string, &data->cache->used, &data->cache->size);
-              if (F_status_is_error(state->status)) break;
-
-              // @todo this should be different, in regards to the f_fss_payload_header_map_flag_null_dynamic_e bit.
-              macro_f_fss_payload_header_write_process_dynamic_d(data, state, internal, headers.array[internal.i].value.is.a_map.name);
-              if (F_status_is_error(state->status)) break;
-
-              macro_f_fss_payload_header_write_process_dynamic_d(data, state, internal, headers.array[internal.i].value.is.a_map.value);
-
-              if (F_status_is_error_not(state->status)) {
-
-                // The f_fss_extended_next_s is always added at the end of the macro.
-                data->cache->used -= f_fss_extended_next_s.used;
-
-                state->status = f_string_dynamic_append(*data->cache, &destinations->array[destinations->used].value);
+                  ++destinations->used;
+                }
+                else {
+                  private_fl_payload_header_map_map_name_value_null(data, state, &internal, destinations);
+                }
               }
-
-              if (F_status_is_error_not(state->status)) {
+              else if (data->flag & f_fss_payload_header_map_flag_null_e) {
                 ++destinations->used;
               }
 
               break;
 
             case f_abstruse_maps_e:
-              // @todo
-              break;
-
-            case f_abstruse_map_multi_e:
-              data->cache->used = 0;
-              internal.k = headers.array[internal.i].value.is.a_map_multi.name.used ? headers.array[internal.i].value.is.a_map_multi.name.used : f_string_ascii_quote_double_s.used * 2;
-              internal.k += f_fss_extended_next_s.used;
-
-              if (headers.array[internal.i].value.is.a_map_multi.value.used) {
-                for (internal.l = 0; internal.l < headers.array[internal.i].value.is.a_map_multi.value.used; ++internal.l) {
-
-                  if (state->interrupt) {
-                    state->interrupt((void * const) state, (void * const) &internal);
-                    if (F_status_set_fine(state->status) == F_interrupt) return;
-                  }
-
-                  internal.k += headers.array[internal.i].value.is.a_map_multi.value.array[internal.l].used ? headers.array[internal.i].value.is.a_map_multi.value.array[internal.l].used : f_string_ascii_quote_double_s.used * 2;
-                  internal.k += f_fss_extended_next_s.used;
-                } // for
-
-                state->status = f_memory_array_increase_by(internal.k, sizeof(f_char_t), (void **) &data->cache->string, &data->cache->used, &data->cache->size);
-                if (F_status_is_error(state->status)) break;
-
-                macro_f_fss_payload_header_write_process_dynamic_d(data, state, internal, headers.array[internal.i].value.is.a_map_multi.name);
-
-                data->cache->string[data->cache->used++] = f_fss_extended_next_s.string[0];
-
-                for (internal.l = 0; internal.l < headers.array[internal.i].value.is.a_map_multi.value.used; ++internal.l) {
-
-                  if (state->interrupt) {
-                    state->interrupt((void * const) state, (void * const) &internal);
-                    if (F_status_set_fine(state->status) == F_interrupt) return;
-                  }
-
-                  if (headers.array[internal.i].value.is.a_map_multi.value.array[internal.l].used) {
-                    state->status = f_string_dynamic_append(headers.array[internal.i].value.is.a_map_multi.value.array[internal.l], data->cache);
-                    if (F_status_is_error(state->status)) break;
-                  }
-                  else {
-                    data->cache->string[data->cache->used++] = f_string_ascii_quote_double_s.string[0];
-                    data->cache->string[data->cache->used++] = f_string_ascii_quote_double_s.string[0];
-                  }
-
-                  data->cache->string[data->cache->used++] = f_fss_extended_next_s.string[0];
-                } // for
-
-                if (F_status_is_error_not(state->status)) {
-
-                  // The f_fss_extended_next_s is always added at the end of the loop to avoid an additional condition check in the loop.
-                  data->cache->used -= f_fss_extended_next_s.used;
+              if (headers.array[internal.i].value.is.a_maps.used) {
+                private_fl_payload_header_map_maps(data, state, &internal, &headers.array[internal.i].value.is.a_maps, destinations);
+              }
+              else if (data->flag & f_fss_payload_header_map_flag_null_map_name_value_e) {
+                if (data->flag & f_fss_payload_header_map_flag_join_maps_e) {
+                  state->status = f_string_dynamic_append(internal.quote_null, &destinations->array[destinations->used].value);
+                  if (F_status_is_error(state->status)) break;
 
-                  state->status = f_string_dynamic_append(*data->cache, &destinations->array[destinations->used].value);
+                  ++destinations->used;
+                }
+                else {
+                  private_fl_payload_header_map_map_name_value_null(data, state, &internal, destinations);
                 }
               }
-              else if (headers.array[internal.i].value.is.a_map_multi.name.used) {
-                state->status = f_string_dynamic_append(headers.array[internal.i].value.is.a_map_multi.name, &destinations->array[destinations->used].value);
-              }
-
-              if (F_status_is_error_not(state->status)) {
+              else if (data->flag & f_fss_payload_header_map_flag_null_e) {
                 ++destinations->used;
               }
 
               break;
 
+// @todo resume after here.
+            case f_abstruse_map_multi_e:
+              // @todo
+              break;
+
             case f_abstruse_map_multis_e:
               // @todo
               break;
@@ -336,6 +292,7 @@ extern "C" {
               break;
 
             case f_abstruse_triple_e:
+              // @todo update this.
               data->cache->used = 0;
 
               if (headers.array[internal.i].value.is.a_triple.a.used) {
@@ -343,28 +300,28 @@ extern "C" {
 
                 if (headers.array[internal.i].value.is.a_triple.b.used) {
                   internal.k += headers.array[internal.i].value.is.a_triple.b.used;
-                  internal.k += headers.array[internal.i].value.is.a_triple.c.used ? headers.array[internal.i].value.is.a_triple.c.used : (f_string_ascii_quote_double_s.used * 2);
+                  internal.k += headers.array[internal.i].value.is.a_triple.c.used ? headers.array[internal.i].value.is.a_triple.c.used : internal.quote_null.used;
                 }
                 else if (headers.array[internal.i].value.is.a_triple.c.used) {
-                  internal.k += headers.array[internal.i].value.is.a_triple.c.used + (f_string_ascii_quote_double_s.used * 2);
+                  internal.k += headers.array[internal.i].value.is.a_triple.c.used + internal.quote_null.used;
                 }
                 else {
-                  internal.k = f_string_ascii_quote_double_s.used * 4;
+                  internal.k = internal.quote_null.used * 2;
                 }
               }
               else if (headers.array[internal.i].value.is.a_triple.b.used) {
                 if (headers.array[internal.i].value.is.a_triple.c.used) {
-                  internal.k = (f_string_ascii_quote_double_s.used * 2) + headers.array[internal.i].value.is.a_triple.b.used + headers.array[internal.i].value.is.a_triple.c.used;
+                  internal.k = internal.quote_null.used + headers.array[internal.i].value.is.a_triple.b.used + headers.array[internal.i].value.is.a_triple.c.used;
                 }
                 else {
-                  internal.k = (f_string_ascii_quote_double_s.used * 4) + headers.array[internal.i].value.is.a_triple.b.used;
+                  internal.k = internal.quote_null.used * 2 + headers.array[internal.i].value.is.a_triple.b.used;
                 }
               }
               else if (headers.array[internal.i].value.is.a_triple.c.used) {
-                internal.k = (f_string_ascii_quote_double_s.used * 4) + headers.array[internal.i].value.is.a_triple.c.used;
+                internal.k = internal.quote_null.used * 2 + headers.array[internal.i].value.is.a_triple.c.used;
               }
               else {
-                internal.k = f_string_ascii_quote_double_s.used * 6;
+                internal.k = internal.quote_null.used * 3;
               }
 
               internal.k += f_fss_extended_next_s.used * 2;
index 4b43e6d8aa954564ac12ecf0928f63a664a08e83..6f18ec81f0fd13093c24708737cbf2458834d7b0 100644 (file)
@@ -75,14 +75,9 @@ extern "C" {
  *
  *   This alters state.status:
  *     F_okay on success.
- *     F_okay_eos on success after reaching the end of the buffer.
- *     F_okay_stop on success after reaching the range stop.
- *     F_data_not if object is empty (object.used is 0).
- *     F_data_not_eos no data to write due start location being greater than or equal to buffer size.
- *     F_data_not_stop no data to write due start location being greater than stop location.
+ *     F_data_not if headers is empty (headers.used is 0).
  *
  *     F_interrupt (with error bit) if stopping due to an interrupt.
- *     F_okay_eol (with error bit) after reaching an EOL, which is not supported by the standard.
  *     F_parameter (with error bit) if a parameter is invalid.
  *
  *     Errors (with error bit) from: f_memory_array_increase().
index c91d70f1974bc7243378889527385923ff7adaa3..55954696719fbc30aace9f033ef947731db5787e 100644 (file)
@@ -122,7 +122,7 @@ extern "C" {
         private_fl_fss_basic_write(F_false, dynamic, internal.quote, &internal.range, data->cache, state, (void * const) &internal); \
       } \
       else { \
-        private_fl_payload_header_map_null_add(internal, data->cache); \
+        state->status = f_string_dynamic_append(internal.quote_null, data->cache); \
       } \
       \
       if (F_status_is_error_not(state->status)) { \
index 609a2caff5adcd8e9c5249847aee56cdf9760a06..a4b33927db15556373e1870e2b22a79f38b90a48 100644 (file)
@@ -28,6 +28,7 @@ extern "C" {
  *   - l:            A counter used for more complex use cases such as with multi-maps.
  *   - range:        Used for passing a given string range to the FSS write functions.
  *   - conversion:   The conversion data.
+ *   - quote_null:   The string representing an empty, aka NULL, Content. This is generally double-quotes.
  *   - destinations: The destinations map being appended to.
  *   - original:     The original destination used length.
  */
@@ -42,6 +43,7 @@ extern "C" {
     f_range_t range;
     f_conversion_data_t conversion;
 
+    f_string_static_t quote_null;
     f_string_maps_t * const destinations;
     const f_number_unsigned_t original;
   } f_fss_payload_header_internal_t;
@@ -55,11 +57,12 @@ extern "C" {
     0, \
     f_range_t_initialize, \
     f_conversion_data_base_10_c, \
+    f_string_static_t_initialize, \
     0, \
     0, \
   }
 
-  #define macro_f_fss_payload_header_internal_t_initialize_1(quote, step, i, j, k, l, range, conversion, destinations, original) { \
+  #define macro_f_fss_payload_header_internal_t_initialize_1(quote, step, i, j, k, l, range, conversion, destinations, quote_null, original) { \
     quote, \
     step, \
     i, \
@@ -69,6 +72,7 @@ extern "C" {
     range, \
     conversion, \
     destinations, \
+    quote_null, \
     original, \
   }
 
@@ -81,6 +85,7 @@ extern "C" {
     0, \
     f_range_t_initialize, \
     f_conversion_data_base_10_c, \
+    f_string_static_t_initialize, \
     destinations, \
     original, \
   }
index a1be9ee99cc197014df4f74c8f0aefb7ca099201..a32df60c09605bb52b1c763dfe7d5ac482ce9a79 100644 (file)
@@ -20,6 +20,8 @@ extern "C" {
     state->status = f_string_dynamic_strip_null(&internal->destinations->array[internal->destinations->used].value);
     if (F_status_is_error(state->status)) return F_true;
 
+    state->status = F_okay;
+
     return F_false;
   }
 #endif // !defined(_di_fl_fss_payload_header_map_)
@@ -37,15 +39,13 @@ extern "C" {
       state->status = f_string_dynamic_strip_null(&destinations->array[destinations->used].value);
     }
     else {
-      state->status = f_memory_array_increase_by(2, sizeof(f_char_t), (void **) &destinations->array[destinations->used].value.string, &destinations->array[destinations->used].value.used, &destinations->array[destinations->used].value.size);
-      if (F_status_is_error(state->status)) return F_true;
-
-      private_fl_payload_header_map_null_add(*internal, &destinations->array[destinations->used].value);
+      state->status = f_string_dynamic_append(internal->quote_null, &destinations->array[destinations->used].value);
     }
 
     if (F_status_is_error(state->status)) return F_true;
 
     ++destinations->used;
+    state->status = F_okay;
 
     return F_false;
   }
@@ -54,11 +54,17 @@ extern "C" {
 #if !defined(_di_fl_fss_payload_header_map_)
   uint8_t private_fl_payload_header_map_dynamics(f_fss_payload_header_state_t * const data, f_state_t * const state, f_fss_payload_header_internal_t * const internal, f_string_statics_t * const buffers, f_string_maps_t * const destinations) {
 
-    // @todo this needs to implement f_fss_payload_header_map_flag_join_dynamics_e.
-
     data->cache->used = 0;
     internal->k = 0;
 
+    state->status = f_memory_array_increase_by(buffers->used + ((f_fss_extended_next_s.used + internal->quote_null.used) * buffers->used), sizeof(f_char_t), (void **) &destinations->array[destinations->used].value.string, &destinations->array[destinations->used].value.used, &destinations->array[destinations->used].value.size);
+    if (F_status_is_error(state->status)) return F_true;
+
+    if (data->flag & f_fss_payload_header_map_flag_join_dynamics_e) {
+      state->status = f_memory_array_increase_by(buffers->used + ((f_fss_extended_next_s.used + internal->quote_null.used) * buffers->used), sizeof(f_char_t), (void **) &data->cache->string, &data->cache->used, &data->cache->size);
+      if (F_status_is_error(state->status)) return F_true;
+    }
+
     for (internal->j = 0; internal->j < buffers->used; ++internal->j) {
 
       if (state->interrupt) {
@@ -66,55 +72,248 @@ extern "C" {
         if (F_status_set_fine(state->status) == F_interrupt) return F_true;
       }
 
-      internal->k += buffers->array[internal->j].used ? buffers->array[internal->j].used : f_string_ascii_quote_double_s.used * 2;
-      internal->k += f_fss_extended_next_s.used;
+      if (data->flag & f_fss_payload_header_map_flag_join_dynamics_e) {
+        state->status = f_string_dynamic_append(buffers->array[internal->j], data->cache);
+        if (F_status_is_error(state->status)) return F_true;
+
+        state->status = f_string_dynamic_append_assure(f_string_space_s, data->cache);
+        if (F_status_is_error(state->status)) return F_true;
+      }
+      else {
+        if (buffers->array[internal->j].used) {
+          internal->range.start = 0;
+          internal->range.stop = buffers->array[internal->j].used - 1;
+
+          private_fl_fss_basic_write(F_false, buffers->array[internal->j], internal->quote, &internal->range, &destinations->array[destinations->used].value, state, (void * const) internal);
+          if (F_status_is_error(state->status)) return F_true;
+
+          state->status = f_string_dynamic_append_assure(f_fss_extended_next_s, data->cache);
+          if (F_status_is_error(state->status)) return F_true;
+        }
+        else if (data->flag & f_fss_payload_header_map_flag_null_string_e) {
+          state->status = f_string_dynamic_append(internal->quote_null, &destinations->array[destinations->used].value);
+          if (F_status_is_error(state->status)) return F_true;
+        }
+      }
     } // for
 
-    state->status = f_memory_array_increase_by(internal->k, sizeof(f_char_t), (void **) &data->cache->string, &data->cache->used, &data->cache->size);
+    if (data->flag & f_fss_payload_header_map_flag_join_dynamics_e) {
+      if (data->cache->used) {
+
+        // Do not include the f_string_space_s that is always added at the end of the loop.
+        data->cache->used -= f_string_space_s.used;
+
+        internal->range.start = 0;
+        internal->range.stop = data->cache->used - 1;
+
+        private_fl_fss_basic_write(F_false, *data->cache, internal->quote, &internal->range, &destinations->array[destinations->used].value, state, (void * const) internal);
+        if (F_status_is_error(state->status)) return F_true;
+      }
+      else {
+        if (data->flag & f_fss_payload_header_map_flag_null_string_e) {
+          state->status = f_string_dynamic_append(internal->quote_null, &destinations->array[destinations->used].value);
+          if (F_status_is_error(state->status)) return F_true;
+        }
+      }
+    }
+
+    state->status = f_string_dynamic_strip_null(&destinations->array[destinations->used].value);
     if (F_status_is_error(state->status)) return F_true;
 
-    for (internal->j = 0; internal->j < buffers->used; ++internal->j) {
+    ++destinations->used;
+    state->status = F_okay;
 
-      if (state->interrupt) {
-        state->interrupt((void * const) state, (void * const) internal);
-        if (F_status_set_fine(state->status) == F_interrupt) return F_true;
+    return F_false;
+  }
+#endif // !defined(_di_fl_fss_payload_header_map_)
+
+#if !defined(_di_fl_fss_payload_header_map_)
+  uint8_t private_fl_payload_header_map_map(f_fss_payload_header_state_t * const data, f_state_t * const state, f_fss_payload_header_internal_t * const internal, f_string_map_t * const map, f_string_maps_t * const destinations) {
+
+    if (data->flag & f_fss_payload_header_map_flag_join_map_e) {
+      state->status = f_memory_array_increase_by(map->name.used + map->value.used + f_string_space_s.used, sizeof(f_char_t), (void **) &destinations->array[destinations->used].value.string, &destinations->array[destinations->used].value.used, &destinations->array[destinations->used].value.size);
+      if (F_status_is_error(state->status)) return F_true;
+
+      data->cache->used = 0;
+
+      if (map->name.used) {
+        f_string_dynamic_append(map->name, data->cache);
+        if (F_status_is_error(state->status)) return F_true;
+
+        if (map->value.used) {
+          f_string_dynamic_append_assure(f_fss_extended_next_s, data->cache);
+          if (F_status_is_error(state->status)) return F_true;
+        }
+      }
+
+      if (map->value.used) {
+        f_string_dynamic_append(map->value, data->cache);
+        if (F_status_is_error(state->status)) return F_true;
       }
 
-      macro_f_fss_payload_header_write_process_dynamic_d(data, state, (*internal), buffers->array[internal->j]);
+      private_fl_fss_basic_write(F_false, *data->cache, 0, &internal->range, &destinations->array[destinations->used].value, state, (void * const) internal);
       if (F_status_is_error(state->status)) return F_true;
-    } // for
+    }
+    else {
+      if (map->name.used) {
+        internal->range.start = 0;
+        internal->range.stop = map->name.used - 1;
+
+        private_fl_fss_basic_write(F_false, map->name, 0, &internal->range, &destinations->array[destinations->used].value, state, (void * const) internal);
+        if (F_status_is_error(state->status)) return F_true;
+
+        if (map->value.used) {
+          f_string_dynamic_append_assure(f_string_space_s, &destinations->array[destinations->used].value);
+          if (F_status_is_error(state->status)) return F_true;
+        }
+      }
 
-    // The f_fss_extended_next_s is always added at the end of the loop to avoid an additional condition check in the loop.
-    data->cache->used -= f_fss_extended_next_s.used;
+      if (map->value.used) {
+        internal->range.start = 0;
+        internal->range.stop = map->value.used - 1;
 
-    state->status = f_string_dynamic_append(*data->cache, &destinations->array[destinations->used].value);
+        private_fl_fss_basic_write(F_false, map->value, 0, &internal->range, &destinations->array[destinations->used].value, state, (void * const) internal);
+        if (F_status_is_error(state->status)) return F_true;
+      }
+    }
+
+    state->status = f_string_dynamic_strip_null(&destinations->array[destinations->used].value);
     if (F_status_is_error(state->status)) return F_true;
 
     ++destinations->used;
+    state->status = F_okay;
 
     return F_false;
   }
 #endif // !defined(_di_fl_fss_payload_header_map_)
 
 #if !defined(_di_fl_fss_payload_header_map_)
-  void private_fl_payload_header_map_null_add(const f_fss_payload_header_internal_t internal, f_string_dynamic_t * const destination) {
+  uint8_t private_fl_payload_header_map_map_name_value_null(f_fss_payload_header_state_t * const data, f_state_t * const state, f_fss_payload_header_internal_t * const internal, f_string_maps_t * const destinations) {
+
+    state->status = f_memory_array_increase_by(internal->quote_null.used * 2 + f_fss_extended_next_s.used, sizeof(f_char_t), (void **) &destinations->array[destinations->used].value.string, &destinations->array[destinations->used].value.used, &destinations->array[destinations->used].value.size);
+    if (F_status_is_error(state->status)) return F_true;
+
+    state->status = f_string_dynamic_append(internal->quote_null, &destinations->array[destinations->used].value);
+    if (F_status_is_error(state->status)) return F_true;
+
+    state->status = f_string_dynamic_append_assure(f_fss_extended_next_s, &destinations->array[destinations->used].value);
+    if (F_status_is_error(state->status)) return F_true;
 
-    destination->string[destination->used++] = internal.quote ? internal.quote : f_string_ascii_quote_double_s.string[0];
-    destination->string[destination->used++] = internal.quote ? internal.quote : f_string_ascii_quote_double_s.string[0];
+    state->status = f_string_dynamic_append(internal->quote_null, &destinations->array[destinations->used].value);
+    if (F_status_is_error(state->status)) return F_true;
+
+    ++destinations->used;
+    state->status = F_none;
+
+    return F_false;
   }
 #endif // !defined(_di_fl_fss_payload_header_map_)
 
+#if !defined(_di_fl_fss_payload_header_maps_)
+  uint8_t private_fl_payload_header_map_maps(f_fss_payload_header_state_t * const data, f_state_t * const state, f_fss_payload_header_internal_t * const internal, f_string_maps_t * const maps, f_string_maps_t * const destinations) {
+
+    if (data->flag & f_fss_payload_header_map_flag_join_maps_e) {
+      // @todo
+    }
+    else if (data->flag & f_fss_payload_header_map_flag_null_map_name_value_e) {
+      // @todo
+    }
+    else {
+      for (internal->k = 0; internal->k < maps->used; ++internal->k) {
+
+        if (maps->array[internal->k].name.used) {
+          internal->k += maps->array[internal->k].name.used + f_fss_extended_next_s.used + internal->quote_null.used;
+        }
+        else if (data->flag & f_fss_payload_header_map_flag_null_map_name_e) {
+          internal->k += f_fss_extended_next_s.used + internal->quote_null.used;
+        }
+
+        if (maps->array[internal->k].value.used) {
+          internal->k += maps->array[internal->k].value.used + f_fss_extended_next_s.used + internal->quote_null.used;
+        }
+        else if (data->flag & f_fss_payload_header_map_flag_null_map_value_e) {
+          internal->k += f_fss_extended_next_s.used + internal->quote_null.used;
+        }
+      } // for
+
+      // @todo all of this below.
+
+      if (data->flag & f_fss_payload_header_map_flag_join_map_e) {
+        data->cache->used = 0;
+
+        state->status = f_memory_array_increase_by(internal->k, sizeof(f_char_t), (void **) &data->cache->string, &data->cache->used, &data->cache->size);
+        if (F_status_is_error(state->status)) return F_true;
+
+        for (internal->l = 0; internal->l < maps->used; ++internal->l) {
+
+          if (maps->array[internal->l].name.used || (data->flag & f_fss_payload_header_map_flag_null_map_name_e)) {
+            if (maps->array[internal->l].name.used) {
+              f_string_dynamic_append(maps->array[internal->l].name, data->cache);
+            }
+            else if (data->flag & f_fss_payload_header_map_flag_null_map_name_e) {
+              state->status = f_string_dynamic_append(internal->quote_null, data->cache);
+            }
+
+            if (F_status_is_error(state->status)) return F_true;
+
+            if (maps->array[internal->l].value.used) {
+              f_string_dynamic_append_assure(f_fss_extended_next_s, data->cache);
+              if (F_status_is_error(state->status)) return F_true;
+            }
+          }
+
+          if (maps->array[internal->l].value.used) {
+            f_string_dynamic_append(maps->array[internal->l].value, data->cache);
+          }
+          else if (data->flag & f_fss_payload_header_map_flag_null_map_value_e) {
+            state->status = f_string_dynamic_append(internal->quote_null, data->cache);
+          }
+
+          if (F_status_is_error(state->status)) return F_true;
+
+          state->status = f_string_dynamic_append_assure(f_fss_extended_next_s, data->cache);
+          if (F_status_is_error(state->status)) return F_true;
+        } // for
+
+        // Remove any trailing "extended_next".
+        if (data->cache->used) {
+          data->cache->used -= f_fss_extended_next_s.used;
+        }
+
+        private_fl_fss_basic_write(F_false, *data->cache, 0, &internal->range, &destinations->array[destinations->used].value, state, (void * const) internal);
+        if (F_status_is_error(state->status)) return F_true;
+      }
+      else {
+        state->status = f_memory_array_increase_by(internal->k, sizeof(f_char_t), (void **) &destinations->array[destinations->used].value.string, &destinations->array[destinations->used].value.used, &destinations->array[destinations->used].value.size);
+        if (F_status_is_error(state->status)) return F_true;
+
+        // @todo
+      }
+    }
+
+    state->status = f_string_dynamic_strip_null(&destinations->array[destinations->used].value);
+    if (F_status_is_error(state->status)) return F_true;
+
+    ++destinations->used;
+    state->status = F_okay;
+
+    return F_false;
+  }
+#endif // !defined(_di_fl_fss_payload_header_maps_)
+
 #if !defined(_di_fl_fss_payload_header_map_)
   uint8_t private_fl_payload_header_map_number_signed(f_fss_payload_header_state_t * const data, f_state_t * const state, f_fss_payload_header_internal_t * const internal, const f_number_signed_t number) {
 
     if (data->cache->used) {
-      state->status = f_string_dynamic_append(f_fss_extended_next_s, data->cache);
+      state->status = f_string_dynamic_append_assure(f_fss_extended_next_s, data->cache);
       if (F_status_is_error(state->status)) return F_true;
     }
 
     state->status = f_conversion_number_signed_to_string(number, data->conversion, data->cache);
     if (F_status_is_error(state->status)) return F_true;
 
+    state->status = F_okay;
+
     return F_false;
   }
 #endif // !defined(_di_fl_fss_payload_header_map_)
@@ -123,16 +322,19 @@ extern "C" {
   uint8_t private_fl_payload_header_map_number_unsigned(f_fss_payload_header_state_t * const data, f_state_t * const state, f_fss_payload_header_internal_t * const internal, const f_number_unsigned_t number) {
 
     if (data->cache->used) {
-      state->status = f_string_dynamic_append(f_fss_extended_next_s, data->cache);
+      state->status = f_string_dynamic_append_assure(f_fss_extended_next_s, data->cache);
       if (F_status_is_error(state->status)) return F_true;
     }
 
     state->status = f_conversion_number_unsigned_to_string(number, data->conversion, data->cache);
     if (F_status_is_error(state->status)) return F_true;
 
+    state->status = F_okay;
+
     return F_false;
   }
 #endif // !defined(_di_fl_fss_payload_header_map_)
+
 #if !defined(_di_fl_fss_payload_header_map_)
   uint8_t private_fl_payload_header_map_strings(f_fss_payload_header_state_t * const data, f_state_t * const state, f_fss_payload_header_internal_t * const internal, f_string_t * const buffers, f_string_maps_t * const destinations) {
 
@@ -141,6 +343,7 @@ extern "C" {
     data->cache->used = 0;
     internal->k = 0;
 
+    // Pre-process the string lengths to allow for a single allocation.
     for (internal->j = 0; buffers[internal->j]; ++internal->j) {
 
       if (state->interrupt) {
@@ -150,84 +353,73 @@ extern "C" {
 
       string_static.string = buffers[internal->j];
       string_static.used = string_static.string ? strnlen(string_static.string, F_string_t_size_d) : 0;
-
-      internal->k += string_static.used ? string_static.used : f_string_ascii_quote_double_s.used * 2;
-      internal->k += f_fss_extended_next_s.used;
+      internal->k += string_static.used + f_fss_extended_next_s.used + internal->quote_null.used;
     } // for
 
-    // Save the total strings as internal.l so that intenal.j can be used for the loop counter later on.
-    internal->l = internal->j;
+    state->status = f_memory_array_increase_by(internal->k, sizeof(f_char_t), (void **) &destinations->array[destinations->used].value.string, &destinations->array[destinations->used].value.used, &destinations->array[destinations->used].value.size);
+    if (F_status_is_error(state->status)) return F_true;
 
     if (data->flag & f_fss_payload_header_map_flag_join_strings_e) {
       state->status = f_memory_array_increase_by(internal->k, sizeof(f_char_t), (void **) &data->cache->string, &data->cache->used, &data->cache->size);
       if (F_status_is_error(state->status)) return F_true;
+    }
 
-      for (internal->j = 0; internal->j < internal->l; ++internal->j) {
+    for (internal->l = internal->j, internal->j = 0; internal->j < internal->l; ++internal->j) {
 
-        if (state->interrupt) {
-          state->interrupt((void * const) state, (void * const) internal);
-          if (F_status_set_fine(state->status) == F_interrupt) return F_true;
-        }
+      if (state->interrupt) {
+        state->interrupt((void * const) state, (void * const) internal);
+        if (F_status_set_fine(state->status) == F_interrupt) return F_true;
+      }
 
-        string_static.string = buffers[internal->j];
-        string_static.used = string_static.string ? strnlen(string_static.string, F_string_t_size_d) : 0;
+      string_static.string = buffers[internal->j];
+      string_static.used = string_static.string ? strnlen(string_static.string, F_string_t_size_d) : 0;
+
+      if (data->flag & f_fss_payload_header_map_flag_join_strings_e) {
+        state->status = f_string_dynamic_append(string_static, data->cache);
+        if (F_status_is_error(state->status)) return F_true;
 
+        state->status = f_string_dynamic_append_assure(f_string_space_s, data->cache);
+        if (F_status_is_error(state->status)) return F_true;
+      }
+      else {
         if (string_static.used) {
           internal->range.start = 0;
           internal->range.stop = string_static.used - 1;
 
-          private_fl_fss_basic_write(F_false, string_static, internal->quote, &internal->range, data->cache, state, (void * const) internal);
+          private_fl_fss_basic_write(F_false, string_static, internal->quote, &internal->range, &destinations->array[destinations->used].value, state, (void * const) internal);
           if (F_status_is_error(state->status)) return F_true;
 
-          data->cache->string[data->cache->used++] = f_fss_extended_open_s.string[0];
+          state->status = f_string_dynamic_append_assure(f_fss_extended_next_s, data->cache);
+          if (F_status_is_error(state->status)) return F_true;
+        }
+        else if (data->flag & f_fss_payload_header_map_flag_null_string_e) {
+          state->status = f_string_dynamic_append(internal->quote_null, &destinations->array[destinations->used].value);
+          if (F_status_is_error(state->status)) return F_true;
         }
-      } // for
-
-      if (data->cache->used) {
-
-        // The f_fss_extended_next_s is always added at the end of the loop to avoid an additional condition check in the loop.
-        data->cache->used -= f_fss_extended_next_s.used;
-      }
-      else if (data->flag & f_fss_payload_header_map_flag_null_string_e) {
-        private_fl_payload_header_map_null_add(*internal, data->cache);
       }
+    } // for
 
+    if (data->flag & f_fss_payload_header_map_flag_join_strings_e) {
       if (data->cache->used) {
-        state->status = f_string_dynamic_append(*data->cache, &destinations->array[destinations->used].value);
-      }
-    }
-    else {
-      state->status = f_memory_array_increase_by(internal->k, sizeof(f_char_t), (void **) &destinations->array[destinations->used].value.string, &destinations->array[destinations->used].value.used, &destinations->array[destinations->used].value.size);
-
-      for (internal->j = 0; internal->j < internal->l; ++internal->j) {
 
-        if (state->interrupt) {
-          state->interrupt((void * const) state, (void * const) internal);
-          if (F_status_set_fine(state->status) == F_interrupt) return F_true;
-        }
+        // Do not include the f_string_space_s that is always added at the end of the loop.
+        data->cache->used -= f_string_space_s.used;
 
-        string_static.string = buffers[internal->j];
-        string_static.used = string_static.string ? strnlen(string_static.string, F_string_t_size_d) : 0;
+        internal->range.start = 0;
+        internal->range.stop = data->cache->used - 1;
 
-        state->status = f_string_dynamic_append(string_static, data->cache);
-        if (F_status_is_error(state->status)) return F_true;
-
-        state->status = f_string_dynamic_append(f_fss_extended_next_s, data->cache);
+        private_fl_fss_basic_write(F_false, *data->cache, internal->quote, &internal->range, &destinations->array[destinations->used].value, state, (void * const) internal);
         if (F_status_is_error(state->status)) return F_true;
-      } // for
-
-      // Do not include the f_fss_extended_next_s that is always added at the end of the loop.
-      data->cache->used -= f_fss_extended_next_s.used;
-
-      internal->range.start = 0;
-      internal->range.stop = data->cache->used - 1;
-
-      private_fl_fss_basic_write(F_false, *data->cache, internal->quote, &internal->range, &destinations->array[destinations->used].value, state, (void * const) internal);
-      if (F_status_is_error(state->status)) return F_true;
-
-      state->status = f_string_dynamic_strip_null(&destinations->array[destinations->used].value);
+      }
+      else {
+        if (data->flag & f_fss_payload_header_map_flag_null_string_e) {
+          state->status = f_string_dynamic_append(internal->quote_null, &destinations->array[destinations->used].value);
+          if (F_status_is_error(state->status)) return F_true;
+        }
+      }
     }
 
+    state->status = f_string_dynamic_strip_null(&destinations->array[destinations->used].value);
     if (F_status_is_error(state->status)) return F_true;
 
     ++destinations->used;
index 9fe91baf3868e0fcc9ba9f0887f4a8fafd28bcff..c816e5d05ade8dd445becfe2b8eca0fa59e51f59 100644 (file)
@@ -27,7 +27,7 @@ extern "C" {
  *   The state passed directly from the fl_fss_payload_header_map() parameters.
  *
  *   This alters state.status:
- *     Success from: f_string_dynamic_strip_null().
+ *     F_okay on success.
  *
  *     Errors (with error bit) from: private_fl_fss_basic_write().
  *     Errors (with error bit) from: f_string_dynamic_strip_null().
@@ -63,13 +63,10 @@ extern "C" {
  *   The state passed directly from the fl_fss_payload_header_map() parameters.
  *
  *   This alters state.status:
- *     Success from: f_string_dynamic_strip_null().
- *     Success from: private_fl_payload_header_map_null_add().
+ *     F_okay on success.
  *
- *     Errors (with error bit) from: f_memory_array_increase_by().
  *     Errors (with error bit) from: f_string_dynamic_strip_null().
  *     Errors (with error bit) from: private_fl_fss_basic_write().
- *     Errors (with error bit) from: private_fl_payload_header_map_null_add().
  *
  *   Must not be NULL.
  * @param internal
@@ -88,11 +85,10 @@ extern "C" {
  *   F_true if the caller should break or exit due to an error or something similar.
  *   F_false, otherwise.
  *
- * @see f_memory_array_increase_by()
+ * @see f_string_dynamic_append()
  * @see f_string_dynamic_strip_null()
  *
  * @see private_fl_fss_basic_write()
- * @see private_fl_payload_header_map_null_add()
  *
  * @see fl_fss_payload_header_map()
  */
@@ -113,6 +109,17 @@ extern "C" {
  *   Must not be NULL.
  * @param state
  *   The state passed directly from the fl_fss_payload_header_map() parameters.
+ *
+ *   This alters state.status:
+ *     F_okay on success.
+ *
+ *     Errors (with error bit) from: f_memory_array_increase_by().
+ *     Errors (with error bit) from: f_string_dynamic_append().
+ *     Errors (with error bit) from: f_string_dynamic_append_assure().
+ *     Errors (with error bit) from: f_string_dynamic_strip_null().
+ *
+ *     Errors (with error bit) from: private_fl_fss_basic_write().
+ *
  *   Must not be NULL.
  * @param internal
  *   The internal state, f_fss_payload_header_internal_t, created inside of fl_fss_payload_header_map().
@@ -131,10 +138,11 @@ extern "C" {
  *   F_false, otherwise.
  *
  * @see f_memory_array_increase_by()
+ * @see f_string_dynamic_append()
+ * @see f_string_dynamic_append_assure()
  * @see f_string_dynamic_strip_null()
  *
  * @see private_fl_fss_basic_write()
- * @see private_fl_payload_header_map_null_add()
  *
  * @see fl_fss_payload_header_map()
  */
@@ -143,25 +151,146 @@ extern "C" {
 #endif // !defined(_di_fl_fss_payload_header_map_)
 
 /**
- * Add a NULL Content (column value), represented as an empty quoted string.
+ * Process the map strings, writing it into the packet with the appropriate escaping as necessary.
+ *
+ * This expects that the appropriate used and flag checks are performed prior to calling this.
+ *
+ * @param data
+ *   The f_fss_payload_header_state_t pointer.
+ *   Must not be NULL.
+ * @param state
+ *   The state passed directly from the fl_fss_payload_header_map() parameters.
+ *
+ *   This alters state.status:
+ *     F_okay on success.
+ *
+ *     Errors (with error bit) from: f_memory_array_increase_by().
+ *     Errors (with error bit) from: f_string_dynamic_strip_null().
+ *     Errors (with error bit) from: private_fl_fss_basic_write().
+ *
+ *   Must not be NULL.
+ * @param internal
+ *   The internal state, f_fss_payload_header_internal_t, created inside of fl_fss_payload_header_map().
+ *   Must not be NULL.
+ * @param map
+ *   The map to read from.
+ *   Must not be NULL.
+ * @param destinations
+ *   A map of strings representing the header names and values after being safely converted into the valid payload header format.
+ *   This built header names and values are appended onto this.
+ *   This is updated as appropriate.
+ *   Must not be NULL.
+ *
+ * @return
+ *   F_true if the caller should break or exit due to an error or something similar.
+ *   F_false, otherwise.
+ *
+ * @see f_memory_array_increase_by()
+ * @see f_string_dynamic_append()
+ * @see f_string_dynamic_strip_null()
+ *
+ * @see private_fl_fss_basic_write()
+ *
+ * @see fl_fss_payload_header_map()
+ */
+#if !defined(_di_fl_fss_payload_header_map_)
+  extern uint8_t private_fl_payload_header_map_map(f_fss_payload_header_state_t * const data, f_state_t * const state, f_fss_payload_header_internal_t * const internal, f_string_map_t * const map, f_string_maps_t * const destinations) F_attribute_visibility_internal_d;
+#endif // !defined(_di_fl_fss_payload_header_map_)
+
+/**
+ * Process the case where a map is added with the appropriate NULL flag bits set.
+ *
+ * This adds the data.quote_null strings for both the map name and the map value, depending on the f_fss_payload_header_map_flag_null_map_name_e and f_fss_payload_header_map_flag_null_map_value_e flags.
+ *
+ * This expects that the appropriate used and flag checks are performed prior to calling this.
+ *
+ * @param data
+ *   The f_fss_payload_header_state_t pointer.
+ *   Must not be NULL.
+ * @param state
+ *   The state passed directly from the fl_fss_payload_header_map() parameters.
  *
+ *   This alters state.status:
+ *     F_okay on success.
+ *
+ *     Errors (with error bit) from: f_memory_array_increase_by().
+ *     Errors (with error bit) from: f_string_dynamic_strip_null().
+ *     Errors (with error bit) from: private_fl_fss_basic_write().
+ *
+ *   Must not be NULL.
  * @param internal
  *   The internal state, f_fss_payload_header_internal_t, created inside of fl_fss_payload_header_map().
- * @param destination
- *   The destination string to write to.
- *   This is not reallocated as needed.
- *   The caller must ensure enough space exists.
  *   Must not be NULL.
+ * @param destinations
+ *   A map of strings representing the header names and values after being safely converted into the valid payload header format.
+ *   This built header names and values are appended onto this.
+ *   This is updated as appropriate.
+ *   Must not be NULL.
+ *
+ * @return
+ *   F_true if the caller should break or exit due to an error or something similar.
+ *   F_false, otherwise.
  *
  * @see f_memory_array_increase_by()
+ * @see f_string_dynamic_append()
+ * @see f_string_dynamic_strip_null()
+ *
+ * @see private_fl_fss_basic_write()
  *
  * @see fl_fss_payload_header_map()
  */
 #if !defined(_di_fl_fss_payload_header_map_)
-  extern void private_fl_payload_header_map_null_add(const f_fss_payload_header_internal_t internal, f_string_dynamic_t * const destination) F_attribute_visibility_internal_d;
+  extern uint8_t private_fl_payload_header_map_map_name_value_null(f_fss_payload_header_state_t * const data, f_state_t * const state, f_fss_payload_header_internal_t * const internal, f_string_maps_t * const destinations) F_attribute_visibility_internal_d;
 #endif // !defined(_di_fl_fss_payload_header_map_)
 
 /**
+ * Process the map strings, writing it into the packet with the appropriate escaping as necessary.
+ *
+ * This expects that the appropriate used and flag checks are performed prior to calling this.
+ *
+ * @param data
+ *   The f_fss_payload_header_state_t pointer.
+ *   Must not be NULL.
+ * @param state
+ *   The state passed directly from the fl_fss_payload_header_map() parameters.
+ *
+ *   This alters state.status:
+ *     F_okay on success.
+ *
+ *     Errors (with error bit) from: f_memory_array_increase_by().
+ *     Errors (with error bit) from: f_string_dynamic_strip_null().
+ *     Errors (with error bit) from: private_fl_fss_basic_write().
+ *
+ *   Must not be NULL.
+ * @param internal
+ *   The internal state, f_fss_payload_header_internal_t, created inside of fl_fss_payload_header_map().
+ *   Must not be NULL.
+ * @param maps
+ *   The maps to read from.
+ *   Must not be NULL.
+ * @param destinations
+ *   A map of strings representing the header names and values after being safely converted into the valid payload header format.
+ *   This built header names and values are appended onto this.
+ *   This is updated as appropriate.
+ *   Must not be NULL.
+ *
+ * @return
+ *   F_true if the caller should break or exit due to an error or something similar.
+ *   F_false, otherwise.
+ *
+ * @see f_memory_array_increase_by()
+ * @see f_string_dynamic_append()
+ * @see f_string_dynamic_strip_null()
+ *
+ * @see private_fl_fss_basic_write()
+ *
+ * @see fl_fss_payload_header_map()
+ */
+#if !defined(_di_fl_fss_payload_header_maps_)
+  extern uint8_t private_fl_payload_header_map_maps(f_fss_payload_header_state_t * const data, f_state_t * const state, f_fss_payload_header_internal_t * const internal, f_string_maps_t * const maps, f_string_maps_t * const destinations) F_attribute_visibility_internal_d;
+#endif // !defined(_di_fl_fss_payload_header_maps_)
+
+/**
  * Process the signed number, converting it to a string and appending that string onto data->cache.
  * The resulting data->cache is then appended onto the destination value on success.
  * If the number is not appended to data->cache, then nothing is appended to the destination value.
@@ -175,10 +304,10 @@ extern "C" {
  *   The state passed directly from the fl_fss_payload_header_map() parameters.
  *
  *   This alters state.status:
- *     Success from: f_conversion_number_signed_to_string().
+ *     F_okay on success.
  *
  *     Errors (with error bit) from: f_conversion_number_signed_to_string().
- *     Errors (with error bit) from: f_string_dynamic_append().
+ *     Errors (with error bit) from: f_string_dynamic_append_assure().
  *
  *   Must not be NULL.
  * @param internal
@@ -193,7 +322,7 @@ extern "C" {
  *   F_false, otherwise.
  *
  * @see f_conversion_number_unsigned_to_string()
- * @see f_string_dynamic_append()
+ * @see f_string_dynamic_append_assure()
  *
  * @see fl_fss_payload_header_map()
  */
@@ -216,10 +345,10 @@ extern "C" {
  *   The state passed directly from the fl_fss_payload_header_map() parameters.
  *
  *   This alters state.status:
- *     Success from: f_conversion_number_unsigned_to_string().
+ *     F_okay on success.
  *
  *     Errors (with error bit) from: f_conversion_number_unsigned_to_string().
- *     Errors (with error bit) from: f_string_dynamic_append().
+ *     Errors (with error bit) from: f_string_dynamic_append_assure().
  *
  *   Must not be NULL.
  * @param internal
@@ -234,7 +363,7 @@ extern "C" {
  *   F_false, otherwise.
  *
  * @see f_conversion_number_unsigned_to_string()
- * @see f_string_dynamic_append()
+ * @see f_string_dynamic_append_assure()
  *
  * @see fl_fss_payload_header_map()
  */
@@ -261,6 +390,7 @@ extern "C" {
  *
  *     Errors (with error bit) from: f_memory_array_increase_by().
  *     Errors (with error bit) from: f_string_dynamic_append().
+ *     Errors (with error bit) from: f_string_dynamic_append_assure().
  *     Errors (with error bit) from: f_string_dynamic_strip_null().
  *     Errors (with error bit) from: private_fl_fss_basic_write().
  *
@@ -283,10 +413,10 @@ extern "C" {
  *
  * @see f_memory_array_increase_by()
  * @see f_string_dynamic_append()
+ * @see f_string_dynamic_append_assure()
  * @see f_string_dynamic_strip_null()
  *
  * @see private_fl_fss_basic_write()
- * @see private_fl_payload_header_map_null_add()
  *
  * @see fl_fss_payload_header_map()
  */
diff --git a/level_1/fl_fss/data/build/dependencies-tests b/level_1/fl_fss/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_1/fl_fss/data/build/settings-tests b/level_1/fl_fss/data/build/settings-tests
new file mode 100644 (file)
index 0000000..9d9dc61
--- /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-fl_fss
+
+version_major 0
+version_minor 6
+version_micro 4
+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 -lcmocka
+build_libraries-individual -lf_abstruse -lf_conversion -lf_file -lf_fss -lf_memory -lf_string -lf_type_array -lf_utf -lfl_fss
+
+build_sources_program test-fss-payload_header_map.c
+
+build_sources_program test-fss.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_1/fl_fss/tests/unit/c/test-fss-payload_header_map.c b/level_1/fl_fss/tests/unit/c/test-fss-payload_header_map.c
new file mode 100644 (file)
index 0000000..07c0eec
--- /dev/null
@@ -0,0 +1,78 @@
+#include "test-fss.h"
+#include "test-fss-payload_header_map.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__fl_fss_payload_header_map__parameter_checking(void **void_state) {
+
+  const f_abstruse_maps_t headers = f_abstruse_maps_t_initialize;
+  f_state_t state = f_state_t_initialize;
+  f_fss_payload_header_state_t data = f_fss_payload_header_state_t_initialize;
+  f_string_dynamic_t cache = f_string_dynamic_t_initialize;
+  f_string_maps_t destinations = f_string_maps_t_initialize;
+
+  {
+    state.status = F_none;
+    state.data = &data;
+    data.cache = &cache;
+
+    fl_fss_payload_header_map(headers, 0, &state);
+
+    assert_int_equal(state.status, F_status_set_error(F_parameter));
+  }
+
+  {
+    state.status = F_none;
+    state.data = 0;
+    data.cache = 0;
+
+    fl_fss_payload_header_map(headers, &destinations, &state);
+
+    assert_int_equal(state.status, F_status_set_error(F_parameter));
+  }
+
+  {
+    state.status = F_none;
+    state.data = &data;
+    data.cache = 0;
+
+    fl_fss_payload_header_map(headers, &destinations, &state);
+
+    assert_int_equal(state.status, F_status_set_error(F_parameter));
+  }
+
+  {
+    state.status = F_none;
+    state.data = 0;
+    data.cache = &cache;
+
+    fl_fss_payload_header_map(headers, &destinations, &state);
+
+    assert_int_equal(state.status, F_status_set_error(F_parameter));
+  }
+}
+
+void test__fl_fss_payload_header_map__returns_data_not(void **void_state) {
+
+  const f_abstruse_maps_t headers = f_abstruse_maps_t_initialize;
+  f_state_t state = f_state_t_initialize;
+  f_fss_payload_header_state_t data = f_fss_payload_header_state_t_initialize;
+  f_string_dynamic_t cache = f_string_dynamic_t_initialize;
+  f_string_maps_t destinations = f_string_maps_t_initialize;
+
+  {
+    state.status = F_none;
+    state.data = &data;
+    data.cache = &cache;
+
+    fl_fss_payload_header_map(headers, &destinations, &state);
+
+    assert_int_equal(state.status, F_data_not);
+  }
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_1/fl_fss/tests/unit/c/test-fss-payload_header_map.h b/level_1/fl_fss/tests/unit/c/test-fss-payload_header_map.h
new file mode 100644 (file)
index 0000000..930f40d
--- /dev/null
@@ -0,0 +1,28 @@
+/**
+ * FLL - Level 2
+ *
+ * Project: IKI
+ * API Version: 0.6
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the fl_fss project.
+ */
+#ifndef _TEST__FL_fss_payload_header_map_h
+#define _TEST__FL_fss_payload_header_map_h
+
+/**
+ * Test that parameter checking works as expected.
+ *
+ * @see fl_fss_payload_header_map()
+ */
+extern void test__fl_fss_payload_header_map__parameter_checking(void **state);
+
+/**
+ * Test that the function returns F_data_not.
+ *
+ * @see fl_fss_payload_header_map()
+ */
+extern void test__fl_fss_payload_header_map__returns_data_not(void **state);
+
+
+#endif // _TEST__FL_fss_payload_header_map_h
diff --git a/level_1/fl_fss/tests/unit/c/test-fss.c b/level_1/fl_fss/tests/unit/c/test-fss.c
new file mode 100644 (file)
index 0000000..d45ea3d
--- /dev/null
@@ -0,0 +1,34 @@
+#include "test-fss.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__fl_fss_payload_header_map__returns_data_not),
+
+    #ifndef _di_level_0_parameter_checking_
+      cmocka_unit_test(test__fl_fss_payload_header_map__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_1/fl_fss/tests/unit/c/test-fss.h b/level_1/fl_fss/tests/unit/c/test-fss.h
new file mode 100644 (file)
index 0000000..c1aba1d
--- /dev/null
@@ -0,0 +1,75 @@
+/**
+ * FLL - Level 2
+ *
+ * Project: FSS
+ * API Version: 0.6
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the fl_fss project.
+ */
+#ifndef _TEST__FL_fss_h
+#define _TEST__FL_fss_h
+
+// Libc includes.
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+// cmocka includes.
+#include <cmocka.h>
+
+// FLL-1 includes.
+#include <fll/level_1/fss.h>
+#include <fll/level_1/fss/payload.h>
+
+// Mock includes.
+//#include "mock-fss.h"
+
+// Test includes.
+#include "test-fss-payload_header_map.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__FL_fss_h