]> Kevux Git Server - fll/commitdiff
Progress: Continue work.
authorKevin Day <Kevin@kevux.org>
Wed, 28 Oct 2026 04:34:51 +0000 (23:34 -0500)
committerKevin Day <Kevin@kevux.org>
Wed, 28 Oct 2026 04:34:51 +0000 (23:34 -0500)
12 files changed:
build/scripts/generate_codepoints_from_digits.sh
level_0/f_fss/c/fss.c
level_0/f_fss/c/fss.h
level_0/f_fss/c/private-fss.c
level_0/f_fss/c/private-fss.h
level_0/f_fss/tests/unit/c/test-fss-skip_past_combining_joiner.c
level_0/f_fss/tests/unit/c/test-fss-skip_past_space.c
level_0/f_fss/tests/unit/c/test-fss-skip_past_space_previous.c
level_1/fl_fss/c/fss/basic_list.c
level_1/fl_fss/c/fss/embedded_list.c
level_1/fl_fss/c/fss/extended_list.c
level_1/fl_fss/c/private-fss-list.c

index bf4af14..c4878d9 100644 (file)
@@ -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.
index a0e5029..938df4d 100644 (file)
@@ -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_
 
index bd811b9..ed0caef 100644 (file)
@@ -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);
index 359a0d7..778c390 100644 (file)
@@ -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;
index 3d46248..f72bcc2 100644 (file)
@@ -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()
  *
index 90c0ffb..13bc8ed 100644 (file)
@@ -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);
 
index 95ddd01..e6dcb8f 100644 (file)
@@ -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);
 
index e62531f..a38085b 100644 (file)
@@ -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
 }
 
index 5518691..0fcbbcf 100644 (file)
@@ -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;
         }
index ef97736..a350d32 100644 (file)
@@ -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;
         }
 
index 4b84b46..655eb05 100644 (file)
@@ -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;
         }
 
index f8c5c92..0946e37 100644 (file)
@@ -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;