From: Kevin Day Date: Fri, 19 Jan 2024 03:54:52 +0000 (-0600) Subject: Progress: Continue adding FSS Payload processing code. X-Git-Url: https://git.kevux.org/?a=commitdiff_plain;h=f5a7502ac27f24ab2dc69a4f6293c312bf6604de;p=fll Progress: Continue adding FSS Payload processing code. 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. --- diff --git a/level_0/f_abstruse/c/abstruse/map.h b/level_0/f_abstruse/c/abstruse/map.h index dce5e8d..39e1f5a 100644 --- a/level_0/f_abstruse/c/abstruse/map.h +++ b/level_0/f_abstruse/c/abstruse/map.h @@ -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 } diff --git a/level_0/f_abstruse/tests/unit/c/mock-abstruse.h b/level_0/f_abstruse/tests/unit/c/mock-abstruse.h index 4dcb9f0..f145865 100644 --- a/level_0/f_abstruse/tests/unit/c/mock-abstruse.h +++ b/level_0/f_abstruse/tests/unit/c/mock-abstruse.h @@ -1,7 +1,7 @@ /** * FLL - Level 0 * - * Project: IKI + * Project: Abstruse * API Version: 0.7 * Licenses: lgpl-2.1-or-later * diff --git a/level_0/f_fss/c/fss/payload.h b/level_0/f_fss/c/fss/payload.h index 906e08b..6992f39 100644 --- a/level_0/f_fss/c/fss/payload.h +++ b/level_0/f_fss/c/fss/payload.h @@ -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_ diff --git a/level_1/fl_fss/c/fss/payload.c b/level_1/fl_fss/c/fss/payload.c index b397e81..4974adc 100644 --- a/level_1/fl_fss/c/fss/payload.c +++ b/level_1/fl_fss/c/fss/payload.c @@ -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; diff --git a/level_1/fl_fss/c/fss/payload.h b/level_1/fl_fss/c/fss/payload.h index 4b43e6d..6f18ec8 100644 --- a/level_1/fl_fss/c/fss/payload.h +++ b/level_1/fl_fss/c/fss/payload.h @@ -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(). diff --git a/level_1/fl_fss/c/fss/payload/define.h b/level_1/fl_fss/c/fss/payload/define.h index c91d70f..5595469 100644 --- a/level_1/fl_fss/c/fss/payload/define.h +++ b/level_1/fl_fss/c/fss/payload/define.h @@ -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)) { \ diff --git a/level_1/fl_fss/c/fss/payload/type.h b/level_1/fl_fss/c/fss/payload/type.h index 609a2ca..a4b3392 100644 --- a/level_1/fl_fss/c/fss/payload/type.h +++ b/level_1/fl_fss/c/fss/payload/type.h @@ -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, \ } diff --git a/level_1/fl_fss/c/fss/private-payload.c b/level_1/fl_fss/c/fss/private-payload.c index a1be9ee..a32df60 100644 --- a/level_1/fl_fss/c/fss/private-payload.c +++ b/level_1/fl_fss/c/fss/private-payload.c @@ -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; diff --git a/level_1/fl_fss/c/fss/private-payload.h b/level_1/fl_fss/c/fss/private-payload.h index 9fe91ba..c816e5d 100644 --- a/level_1/fl_fss/c/fss/private-payload.h +++ b/level_1/fl_fss/c/fss/private-payload.h @@ -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 index 0000000..dea3179 --- /dev/null +++ b/level_1/fl_fss/data/build/dependencies-tests @@ -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 index 0000000..9d9dc61 --- /dev/null +++ b/level_1/fl_fss/data/build/settings-tests @@ -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 index 0000000..07c0eec --- /dev/null +++ b/level_1/fl_fss/tests/unit/c/test-fss-payload_header_map.c @@ -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 index 0000000..930f40d --- /dev/null +++ b/level_1/fl_fss/tests/unit/c/test-fss-payload_header_map.h @@ -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 index 0000000..d45ea3d --- /dev/null +++ b/level_1/fl_fss/tests/unit/c/test-fss.c @@ -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 index 0000000..c1aba1d --- /dev/null +++ b/level_1/fl_fss/tests/unit/c/test-fss.h @@ -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 +#include +#include +#include +#include +#include + +// cmocka includes. +#include + +// FLL-1 includes. +#include +#include + +// 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