From d4e5e4dd5c513e47203b77d591fc25e2c23db6bd Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Sun, 17 Nov 2024 22:58:54 -0600 Subject: [PATCH] Feature: Add f_iki_write() along with appropriate unit tests. The `f_iki_write()` function is missing. Add appropriate unit tests. I also need to add tests with existing slashes. I think I noticed a bug in the IKI read functions regarding slashes and I will investigate that before I add such tests here. I will write the EKI write functions once I have done further review and fixed the likely IKI read bugs that I believe that I have observed. --- level_0/f_iki/c/iki.c | 110 ++++ level_0/f_iki/c/iki.h | 56 ++ level_0/f_iki/c/iki/common.h | 18 +- level_0/f_iki/data/build/settings-tests | 2 +- level_0/f_iki/tests/unit/c/test-iki-write.c | 952 ++++++++++++++++++++++++++++ level_0/f_iki/tests/unit/c/test-iki-write.h | 41 ++ level_0/f_iki/tests/unit/c/test-iki.c | 6 + level_0/f_iki/tests/unit/c/test-iki.h | 1 + 8 files changed, 1182 insertions(+), 4 deletions(-) create mode 100644 level_0/f_iki/tests/unit/c/test-iki-write.c create mode 100644 level_0/f_iki/tests/unit/c/test-iki-write.h diff --git a/level_0/f_iki/c/iki.c b/level_0/f_iki/c/iki.c index 54ab886..6d1fe65 100644 --- a/level_0/f_iki/c/iki.c +++ b/level_0/f_iki/c/iki.c @@ -1087,6 +1087,116 @@ extern "C" { } #endif // _di_f_iki_read_ +#ifndef _di_f_iki_write_ + void f_iki_write(const f_string_static_t vocabulary, const f_string_static_t content, const f_string_static_t quote, f_string_dynamic_t * const destination, f_state_t * const state) { + #ifndef _di_level_1_parameter_checking_ + if (!state) return; + + if (!destination || !quote.used || (quote.string[0] != f_iki_syntax_quote_double_s.string[0] && quote.string[0] != f_iki_syntax_quote_grave_s.string[0] && quote.string[0] != f_iki_syntax_quote_single_s.string[0])) { + state->status = F_status_set_error(F_parameter); + + return; + } + #endif // _di_level_1_parameter_checking_ + + if (!vocabulary.used) { + state->status = F_status_set_error(F_data_not); + + return; + } + + f_range_t range = macro_f_range_t_initialize_2(vocabulary.used); + f_number_unsigned_t i = 0; + + do { + if (state->interrupt) { + state->interrupt((void * const) state, 0); + if (F_status_set_fine(state->status) == F_interrupt) break; + } + + i = vocabulary.used - range.start; + + state->status = f_utf_is_word_dash_plus(vocabulary.string + range.start, i, F_false); + if (F_status_is_error(state->status)) break; + + if (state->status == F_false) { + state->status = F_status_set_error(F_syntax); + + break; + } + + state->status = f_utf_buffer_increment(vocabulary, &range, 1); + + } while (F_status_is_error_not(state->status) && range.start < range.stop); + + // Pre-allocate the expected size along with two extra slots for slashes to help reduce potential allocations. + if (F_status_is_error_not(state->status)) { + state->status = f_memory_array_increase_by(vocabulary.used + content.used + f_iki_syntax_wrap_close_s.used + f_iki_syntax_wrap_open_s.used + f_iki_syntax_separator_s.used + (f_iki_syntax_slash_s.used * 2) + (quote.used * 2), sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size); + } + + if (F_status_is_error_not(state->status) && (state->flag & f_iki_state_flag_force_wrap_e)) { + state->status = f_string_dynamic_append(f_iki_syntax_wrap_open_s, destination); + } + + if (F_status_is_error_not(state->status)) { + state->status = f_string_dynamic_append(vocabulary, destination); + } + + if (F_status_is_error_not(state->status) && (state->flag & f_iki_state_flag_force_wrap_e)) { + state->status = f_string_dynamic_append(f_iki_syntax_wrap_close_s, destination); + } + + if (F_status_is_error_not(state->status)) { + state->status = f_string_dynamic_append(f_iki_syntax_separator_s, destination); + } + + if (F_status_is_error_not(state->status)) { + state->status = f_string_dynamic_append(quote, destination); + } + + if (F_status_is_error_not(state->status)) { + range.start = 0; + range.stop = content.used - 1; + + for (i = 0; i < content.used; ++i) { + + if (content.string[i] == quote.string[0]) { + if (i) { + range.stop = i - 1; + + state->status = f_string_dynamic_partial_append(content, range, destination); + } + + if (F_status_is_error_not(state->status)) { + state->status = f_string_dynamic_append(f_iki_syntax_slash_s, destination); + } + + if (F_status_is_error_not(state->status)) { + state->status = f_string_dynamic_append(quote, destination); + } + + if (F_status_is_error(state->status)) break; + + range.start = i + 1; + range.stop = content.used - 1; + } + } // for + + if (F_status_is_error_not(state->status) && range.start <= range.stop) { + state->status = f_string_dynamic_partial_append(content, range, destination); + } + } + + if (F_status_is_error_not(state->status)) { + state->status = f_string_dynamic_append(quote, destination); + } + + if (F_status_is_error_not(state->status)) { + state->status = F_okay; + } + } +#endif // _di_f_iki_write_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_iki/c/iki.h b/level_0/f_iki/c/iki.h index 09c6510..4e2e98c 100644 --- a/level_0/f_iki/c/iki.h +++ b/level_0/f_iki/c/iki.h @@ -235,6 +235,62 @@ extern "C" { extern void f_iki_read(f_string_static_t * const buffer, f_range_t * const range, f_iki_data_t * const data, f_state_t * const state); #endif // _di_f_iki_read_ +/** + * Write an IKI vocabulary and content as an IKI string. + * + * Anything within this source strings will be escaped as necessary. + * + * The destination string may have NULLs. + * + * @param vocabulary + * The IKI vocabulary. + * + * The string must not have length of 0. + * @param content + * The IKI content. + * @param quote + * The quote to use. @todo replace this with a flag, also include wrapper. + * @param destination + * The buffer where the content is written to. + * + * Must not be NULL. + * @param state + * A state for providing flags and handling interrupts during long running operations. + * + * The following f_iki_state_flag_*_e are used: + * - force_wrap: Always use wrapping characters even when not strictly required. + * + * There is no state.handle(). + * There is no "callbacks" structure. + * There is no data structure passed to these functions. + * + * When state.interrupt() returns, only F_interrupt and F_interrupt_not are processed. + * Error bit designates an error but must be passed along with F_interrupt. + * + * Must not be NULL. + * + * This alters state.status: + * F_okay on success. + * + * F_data_not (with error bit) if either the vocabulary string has a length of 0. + * F_interrupt (with error bit) if stopping due to an interrupt. + * F_parameter (with error bit) if a parameter is invalid. + * F_syntax (with error bit) if the vocabulary has unsupported characters (NULL is ignored and does not produce this error). + * + * Errors (with error bit) from: f_memory_array_increase(). + * Errors (with error bit) from: f_string_dynamic_append(). + * Errors (with error bit) from: f_utf_buffer_increment(). + * Errors (with error bit) from: f_utf_is_word_dash_plus(). + * + * @see f_memory_array_increase() + * @see f_string_dynamic_append() + * @see f_utf_buffer_increment() + * @see f_utf_is_word_dash_plus() + */ +#ifndef _di_f_iki_write_ + extern void f_iki_write(const f_string_static_t vocabulary, const f_string_static_t content, const f_string_static_t quote, f_string_dynamic_t * const destination, f_state_t * const state); +#endif // _di_f_iki_write_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_iki/c/iki/common.h b/level_0/f_iki/c/iki/common.h index 92a2b4c..3edf095 100644 --- a/level_0/f_iki/c/iki/common.h +++ b/level_0/f_iki/c/iki/common.h @@ -21,7 +21,7 @@ extern "C" { * * For a UTF-8 friendly allocation step, set to at least 4. * - * F_iki_default_allocation_*: + * F_iki_default_allocation_*_d: * - console: An allocation step used for small buffers specifically for console parameter. * - large: The large allocation size. * - small: The small allocation size, in particular used for allocation iki strings. @@ -39,19 +39,31 @@ extern "C" { * * The f_iki_state_flag_none_e is expected to be 0, therefore it must be safe to use 0 directly. * - * f_iki_state_flag_*: + * f_iki_state_flag_*_e: * - none: No flags are set. + * - force_wrap: For IKI writing, this forces the use of wrapping characters even if this is not required. * - utf_fail_on_valid_not: Immediately fail on invalid UTF-8 character (including incomplete). */ #ifndef _di_f_iki_state_flag_e_ enum { f_iki_state_flag_none_e = 0x0, - f_iki_state_flag_utf_fail_on_valid_not_e = 0x1, + f_iki_state_flag_force_wrap_e = 0x1, + f_iki_state_flag_utf_fail_on_valid_not_e = 0x2, }; // enum #endif // _di_f_iki_state_flag_e_ /** * IKI-specific syntax. + * + * f_iki_syntax_*_e: + * - separator: The separator character used to separate the Vocabulary from the Content. + * - placeholder: The placeholder character (such as NULL), often used to remove delimits before printing. + * - quote_double: The double-quote character used for wrapping the Content. + * - quote_grave: The grave character used for wrapping the Content. + * - quote_single: The single-quote character used for wrapping the Content. + * - slash: The slash character used for escaping. + * - wrap_open: The wrapping character used at the start of a Vocabulary. + * - wrap_close: The separator character used at the stop of a Vocabulary. */ #ifndef _di_f_iki_syntax_s_ #define F_iki_syntax_separator_s F_string_ascii_colon_s diff --git a/level_0/f_iki/data/build/settings-tests b/level_0/f_iki/data/build/settings-tests index 294b995..33a6885 100644 --- a/level_0/f_iki/data/build/settings-tests +++ b/level_0/f_iki/data/build/settings-tests @@ -25,7 +25,7 @@ build_language c build_libraries -lc -lcmocka build_libraries-individual -lf_memory -lf_string -lf_type_array -lf_utf -lf_iki -build_sources_program test-iki-content_is.c test-iki-content_partial_is.c test-iki-eki_read.c test-iki-object_is.c test-iki-object_partial_is.c test-iki-read.c +build_sources_program test-iki-content_is.c test-iki-content_partial_is.c test-iki-eki_read.c test-iki-object_is.c test-iki-object_partial_is.c test-iki-read.c test-iki-write.c build_sources_program test-iki-datas_append.c test-iki-datas_append_all.c test-iki-datass_append.c test-iki-datass_append_all.c build_sources_program test-iki-datas_delete_callback.c test-iki-datas_destroy_callback.c test-iki-datass_delete_callback.c test-iki-datass_destroy_callback.c build_sources_program test-iki-ekis_append.c test-iki-ekis_append_all.c test-iki-ekiss_append.c test-iki-ekiss_append_all.c diff --git a/level_0/f_iki/tests/unit/c/test-iki-write.c b/level_0/f_iki/tests/unit/c/test-iki-write.c new file mode 100644 index 0000000..32d2164 --- /dev/null +++ b/level_0/f_iki/tests/unit/c/test-iki-write.c @@ -0,0 +1,952 @@ +#include "test-iki.h" +#include "test-iki-write.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_iki_write__parameter_checking(void **state) { + + f_state_t state_data = f_state_t_initialize; + f_string_dynamic_t destination = f_string_dynamic_t_initialize; + const f_string_static_t empty = macro_f_string_static_t_initialize_1(f_string_empty_s.string, f_string_empty_s.size, f_string_empty_s.used); + const f_string_static_t vocabulary = macro_f_string_static_t_initialize_1("vocabulary", 0, 10); + const f_string_static_t content = macro_f_string_static_t_initialize_1("content", 0, 7); + + state_data.status = F_known_not; + + { + f_iki_write(vocabulary, content, f_iki_syntax_quote_double_s, &destination, 0); + + // The state cannot be set to F_parameter because the state is not passed to the function. + assert_int_equal(state_data.status, F_known_not); + } + + { + f_iki_write(vocabulary, content, f_iki_syntax_quote_grave_s, &destination, 0); + + // The state cannot be set to F_parameter because the state is not passed to the function. + assert_int_equal(state_data.status, F_known_not); + } + + { + f_iki_write(vocabulary, content, f_iki_syntax_quote_single_s, &destination, 0); + + // The state cannot be set to F_parameter because the state is not passed to the function. + assert_int_equal(state_data.status, F_known_not); + } + + { + f_iki_write(vocabulary, content, f_iki_syntax_quote_double_s, 0, &state_data); + + assert_int_equal(state_data.status, F_status_set_error(F_parameter)); + } + + { + f_iki_write(vocabulary, content, empty, &destination, &state_data); + + assert_int_equal(state_data.status, F_status_set_error(F_parameter)); + } + + { + f_iki_write(vocabulary, content, content, &destination, &state_data); + + assert_int_equal(state_data.status, F_status_set_error(F_parameter)); + } +} + +void test__f_iki_write__returns_data_not(void **state) { + + f_state_t state_data = f_state_t_initialize; + f_string_dynamic_t destination = f_string_dynamic_t_initialize; + const f_string_static_t empty = macro_f_string_static_t_initialize_1(f_string_empty_s.string, f_string_empty_s.size, f_string_empty_s.used); + const f_string_static_t content = macro_f_string_static_t_initialize_1("content", 0, 7); + + { + f_iki_write(empty, content, f_iki_syntax_quote_double_s, &destination, &state_data); + + assert_int_equal(F_status_set_fine(state_data.status), F_data_not); + } + + { + f_iki_write(empty, content, f_iki_syntax_quote_grave_s, &destination, &state_data); + + assert_int_equal(F_status_set_fine(state_data.status), F_data_not); + } + + { + f_iki_write(empty, content, f_iki_syntax_quote_single_s, &destination, &state_data); + + assert_int_equal(F_status_set_fine(state_data.status), F_data_not); + } +} + +void test__f_iki_write__returns_syntax(void **state) { + + f_state_t state_data = f_state_t_initialize; + f_string_dynamic_t destination = f_string_dynamic_t_initialize; + const f_string_static_t content = macro_f_string_static_t_initialize_1("content", 0, 7); + const f_string_static_t str_colon = macro_f_string_static_t_initialize_1(":", 0, 1); + const f_string_static_t str_space = macro_f_string_static_t_initialize_1(" ", 0, 1); + const f_string_static_t str_at = macro_f_string_static_t_initialize_1("@", 0, 1); + const f_string_static_t str_bracket_open = macro_f_string_static_t_initialize_1("[", 0, 1); + const f_string_static_t str_bracket_close = macro_f_string_static_t_initialize_1("]", 0, 1); + const f_string_static_t str_lots = macro_f_string_static_t_initialize_1("This * is [never] going && to be...>%'`\" valid!", 0, 47); + + { + f_iki_write(str_colon, content, f_iki_syntax_quote_double_s, &destination, &state_data); + + assert_int_equal(F_status_set_fine(state_data.status), F_syntax); + } + + { + f_iki_write(str_space, content, f_iki_syntax_quote_double_s, &destination, &state_data); + + assert_int_equal(F_status_set_fine(state_data.status), F_syntax); + } + + { + f_iki_write(str_at, content, f_iki_syntax_quote_double_s, &destination, &state_data); + + assert_int_equal(F_status_set_fine(state_data.status), F_syntax); + } + + { + f_iki_write(str_bracket_open, content, f_iki_syntax_quote_double_s, &destination, &state_data); + + assert_int_equal(F_status_set_fine(state_data.status), F_syntax); + } + + { + f_iki_write(str_bracket_close, content, f_iki_syntax_quote_double_s, &destination, &state_data); + + assert_int_equal(F_status_set_fine(state_data.status), F_syntax); + } + + { + f_iki_write(str_lots, content, f_iki_syntax_quote_double_s, &destination, &state_data); + + assert_int_equal(F_status_set_fine(state_data.status), F_syntax); + } +} + +void test__f_iki_write__works(void **state) { + + mock_unwrap = 1; + + f_state_t state_data = f_state_t_initialize; + f_string_dynamic_t destination = f_string_dynamic_t_initialize; + + f_string_static_t empty = macro_f_string_static_t_initialize_1(f_string_empty_s.string, f_string_empty_s.size, f_string_empty_s.used); + f_string_static_t str_a = macro_f_string_static_t_initialize_1("a", 0, 1); + f_string_static_t str_b = macro_f_string_static_t_initialize_1("b", 0, 1); + f_string_static_t str_iki = macro_f_string_static_t_initialize_1("iki", 0, 3); + f_string_static_t str_has = macro_f_string_static_t_initialize_1("has_CHARS+-", 0, 11); + + f_string_static_t str_content = macro_f_string_static_t_initialize_1("content", 0, 7); + f_string_static_t str_content_quote_single = macro_f_string_static_t_initialize_1("'content'", 0, 9); + f_string_static_t str_content_quote_grave = macro_f_string_static_t_initialize_1("`content`", 0, 9); + f_string_static_t str_content_quote_double = macro_f_string_static_t_initialize_1("\"content\"", 0, 9); + f_string_static_t str_quote_single = macro_f_string_static_t_initialize_1("quote's", 0, 7); + f_string_static_t str_quote_grave = macro_f_string_static_t_initialize_1("quote`s", 0, 7); + f_string_static_t str_quote_double = macro_f_string_static_t_initialize_1("quote\"s", 0, 7); + + #define _inline_macro_total_rows 126 + + f_string_static_t vocabularys[] = { + str_a, + str_a, + str_a, + str_a, + str_a, + str_a, + str_a, + str_iki, + str_iki, + str_iki, + str_iki, + str_iki, + str_iki, + str_iki, + str_has, + str_has, + str_has, + str_has, + str_has, + str_has, + str_has, + str_a, + str_a, + str_a, + str_a, + str_a, + str_a, + str_a, + str_iki, + str_iki, + str_iki, + str_iki, + str_iki, + str_iki, + str_iki, + str_has, + str_has, + str_has, + str_has, + str_has, + str_has, + str_has, + str_a, + str_a, + str_a, + str_a, + str_a, + str_a, + str_a, + str_iki, + str_iki, + str_iki, + str_iki, + str_iki, + str_iki, + str_iki, + str_has, + str_has, + str_has, + str_has, + str_has, + str_has, + str_has, + str_a, + str_a, + str_a, + str_a, + str_a, + str_a, + str_a, + str_iki, + str_iki, + str_iki, + str_iki, + str_iki, + str_iki, + str_iki, + str_has, + str_has, + str_has, + str_has, + str_has, + str_has, + str_has, + str_a, + str_a, + str_a, + str_a, + str_a, + str_a, + str_a, + str_iki, + str_iki, + str_iki, + str_iki, + str_iki, + str_iki, + str_iki, + str_has, + str_has, + str_has, + str_has, + str_has, + str_has, + str_has, + str_a, + str_a, + str_a, + str_a, + str_a, + str_a, + str_a, + str_iki, + str_iki, + str_iki, + str_iki, + str_iki, + str_iki, + str_iki, + str_has, + str_has, + str_has, + str_has, + str_has, + str_has, + str_has, + }; + + f_string_static_t contents[] = { + empty, + str_b, + str_content, + str_content_quote_single, + str_quote_single, + str_quote_grave, + str_quote_double, + empty, + str_b, + str_content, + str_content_quote_single, + str_quote_single, + str_quote_grave, + str_quote_double, + empty, + str_b, + str_content, + str_content_quote_single, + str_quote_single, + str_quote_grave, + str_quote_double, + empty, + str_b, + str_content, + str_content_quote_grave, + str_quote_single, + str_quote_grave, + str_quote_double, + empty, + str_b, + str_content, + str_content_quote_grave, + str_quote_single, + str_quote_grave, + str_quote_double, + empty, + str_b, + str_content, + str_content_quote_grave, + str_quote_single, + str_quote_grave, + str_quote_double, + empty, + str_b, + str_content, + str_content_quote_double, + str_quote_single, + str_quote_grave, + str_quote_double, + empty, + str_b, + str_content, + str_content_quote_double, + str_quote_single, + str_quote_grave, + str_quote_double, + empty, + str_b, + str_content, + str_content_quote_double, + str_quote_single, + str_quote_grave, + str_quote_double, + empty, + str_b, + str_content, + str_content_quote_single, + str_quote_single, + str_quote_grave, + str_quote_double, + empty, + str_b, + str_content, + str_content_quote_single, + str_quote_single, + str_quote_grave, + str_quote_double, + empty, + str_b, + str_content, + str_content_quote_single, + str_quote_single, + str_quote_grave, + str_quote_double, + empty, + str_b, + str_content, + str_content_quote_grave, + str_quote_single, + str_quote_grave, + str_quote_double, + empty, + str_b, + str_content, + str_content_quote_grave, + str_quote_single, + str_quote_grave, + str_quote_double, + empty, + str_b, + str_content, + str_content_quote_grave, + str_quote_single, + str_quote_grave, + str_quote_double, + empty, + str_b, + str_content, + str_content_quote_double, + str_quote_single, + str_quote_grave, + str_quote_double, + empty, + str_b, + str_content, + str_content_quote_double, + str_quote_single, + str_quote_grave, + str_quote_double, + empty, + str_b, + str_content, + str_content_quote_double, + str_quote_single, + str_quote_grave, + str_quote_double, + }; + + f_string_static_t quotes[] = { + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_single_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_grave_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + f_iki_syntax_quote_double_s, + }; + + uint64_t flags[] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + f_iki_state_flag_force_wrap_e, + }; + + f_string_static_t ikis[] = { + macro_f_string_static_t_initialize_1("a:''", 0, 4), + macro_f_string_static_t_initialize_1("a:'b'", 0, 5), + macro_f_string_static_t_initialize_1("a:'content'", 0, 11), + macro_f_string_static_t_initialize_1("a:'\\'content\\''", 0, 15), + macro_f_string_static_t_initialize_1("a:'quote\\'s'", 0, 12), + macro_f_string_static_t_initialize_1("a:'quote`s'", 0, 11), + macro_f_string_static_t_initialize_1("a:'quote\"s'", 0, 11), + macro_f_string_static_t_initialize_1("iki:''", 0, 6), + macro_f_string_static_t_initialize_1("iki:'b'", 0, 7), + macro_f_string_static_t_initialize_1("iki:'content'", 0, 13), + macro_f_string_static_t_initialize_1("iki:'\\'content\\''", 0, 17), + macro_f_string_static_t_initialize_1("iki:'quote\\'s'", 0, 14), + macro_f_string_static_t_initialize_1("iki:'quote`s'", 0, 13), + macro_f_string_static_t_initialize_1("iki:'quote\"s'", 0, 13), + macro_f_string_static_t_initialize_1("has_CHARS+-:''", 0, 14), + macro_f_string_static_t_initialize_1("has_CHARS+-:'b'", 0, 15), + macro_f_string_static_t_initialize_1("has_CHARS+-:'content'", 0, 21), + macro_f_string_static_t_initialize_1("has_CHARS+-:'\\'content\\''", 0, 25), + macro_f_string_static_t_initialize_1("has_CHARS+-:'quote\\'s'", 0, 22), + macro_f_string_static_t_initialize_1("has_CHARS+-:'quote`s'", 0, 21), + macro_f_string_static_t_initialize_1("has_CHARS+-:'quote\"s'", 0, 21), + macro_f_string_static_t_initialize_1("a:``", 0, 4), + macro_f_string_static_t_initialize_1("a:`b`", 0, 5), + macro_f_string_static_t_initialize_1("a:`content`", 0, 11), + macro_f_string_static_t_initialize_1("a:`\\`content\\``", 0, 15), + macro_f_string_static_t_initialize_1("a:`quote's`", 0, 11), + macro_f_string_static_t_initialize_1("a:`quote\\`s`", 0, 12), + macro_f_string_static_t_initialize_1("a:`quote\"s`", 0, 11), + macro_f_string_static_t_initialize_1("iki:``", 0, 6), + macro_f_string_static_t_initialize_1("iki:`b`", 0, 7), + macro_f_string_static_t_initialize_1("iki:`content`", 0, 13), + macro_f_string_static_t_initialize_1("iki:`\\`content\\``", 0, 17), + macro_f_string_static_t_initialize_1("iki:`quote's`", 0, 13), + macro_f_string_static_t_initialize_1("iki:`quote\\`s`", 0, 14), + macro_f_string_static_t_initialize_1("iki:`quote\"s`", 0, 13), + macro_f_string_static_t_initialize_1("has_CHARS+-:``", 0, 14), + macro_f_string_static_t_initialize_1("has_CHARS+-:`b`", 0, 15), + macro_f_string_static_t_initialize_1("has_CHARS+-:`content`", 0, 21), + macro_f_string_static_t_initialize_1("has_CHARS+-:`\\`content\\``", 0, 25), + macro_f_string_static_t_initialize_1("has_CHARS+-:`quote's`", 0, 21), + macro_f_string_static_t_initialize_1("has_CHARS+-:`quote\\`s`", 0, 22), + macro_f_string_static_t_initialize_1("has_CHARS+-:`quote\"s`", 0, 21), + macro_f_string_static_t_initialize_1("a:\"\"", 0, 4), + macro_f_string_static_t_initialize_1("a:\"b\"", 0, 5), + macro_f_string_static_t_initialize_1("a:\"content\"", 0, 11), + macro_f_string_static_t_initialize_1("a:\"\\\"content\\\"\"", 0, 15), + macro_f_string_static_t_initialize_1("a:\"quote's\"", 0, 11), + macro_f_string_static_t_initialize_1("a:\"quote`s\"", 0, 11), + macro_f_string_static_t_initialize_1("a:\"quote\\\"s\"", 0, 12), + macro_f_string_static_t_initialize_1("iki:\"\"", 0, 6), + macro_f_string_static_t_initialize_1("iki:\"b\"", 0, 7), + macro_f_string_static_t_initialize_1("iki:\"content\"", 0, 13), + macro_f_string_static_t_initialize_1("iki:\"\\\"content\\\"\"", 0, 17), + macro_f_string_static_t_initialize_1("iki:\"quote's\"", 0, 13), + macro_f_string_static_t_initialize_1("iki:\"quote`s\"", 0, 13), + macro_f_string_static_t_initialize_1("iki:\"quote\\\"s\"", 0, 14), + macro_f_string_static_t_initialize_1("has_CHARS+-:\"\"", 0, 14), + macro_f_string_static_t_initialize_1("has_CHARS+-:\"b\"", 0, 15), + macro_f_string_static_t_initialize_1("has_CHARS+-:\"content\"", 0, 21), + macro_f_string_static_t_initialize_1("has_CHARS+-:\"\\\"content\\\"\"", 0, 25), + macro_f_string_static_t_initialize_1("has_CHARS+-:\"quote's\"", 0, 21), + macro_f_string_static_t_initialize_1("has_CHARS+-:\"quote`s\"", 0, 21), + macro_f_string_static_t_initialize_1("has_CHARS+-:\"quote\\\"s\"", 0, 22), + macro_f_string_static_t_initialize_1("[a]:''", 0, 6), + macro_f_string_static_t_initialize_1("[a]:'b'", 0, 7), + macro_f_string_static_t_initialize_1("[a]:'content'", 0, 13), + macro_f_string_static_t_initialize_1("[a]:'\\'content\\''", 0, 17), + macro_f_string_static_t_initialize_1("[a]:'quote\\'s'", 0, 14), + macro_f_string_static_t_initialize_1("[a]:'quote`s'", 0, 13), + macro_f_string_static_t_initialize_1("[a]:'quote\"s'", 0, 13), + macro_f_string_static_t_initialize_1("[iki]:''", 0, 8), + macro_f_string_static_t_initialize_1("[iki]:'b'", 0, 9), + macro_f_string_static_t_initialize_1("[iki]:'content'", 0, 15), + macro_f_string_static_t_initialize_1("[iki]:'\\'content\\''", 0, 19), + macro_f_string_static_t_initialize_1("[iki]:'quote\\'s'", 0, 16), + macro_f_string_static_t_initialize_1("[iki]:'quote`s'", 0, 15), + macro_f_string_static_t_initialize_1("[iki]:'quote\"s'", 0, 15), + macro_f_string_static_t_initialize_1("[has_CHARS+-]:''", 0, 16), + macro_f_string_static_t_initialize_1("[has_CHARS+-]:'b'", 0, 17), + macro_f_string_static_t_initialize_1("[has_CHARS+-]:'content'", 0, 23), + macro_f_string_static_t_initialize_1("[has_CHARS+-]:'\\'content\\''", 0, 27), + macro_f_string_static_t_initialize_1("[has_CHARS+-]:'quote\\'s'", 0, 24), + macro_f_string_static_t_initialize_1("[has_CHARS+-]:'quote`s'", 0, 23), + macro_f_string_static_t_initialize_1("[has_CHARS+-]:'quote\"s'", 0, 23), + macro_f_string_static_t_initialize_1("[a]:``", 0, 6), + macro_f_string_static_t_initialize_1("[a]:`b`", 0, 7), + macro_f_string_static_t_initialize_1("[a]:`content`", 0, 13), + macro_f_string_static_t_initialize_1("[a]:`\\`content\\``", 0, 17), + macro_f_string_static_t_initialize_1("[a]:`quote's`", 0, 13), + macro_f_string_static_t_initialize_1("[a]:`quote\\`s`", 0, 14), + macro_f_string_static_t_initialize_1("[a]:`quote\"s`", 0, 13), + macro_f_string_static_t_initialize_1("[iki]:``", 0, 8), + macro_f_string_static_t_initialize_1("[iki]:`b`", 0, 9), + macro_f_string_static_t_initialize_1("[iki]:`content`", 0, 15), + macro_f_string_static_t_initialize_1("[iki]:`\\`content\\``", 0, 19), + macro_f_string_static_t_initialize_1("[iki]:`quote's`", 0, 15), + macro_f_string_static_t_initialize_1("[iki]:`quote\\`s`", 0, 16), + macro_f_string_static_t_initialize_1("[iki]:`quote\"s`", 0, 15), + macro_f_string_static_t_initialize_1("[has_CHARS+-]:``", 0, 16), + macro_f_string_static_t_initialize_1("[has_CHARS+-]:`b`", 0, 17), + macro_f_string_static_t_initialize_1("[has_CHARS+-]:`content`", 0, 23), + macro_f_string_static_t_initialize_1("[has_CHARS+-]:`\\`content\\``", 0, 27), + macro_f_string_static_t_initialize_1("[has_CHARS+-]:`quote's`", 0, 23), + macro_f_string_static_t_initialize_1("[has_CHARS+-]:`quote\\`s`", 0, 24), + macro_f_string_static_t_initialize_1("[has_CHARS+-]:`quote\"s`", 0, 23), + macro_f_string_static_t_initialize_1("[a]:\"\"", 0, 6), + macro_f_string_static_t_initialize_1("[a]:\"b\"", 0, 7), + macro_f_string_static_t_initialize_1("[a]:\"content\"", 0, 13), + macro_f_string_static_t_initialize_1("[a]:\"\\\"content\\\"\"", 0, 17), + macro_f_string_static_t_initialize_1("[a]:\"quote's\"", 0, 13), + macro_f_string_static_t_initialize_1("[a]:\"quote`s\"", 0, 13), + macro_f_string_static_t_initialize_1("[a]:\"quote\\\"s\"", 0, 14), + macro_f_string_static_t_initialize_1("[iki]:\"\"", 0, 8), + macro_f_string_static_t_initialize_1("[iki]:\"b\"", 0, 9), + macro_f_string_static_t_initialize_1("[iki]:\"content\"", 0, 15), + macro_f_string_static_t_initialize_1("[iki]:\"\\\"content\\\"\"", 0, 19), + macro_f_string_static_t_initialize_1("[iki]:\"quote's\"", 0, 15), + macro_f_string_static_t_initialize_1("[iki]:\"quote`s\"", 0, 15), + macro_f_string_static_t_initialize_1("[iki]:\"quote\\\"s\"", 0, 16), + macro_f_string_static_t_initialize_1("[has_CHARS+-]:\"\"", 0, 16), + macro_f_string_static_t_initialize_1("[has_CHARS+-]:\"b\"", 0, 17), + macro_f_string_static_t_initialize_1("[has_CHARS+-]:\"content\"", 0, 23), + macro_f_string_static_t_initialize_1("[has_CHARS+-]:\"\\\"content\\\"\"", 0, 27), + macro_f_string_static_t_initialize_1("[has_CHARS+-]:\"quote's\"", 0, 23), + macro_f_string_static_t_initialize_1("[has_CHARS+-]:\"quote`s\"", 0, 23), + macro_f_string_static_t_initialize_1("[has_CHARS+-]:\"quote\\\"s\"", 0, 24), + }; + + const f_status_t statuss[] = { + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + F_okay, + }; + + for (uint8_t i = 0; i < _inline_macro_total_rows; ++i) { + + state_data.flag = flags[i]; + destination.used = 0; + + f_iki_write(vocabularys[i], contents[i], quotes[i], &destination, &state_data); + + assert_int_equal(state_data.status, statuss[i]); + assert_int_equal(destination.used, ikis[i].used); + assert_string_equal(destination.string, ikis[i].string); + + // Clear the string to make any debugging easier. + memset(destination.string, 0, sizeof(destination.used)); + } // for + + if (destination.string) free(destination.string); + + #undef _inline_macro_total_rows +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_iki/tests/unit/c/test-iki-write.h b/level_0/f_iki/tests/unit/c/test-iki-write.h new file mode 100644 index 0000000..9eb8739 --- /dev/null +++ b/level_0/f_iki/tests/unit/c/test-iki-write.h @@ -0,0 +1,41 @@ +/** + * FLL - Level 0 + * + * Project: IKI + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the iki project. + */ +#ifndef _TEST__F_iki_write_h +#define _TEST__F_iki_write_h + +/** + * Test that parameter checking works as expected. + * + * @see f_iki_write() + */ +extern void test__f_iki_write__parameter_checking(void **state); + +/** + * Test that function returns F_data_not. + * + * @see f_iki_write() + */ +extern void test__f_iki_write__returns_data_not(void **state); + +/** + * Test that function returns F_syntax. + * + * @see f_iki_write() + */ +extern void test__f_iki_write__returns_syntax(void **state); + +/** + * Test that function works. + * + * @see f_iki_write() + */ +extern void test__f_iki_write__works(void **state); + +#endif // _TEST__F_iki_write_h diff --git a/level_0/f_iki/tests/unit/c/test-iki.c b/level_0/f_iki/tests/unit/c/test-iki.c index fefd70e..0b89212 100644 --- a/level_0/f_iki/tests/unit/c/test-iki.c +++ b/level_0/f_iki/tests/unit/c/test-iki.c @@ -87,6 +87,10 @@ int main(void) { cmocka_unit_test(test__f_iki_read__returns_data_not_stop), cmocka_unit_test(test__f_iki_read__works), + cmocka_unit_test(test__f_iki_write__returns_data_not), + cmocka_unit_test(test__f_iki_write__returns_syntax), + cmocka_unit_test(test__f_iki_write__works), + #ifndef _di_level_0_parameter_checking_ cmocka_unit_test(test__f_iki_content_is__parameter_checking), cmocka_unit_test(test__f_iki_content_partial_is__parameter_checking), @@ -119,6 +123,8 @@ int main(void) { // f_iki_object_partial_is() doesn't use parameter checking. cmocka_unit_test(test__f_iki_read__parameter_checking), + + cmocka_unit_test(test__f_iki_write__parameter_checking), #endif // _di_level_0_parameter_checking_ }; diff --git a/level_0/f_iki/tests/unit/c/test-iki.h b/level_0/f_iki/tests/unit/c/test-iki.h index d60a527..379bf88 100644 --- a/level_0/f_iki/tests/unit/c/test-iki.h +++ b/level_0/f_iki/tests/unit/c/test-iki.h @@ -48,6 +48,7 @@ #include "test-iki-object_is.h" #include "test-iki-object_partial_is.h" #include "test-iki-read.h" +#include "test-iki-write.h" #ifdef __cplusplus extern "C" { -- 1.8.3.1