From f306594e68101ab6e409304324d4e4366f70a3e1 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Tue, 27 Oct 2026 23:34:51 -0500 Subject: [PATCH] Progress: Continue work. --- .../generate_codepoints_from_digits.sh | 2 + level_0/f_fss/c/fss.c | 4 +- level_0/f_fss/c/fss.h | 49 +++++++++--- level_0/f_fss/c/private-fss.c | 76 +++++++++++++------ level_0/f_fss/c/private-fss.h | 49 +++++++++++- .../c/test-fss-skip_past_combining_joiner.c | 64 ++++++++++------ .../tests/unit/c/test-fss-skip_past_space.c | 24 +++--- .../c/test-fss-skip_past_space_previous.c | 37 +++++++-- level_1/fl_fss/c/fss/basic_list.c | 3 +- level_1/fl_fss/c/fss/embedded_list.c | 10 ++- level_1/fl_fss/c/fss/extended_list.c | 4 +- level_1/fl_fss/c/private-fss-list.c | 28 ++++--- 12 files changed, 256 insertions(+), 94 deletions(-) diff --git a/build/scripts/generate_codepoints_from_digits.sh b/build/scripts/generate_codepoints_from_digits.sh index bf4af145c..c4878d916 100644 --- a/build/scripts/generate_codepoints_from_digits.sh +++ b/build/scripts/generate_codepoints_from_digits.sh @@ -7,6 +7,8 @@ # For example, given the Private Use Area range U+E000 to U+F8FF look like: # ./generate_codepoints_from_digits.sh 57344 63743 # +# TODO: review this script...it looks like its creating the UTF8-sequences rather than the Unicode value, for example U+0-36F is integer 52623 and this prints U+CDAF, which is entirely wrong for the U+ value but is in fact the bytecode sequence 0xcdaf. +# main() { local IFS=$' \t\n' # Prevent IFS exploits by overriding with a local scope. diff --git a/level_0/f_fss/c/fss.c b/level_0/f_fss/c/fss.c index a0e5029c5..938df4d2a 100644 --- a/level_0/f_fss/c/fss.c +++ b/level_0/f_fss/c/fss.c @@ -562,9 +562,7 @@ extern "C" { return; } - f_number_unsigned_t previous = range->start; - - private_f_fss_skip_past_space_previous(buffer, range, state, &previous); + private_f_fss_skip_past_space_previous(buffer, range, state, 0); } #endif // _di_f_fss_skip_past_space_ diff --git a/level_0/f_fss/c/fss.h b/level_0/f_fss/c/fss.h index bd811b9c5..ed0caefa2 100644 --- a/level_0/f_fss/c/fss.h +++ b/level_0/f_fss/c/fss.h @@ -206,6 +206,14 @@ extern "C" { * * F_interrupt (with error bit) if stopping due to an interrupt. * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from f_utf_buffer_increment(). + * Errors (with error bit) from f_utf_is_combining(). + * Errors (with error bit) from f_utf_is_joiner(). + * + * @see f_utf_buffer_increment() + * @see f_utf_is_combining() + * @see f_utf_is_joiner() */ #ifndef _di_f_fss_count_slash_ extern void f_fss_count_slash(const f_string_static_t buffer, f_range_t * const range, f_number_unsigned_t * const count, f_state_t * const state); @@ -525,9 +533,9 @@ extern "C" { * * This alters state.status: * F_okay on success. - * F_data_not on success but buffer.used is 0, initial range.start is greater than range.stop, or initial range.start is greater than or equal to buffer.used. * F_okay_eos on success and EOS was reached. * F_okay_stop on success and stop point was reached. + * F_data_not on success but buffer.used is 0, initial range.start is greater than range.stop, or initial range.start is greater than or equal to buffer.used. * * F_interrupt (with error bit) if stopping due to an interrupt. * F_parameter (with error bit) if a parameter is invalid. @@ -561,12 +569,12 @@ extern "C" { * * This alters state.status: * F_okay on success and last skipped (if any) character is neither a combining character nor a joiner character. - * F_bound on success and last skipped character is a joiner character (future versions will provide a more accurate status, like F_join). - * F_combarudoo on success and last skipped character is a combining character (future versions will provide a more accurate status, like F_combine). - * F_data_not on success but buffer.used is 0, initial range.start is greater than range.stop, or initial range.start is greater than or equal to buffer.used. * F_okay_eol on success and EOL was reached. * F_okay_eos on success and EOS was reached. * F_okay_stop on success and stop point was reached. + * F_bound on success and last skipped character is a joiner character (future versions will provide a more accurate status, like F_join). + * F_combarudoo on success and last skipped character is a combining character (future versions will provide a more accurate status, like F_combine). + * F_data_not on success but buffer.used is 0, initial range.start is greater than range.stop, or initial range.start is greater than or equal to buffer.used. * * F_complete_not_utf_eos (with error bit) if unable to get entire UTF-8 sequence due to EOS. * F_complete_not_utf_start (with error bit) if the first character is a combining character. @@ -574,9 +582,13 @@ extern "C" { * F_interrupt (with error bit) if stopping due to an interrupt. * F_parameter (with error bit) if a parameter is invalid. * + * Errors (with error bit) from: f_utf_is_combining(). * Errors (with error bit) from: f_utf_is_combining_joiner(). + * Errors (with error bit) from: f_utf_is_joiner(). * + * @see f_utf_is_combining() * @see f_utf_is_combining_joiner() + * @see f_utf_is_joiner() */ #ifndef _di_f_fss_skip_past_combining_joiner_ extern void f_fss_skip_past_combining_joiner(const f_string_static_t buffer, f_range_t * const range, f_state_t * const state); @@ -619,8 +631,10 @@ extern "C" { * This is because combining characters apply from right to left. * The caller should check the return status and handle accordingly in this situation. * - * White space is checked for combining characters after the white space. - * If there is a combining character after, then the white space is not consider as such. + * White space is checked for combining/joiner characters after the white space. + * If there is a combining/joiner character after, then the white space is not consider as such. + * This does not reset the position to the space when there is a combining/joiner character after it. + * The status code informs the on whether stopped on combining or joiner and caller needs handle going back to the previous character as needed. * * This skips past place holders. * @@ -651,15 +665,19 @@ extern "C" { * F_interrupt (with error bit) if stopping due to an interrupt. * F_parameter (with error bit) if a parameter is invalid. * + * Errors (with error bit) from: f_utf_is_combining(). * Errors (with error bit) from: f_utf_is_combining_joiner(). + * Errors (with error bit) from: f_utf_is_joiner(). * Errors (with error bit) from: f_utf_is_control(). * Errors (with error bit) from: f_utf_is_whitespace(). - * Errors (with error bit) from: f_utf_is_zero_width(). + * Errors (with error bit) from: f_utf_is_zero_width_simple(). * + * @see f_utf_is_combining() * @see f_utf_is_combining_joiner() + * @see f_utf_is_joiner() * @see f_utf_is_control() * @see f_utf_is_whitespace() - * @see f_utf_is_zero_width() + * @see f_utf_is_zero_width_simple() */ #ifndef _di_f_fss_skip_past_space_ extern void f_fss_skip_past_space(const f_string_static_t buffer, f_range_t * const range, f_state_t * const state); @@ -672,8 +690,11 @@ extern "C" { * This is because combining characters apply from right to left. * The caller should check the return status and handle accordingly in this situation. * - * White space is checked for combining characters after the white space. - * If there is a combining character after, then the white space is not consider as such. + * White space is checked for combining/joiner characters after the white space. + * If there is a combining/joiner character after, then the white space is not consider as such. + * This does not reset the position to the space when there is a combining/joiner character after it. + * The status code informs the on whether stopped on combining or joiner and caller needs handle going back to the previous character as needed. + * The previous stores that position. * * This skips past place holders. * @@ -705,10 +726,12 @@ extern "C" { * F_interrupt (with error bit) if stopping due to an interrupt. * F_parameter (with error bit) if a parameter is invalid. * + * Errors (with error bit) from: f_utf_is_combining(). * Errors (with error bit) from: f_utf_is_combining_joiner(). + * Errors (with error bit) from: f_utf_is_joiner(). * Errors (with error bit) from: f_utf_is_control(). * Errors (with error bit) from: f_utf_is_whitespace(). - * Errors (with error bit) from: f_utf_is_zero_width(). + * Errors (with error bit) from: f_utf_is_zero_width_simple(). * @param previous * The previous position before the last stop point that is a valid character. * @@ -719,10 +742,12 @@ extern "C" { * * Must not be NULL. * + * @see f_utf_is_combining() * @see f_utf_is_combining_joiner() + * @see f_utf_is_joiner() * @see f_utf_is_control() * @see f_utf_is_whitespace() - * @see f_utf_is_zero_width() + * @see f_utf_is_zero_width_simple() */ #ifndef _di_f_fss_skip_past_space_previous_ extern void f_fss_skip_past_space_previous(const f_string_static_t buffer, f_range_t * const range, f_state_t * const state, f_number_unsigned_t * const previous); diff --git a/level_0/f_fss/c/private-fss.c b/level_0/f_fss/c/private-fss.c index 359a0d7dc..778c390d8 100644 --- a/level_0/f_fss/c/private-fss.c +++ b/level_0/f_fss/c/private-fss.c @@ -126,7 +126,7 @@ extern "C" { continue; } - state->status = f_utf_is_combining_joiner( + state->status = f_utf_is_combining( buffer.string + range->start, (range->stop - range->start) + 1 > buffer.used - range->start ? buffer.used - range->start @@ -135,6 +135,25 @@ extern "C" { f_fss_fail_utf_to_false(state); + if (state->status == F_true) { + flag_f = ___f_flag_last_combining___; + } + else if (F_status_is_error_not(state->status)) { + state->status = f_utf_is_joiner( + buffer.string + range->start, + (range->stop - range->start) + 1 > buffer.used - range->start + ? buffer.used - range->start + : (range->stop - range->start) + 1 + ); + + if (state->status == F_true) { + flag_f = ___f_flag_last_joiner___; + } + else { + f_fss_fail_utf_to_false(state); + } + } + if (state->status == F_false) break; if (F_status_is_error(state->status)) return; @@ -157,19 +176,12 @@ extern "C" { } range->start += macro_f_utf_byte_width(buffer.string[range->start]); - - if (state->status == F_bound) { - flag_f = ___f_flag_last_combining___; - } - else if (state->status == F_combarudoo) { - flag_f = ___f_flag_last_joiner___; - } } // for state->status = flag_f & ___f_flag_last_combining___ - ? F_bound + ? F_combarudoo : flag_f & ___f_flag_last_joiner___ - ? F_combarudoo + ? F_bound : F_okay; #undef ___f_flag_last_combining___ @@ -281,23 +293,40 @@ extern "C" { f_fss_fail_utf_to_false(state); if (state->status == F_false) { - state->status = f_utf_is_combining_joiner( + state->status = f_utf_is_combining( buffer.string + range->start, (range->stop - range->start) + 1 > buffer.used - range->start ? buffer.used - range->start : (range->stop - range->start) + 1 ); + if (state->status == F_true) { + state->status = F_combarudoo; + + return; + } + f_fss_fail_utf_to_false(state); - // This is combining, so any previous white space is no longer considered white space as such. - if (state->status == F_true) { - range->start = *previous; + if (F_status_is_error_not(state->status)) { + state->status = f_utf_is_joiner( + buffer.string + range->start, + (range->stop - range->start) + 1 > buffer.used - range->start + ? buffer.used - range->start + : (range->stop - range->start) + 1 + ); + + if (state->status == F_true) { + state->status = F_bound; - break; + return; + } + + f_fss_fail_utf_to_false(state); } - if (state->status == F_false) { + // Handle all other forms of zero-width. + if (F_status_is_error_not(state->status)) { state->status = f_utf_is_control( buffer.string + range->start, (range->stop - range->start) + 1 > buffer.used - range->start @@ -308,7 +337,7 @@ extern "C" { f_fss_fail_utf_to_false(state); if (state->status == F_false) { - state->status = f_utf_is_zero_width( + state->status = f_utf_is_zero_width_simple( buffer.string + range->start, (range->stop - range->start) + 1 > buffer.used - range->start ? buffer.used - range->start @@ -316,6 +345,7 @@ extern "C" { ); f_fss_fail_utf_to_false(state); + if (state->status == F_false) break; } } @@ -323,10 +353,12 @@ extern "C" { if (F_status_is_error(state->status)) return; - *previous = range->start; + if (previous) { + *previous = range->start; + } - if (macro_f_utf_byte_width_is(buffer.string[*previous])) { - if (*previous + macro_f_utf_byte_width(buffer.string[*previous]) >= buffer.used) { + if (macro_f_utf_byte_width_is(buffer.string[range->start])) { + if (range->start + macro_f_utf_byte_width(buffer.string[range->start]) >= buffer.used) { state->status = F_status_set_error(F_complete_not_utf_eos); f_fss_fail_utf(state); @@ -334,7 +366,7 @@ extern "C" { return; } - if (*previous + macro_f_utf_byte_width(buffer.string[*previous]) > range->stop) { + if (range->start + macro_f_utf_byte_width(buffer.string[range->start]) > range->stop) { state->status = F_status_set_error(F_complete_not_utf_stop); f_fss_fail_utf(state); @@ -343,7 +375,7 @@ extern "C" { } } - range->start += macro_f_utf_byte_width(buffer.string[*previous]); + range->start += macro_f_utf_byte_width(buffer.string[range->start]); } // for state->status = F_okay; diff --git a/level_0/f_fss/c/private-fss.h b/level_0/f_fss/c/private-fss.h index 3d462484f..f72bcc224 100644 --- a/level_0/f_fss/c/private-fss.h +++ b/level_0/f_fss/c/private-fss.h @@ -55,8 +55,12 @@ extern "C" { * F_parameter (with error bit) if a parameter is invalid. * * Errors (with error bit) from f_utf_buffer_increment(). + * Errors (with error bit) from f_utf_is_combining(). + * Errors (with error bit) from f_utf_is_joiner(). * * @see f_utf_buffer_increment() + * @see f_utf_is_combining() + * @see f_utf_is_joiner() * * @see f_fss_count_slash() * @see f_fss_is_combining_joiner() @@ -70,6 +74,43 @@ extern "C" { * * Intended to be shared to each of the different implementation variations. * + * @param buffer + * The string to process. + * @param range + * The start and stop positions in the buffer being processed. + * This increments range->start. + * + * Must not be NULL. + * @param state + * A state for providing flags and handling interrupts during long running operations. + * + * This calls state.interrupt(), if defined. + * + * Must not be NULL. + * + * This alters state.status: + * F_okay on success and last skipped (if any) character is neither a combining character nor a joiner character. + * F_okay_eol on success and EOL was reached. + * F_okay_eos on success and EOS was reached. + * F_okay_stop on success and stop point was reached. + * F_bound on success and last skipped character is a joiner character (future versions will provide a more accurate status, like F_join). + * F_combarudoo on success and last skipped character is a combining character (future versions will provide a more accurate status, like F_combine). + * F_data_not on success but buffer.used is 0, initial range.start is greater than range.stop, or initial range.start is greater than or equal to buffer.used. + * + * F_complete_not_utf_eos (with error bit) if unable to get entire UTF-8 sequence due to EOS. + * F_complete_not_utf_start (with error bit) if the first character is a combining character. + * F_complete_not_utf_stop (with error bit) if unable to get entire UTF-8 sequence due to stop point reached. + * F_interrupt (with error bit) if stopping due to an interrupt. + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_utf_is_combining(). + * Errors (with error bit) from: f_utf_is_combining_joiner(). + * Errors (with error bit) from: f_utf_is_joiner(). + * + * @see f_utf_is_combining() + * @see f_utf_is_combining_joiner() + * @see f_utf_is_joiner() + * * @see f_fss_count_slash() * @see f_fss_skip_past_combining_joiner() */ @@ -92,10 +133,12 @@ extern "C" { * * This alters state.status: * F_okay on success. - * F_data_not on success but buffer.used is 0, initial range.start is greater than range.stop, or initial range.start is greater than or equal to buffer.used. * F_okay_eol on success and EOL was reached. * F_okay_eos on success and EOS was reached. * F_okay_stop on success and stop point was reached. + * F_bound on success and last skipped character is a joiner character (future versions will provide a more accurate status, like F_join). + * F_combarudoo on success and last skipped character is a combining character (future versions will provide a more accurate status, like F_combine). + * F_data_not on success but buffer.used is 0, initial range.start is greater than range.stop, or initial range.start is greater than or equal to buffer.used. * * F_complete_not_utf_eos (with error bit) if unable to get entire UTF-8 sequence due to EOS. * F_complete_not_utf_start (with error bit) if the first character is a combining or a joiner character. @@ -103,8 +146,10 @@ extern "C" { * F_interrupt (with error bit) if stopping due to an interrupt. * F_parameter (with error bit) if a parameter is invalid. * + * Errors (with error bit) from: f_utf_is_combining(). * Errors (with error bit) from: f_utf_is_combining_joiner(). * Errors (with error bit) from: f_utf_is_control(). + * Errors (with error bit) from: f_utf_is_joiner(). * Errors (with error bit) from: f_utf_is_whitespace(). * Errors (with error bit) from: f_utf_is_zero_width(). * @param previous @@ -117,8 +162,10 @@ extern "C" { * * Must not be NULL. * + * @see f_utf_is_combining() * @see f_utf_is_combining_joiner() * @see f_utf_is_control() + * @see f_utf_is_joiner() * @see f_utf_is_whitespace() * @see f_utf_is_zero_width() * diff --git a/level_0/f_fss/tests/unit/c/test-fss-skip_past_combining_joiner.c b/level_0/f_fss/tests/unit/c/test-fss-skip_past_combining_joiner.c index 90c0ffb2f..13bc8ed4d 100644 --- a/level_0/f_fss/tests/unit/c/test-fss-skip_past_combining_joiner.c +++ b/level_0/f_fss/tests/unit/c/test-fss-skip_past_combining_joiner.c @@ -59,37 +59,45 @@ void test__f_fss_skip_past_combining_joiner__works(void **state) { f_state_t state_data = f_state_t_initialize; + const uint8_t total = 24; + f_string_static_t tests[] = { - // Set 1 + // Set 1 Derived from $(utf8 -cB U+0301). macro_f_string_static_t_initialize_1("́", 2, 0), macro_f_string_static_t_initialize_1("\0́", 3, 0), macro_f_string_static_t_initialize_1("\0\0\0́", 5, 0), macro_f_string_static_t_initialize_1("\0\0\0́\0\0", 7, 0), - // Set 2 + // Set 2 Derived from $(utf8 -cB U+0301). macro_f_string_static_t_initialize_1("́.", 3, 0), macro_f_string_static_t_initialize_1("\0̃.", 4, 0), macro_f_string_static_t_initialize_1("\0\0\0̃.", 6, 0), macro_f_string_static_t_initialize_1("\0\0\0̃\0\0.", 8, 0), - // Set 3 + // Set 3 Derived from $(utf8 -cB U+0320 U+0301). macro_f_string_static_t_initialize_1("̠.", 3, 0), macro_f_string_static_t_initialize_1("\0̠.", 4, 0), macro_f_string_static_t_initialize_1("\0\0\0̠.", 6, 0), macro_f_string_static_t_initialize_1("\0\0\0̠\0\0.", 8, 0), - // Set 4 + // Set 4 Derived from $(utf8 -cB U+0301). macro_f_string_static_t_initialize_1("̠́.", 5, 0), macro_f_string_static_t_initialize_1("\0̠́.", 6, 0), macro_f_string_static_t_initialize_1("\0\0\0̠́.", 8, 0), macro_f_string_static_t_initialize_1("\0\0\0̠́\0\0.", 10, 0), - // Set 5 + // Set 5 Derived from $(utf8 -cB U+0301 U+0320 U+0301). macro_f_string_static_t_initialize_1("̠́́.", 7, 0), macro_f_string_static_t_initialize_1("\0̠́́.", 8, 0), macro_f_string_static_t_initialize_1("\0\0\0̠́́.", 10, 0), macro_f_string_static_t_initialize_1("\0\0\0̠́́\0\0.", 12, 0), + + // Set 6 Derived from $(utf8 -cB U+200D). + macro_f_string_static_t_initialize_1("\0‍.", 5, 0), + macro_f_string_static_t_initialize_1("\0\0‍.", 6, 0), + macro_f_string_static_t_initialize_1("\0\0\0\0‍.", 8, 0), + macro_f_string_static_t_initialize_1("\0\0\0\0‍.\0\0", 10, 0), }; uint16_t statuss[] = { @@ -101,28 +109,34 @@ void test__f_fss_skip_past_combining_joiner__works(void **state) { F_okay_eos, // Set 2 - F_okay, - F_okay, - F_okay, - F_okay, + F_combarudoo, + F_combarudoo, + F_combarudoo, + F_combarudoo, // Set 3 - F_okay, - F_okay, - F_okay, - F_okay, + F_combarudoo, + F_combarudoo, + F_combarudoo, + F_combarudoo, // Set 4 - F_okay, - F_okay, - F_okay, - F_okay, + F_combarudoo, + F_combarudoo, + F_combarudoo, + F_combarudoo, // Set 5 - F_okay, - F_okay, - F_okay, - F_okay, + F_combarudoo, + F_combarudoo, + F_combarudoo, + F_combarudoo, + + // Set 6 + F_bound, + F_bound, + F_bound, + F_bound, }; f_number_unsigned_t ranges[] = { @@ -156,9 +170,15 @@ void test__f_fss_skip_past_combining_joiner__works(void **state) { 7, 9, 11, + + // Set 6 + 4, + 5, + 7, + 7, }; - for (uint8_t i = 0; i < 20; ++i) { + for (uint8_t i = 0; i < total; ++i) { f_range_t range = macro_f_range_t_initialize_1(0, tests[i].used - 1); diff --git a/level_0/f_fss/tests/unit/c/test-fss-skip_past_space.c b/level_0/f_fss/tests/unit/c/test-fss-skip_past_space.c index 95ddd01cc..e6dcb8f9d 100644 --- a/level_0/f_fss/tests/unit/c/test-fss-skip_past_space.c +++ b/level_0/f_fss/tests/unit/c/test-fss-skip_past_space.c @@ -59,6 +59,8 @@ void test__f_fss_skip_past_space__works(void **state) { f_state_t state_data = f_state_t_initialize; + const uint8_t total = 14; + // Space followed by a zero-width joiner and a joined character with NULLs before joiner (U+0020 \0 \0 U+200D U+1F9D4). char space_null_join[] = { 0x20, 0x0, 0x0, 0xe2, 0x80, 0x8d, 0xf0, 0x9f, 0xa7, 0x94 }; @@ -86,14 +88,14 @@ void test__f_fss_skip_past_space__works(void **state) { F_okay, F_okay, F_okay, + F_combarudoo, F_okay, - F_okay, - F_okay, - F_okay, + F_bound, + F_bound, F_status_set_error(F_complete_not_utf_start), F_status_set_error(F_complete_not_utf_start), - F_okay, - F_okay, + F_bound, + F_bound, }; f_number_unsigned_t ranges[] = { @@ -103,17 +105,17 @@ void test__f_fss_skip_past_space__works(void **state) { 3, 3, 3, - 0, + 1, 3, + 1, + 1, 0, 0, - 0, - 0, - 0, - 0, + 1, + 3, }; - for (uint8_t i = 0; i < 14; ++i) { + for (uint8_t i = 0; i < total; ++i) { f_range_t range = macro_f_range_t_initialize_1(0, tests[i].used - 1); diff --git a/level_0/f_fss/tests/unit/c/test-fss-skip_past_space_previous.c b/level_0/f_fss/tests/unit/c/test-fss-skip_past_space_previous.c index e62531f79..a38085be4 100644 --- a/level_0/f_fss/tests/unit/c/test-fss-skip_past_space_previous.c +++ b/level_0/f_fss/tests/unit/c/test-fss-skip_past_space_previous.c @@ -76,6 +76,8 @@ void test__f_fss_skip_past_space_previous__works(void **state) { f_state_t state_data = f_state_t_initialize; + const uint8_t total = 14; + // Space followed by a zero-width joiner and a joined character with NULLs before joiner (U+0020 \0 \0 U+200D U+1F9D4). char space_null_join[] = { 0x20, 0x0, 0x0, 0xe2, 0x80, 0x8d, 0xf0, 0x9f, 0xa7, 0x94 }; @@ -103,14 +105,14 @@ void test__f_fss_skip_past_space_previous__works(void **state) { F_okay, F_okay, F_okay, + F_combarudoo, F_okay, - F_okay, - F_okay, - F_okay, + F_bound, + F_bound, F_status_set_error(F_complete_not_utf_start), F_status_set_error(F_complete_not_utf_start), - F_okay, - F_okay, + F_bound, + F_bound, }; f_number_unsigned_t ranges[] = { @@ -120,8 +122,25 @@ void test__f_fss_skip_past_space_previous__works(void **state) { 3, 3, 3, + 1, + 3, + 1, + 1, + 0, 0, + 1, 3, + }; + + f_number_unsigned_t previouss[] = { + 0, + 0, + 2, + 1, + 2, + 2, + 0, + 0, 0, 0, 0, @@ -130,7 +149,7 @@ void test__f_fss_skip_past_space_previous__works(void **state) { 0, }; - for (uint8_t i = 0; i < 14; ++i) { + for (uint8_t i = 0; i < total; ++i) { f_range_t range = macro_f_range_t_initialize_1(0, tests[i].used - 1); f_number_unsigned_t previous = 0; @@ -148,6 +167,12 @@ void test__f_fss_skip_past_space_previous__works(void **state) { } assert_int_equal(range.start, ranges[i]); + + if (previous != previouss[i]) { + printf("[ -------> ] --- [02] Expected %lu in previous but got %lu at index %d for string '%s'.\n", previouss[i], previous, i, tests[i].used ? tests[i].string : ""); + } + + assert_int_equal(previous, previouss[i]); } // for } diff --git a/level_1/fl_fss/c/fss/basic_list.c b/level_1/fl_fss/c/fss/basic_list.c index 55186915f..0fcbbcf78 100644 --- a/level_1/fl_fss/c/fss/basic_list.c +++ b/level_1/fl_fss/c/fss/basic_list.c @@ -872,11 +872,12 @@ extern "C" { if (object.string[range->start] == f_fss_slash_s.string[0]) { slash_count = 1; + ++range->start; f_fss_count_slash(object, range, &slash_count, state); if (F_status_is_error(state->status)) break; - // Slashes at the end of the object must be delimited to avoid delimiting the object close character. + // Only slashes at the end of the object must be delimited to avoid delimiting the object close character. if (range->start > range->stop || range->start >= object.used) { slash_count *= 2; } diff --git a/level_1/fl_fss/c/fss/embedded_list.c b/level_1/fl_fss/c/fss/embedded_list.c index ef9773630..a350d328d 100644 --- a/level_1/fl_fss/c/fss/embedded_list.c +++ b/level_1/fl_fss/c/fss/embedded_list.c @@ -204,6 +204,8 @@ extern "C" { if (F_status_is_error(state->status)) break; if (range->start > range->stop || range->start >= buffer.used) break; + // TODO: check found F_bount and F_combaradoo, that space is no longer a valid space (use previous to skip back to the now graphing space character). + // This is an otherwise valid object open/close that has been delimited, save the slash delimit positions. if (state->status == F_okay_eol) { newline_last = range->start; @@ -324,6 +326,8 @@ extern "C" { f_fss_skip_past_space_previous(buffer, range, state, &previous); + // TODO: check found F_bount and F_combaradoo, that space is no longer a valid space (use previous to skip back to the now graphing space character). + // The skip space returns F_complete_not_utf_start with error bit set on combining/joiner. if (F_status_set_fine(state->status) == F_complete_not_utf_start) { @@ -387,6 +391,8 @@ extern "C" { f_fss_skip_past_space_previous(buffer, range, state, &previous); + // TODO: check found F_bount and F_combaradoo, that space is no longer a valid space (use previous to skip back to the now graphing space character). + // The skip space returns F_complete_not_utf_start with error bit set on combining/joiner. if (F_status_set_fine(state->status) == F_complete_not_utf_start) { @@ -1129,13 +1135,13 @@ extern "C" { if (object.string[range->start] == f_fss_slash_s.string[0]) { slash_count = 1; + ++range->start; f_fss_count_slash(object, range, &slash_count, state); if (F_status_is_error(state->status)) return; + // Only slashes at the end of the object must be delimited to avoid delimiting the object close character. if (range->start > range->stop || range->start >= object.used) { - - // Slashes at the end of the object must be delimited to avoid delimiting the object close character. slash_count *= 2; } diff --git a/level_1/fl_fss/c/fss/extended_list.c b/level_1/fl_fss/c/fss/extended_list.c index 4b84b46d4..655eb0590 100644 --- a/level_1/fl_fss/c/fss/extended_list.c +++ b/level_1/fl_fss/c/fss/extended_list.c @@ -870,13 +870,13 @@ extern "C" { if (object.string[range->start] == f_fss_slash_s.string[0]) { slash_count = 1; + ++range->start; f_fss_count_slash(object, range, &slash_count, state); if (F_status_is_error(state->status)) return; + // Only slashes at the end of the object must be delimited to avoid delimiting the object close character. if (range->start > range->stop || range->start >= object.used) { - - // Slashes at the end of the object must be delimited to avoid delimiting the object close character. slash_count *= 2; } diff --git a/level_1/fl_fss/c/private-fss-list.c b/level_1/fl_fss/c/private-fss-list.c index f8c5c928f..0946e3792 100644 --- a/level_1/fl_fss/c/private-fss-list.c +++ b/level_1/fl_fss/c/private-fss-list.c @@ -424,22 +424,23 @@ extern "C" { #if !defined(_di_fl_fss_basic_list_object_write_) || !defined(_di_fl_fss_embedded_list_object_write_) || !defined(_di_fl_fss_extended_list_object_write_) void private_fl_fss_list_write_object_trim(const f_number_unsigned_t used_start, f_string_dynamic_t * const destination, f_state_t * const state) { - f_range_t destination_range = macro_f_range_t_initialize_2(destination->used); + f_range_t range = macro_f_range_t_initialize_2(destination->used); f_number_unsigned_t i = 0; uint8_t width = 0; state->status = F_okay; - for (; destination_range.start < destination->used; ++destination_range.start) { + // Remove leading spaces. + for (; range.start < destination->used; ++range.start) { if (state->interrupt) { state->interrupt((void *) state, 0); if (F_status_set_fine(state->status) == F_interrupt) return; } - if (destination->string[destination_range.start] == f_fss_placeholder_s.string[0]) continue; + if (destination->string[range.start] == f_fss_placeholder_s.string[0]) continue; - if (f_fss_is_space(*destination, destination_range, state) == F_false) { + if (f_fss_is_space(*destination, range, state) == F_false) { // TODO: Needs combining joiner check. if (F_status_is_error(state->status)) { destination->used = used_start; @@ -448,28 +449,31 @@ extern "C" { break; } + else { + } - width = macro_f_utf_byte_width(destination->string[destination_range.start]); + width = macro_f_utf_byte_width(destination->string[range.start]); for (i = 0; i < width; ++i) { - destination->string[destination_range.start + i] = f_fss_placeholder_s.string[0]; + destination->string[range.start + i] = f_fss_placeholder_s.string[0]; } // for } // for - for (destination_range.start = destination->used - 1; destination_range.start > 0; --destination_range.start) { + // Remove trailing spaces. + for (range.start = destination->used - 1; range.start > 0; --range.start) { if (state->interrupt) { state->interrupt((void *) state, 0); if (F_status_set_fine(state->status) == F_interrupt) return; } - if (destination->string[destination_range.start] == f_fss_placeholder_s.string[0]) { + if (destination->string[range.start] == f_fss_placeholder_s.string[0]) { --destination->used; continue; } - if (f_fss_is_space(*destination, destination_range, state) == F_false) { + if (f_fss_is_space(*destination, range, state) == F_false) { // TODO: Needs combining joiner check. // When going backwards, getting incomplete UTF-8 sequences is not an error. if (F_status_set_fine(state->status) == F_complete_not_utf) continue; @@ -483,11 +487,11 @@ extern "C" { break; } - destination->used -= macro_f_utf_byte_width(destination->string[destination_range.start]); + destination->used -= macro_f_utf_byte_width(destination->string[range.start]); } // for - if (destination_range.start == 0) { - if (f_fss_is_space(*destination, destination_range, state) == F_false) { + if (range.start == 0) { + if (f_fss_is_space(*destination, range, state) == F_false) { // TODO: Needs combining joiner check. if (F_status_is_error(state->status)) { destination->used = used_start; -- 2.52.0