]> Kevux Git Server - fll/commitdiff
Progress: Latest changes. 0.8-combining
authorKevin Day <Kevin@kevux.org>
Fri, 3 Jul 2026 03:59:56 +0000 (22:59 -0500)
committerKevin Day <Kevin@kevux.org>
Fri, 3 Jul 2026 03:59:56 +0000 (22:59 -0500)
The code has been sitting recently, so commit the changes as is.
I need to come back and resume the work and then complete everything still.

36 files changed:
build/stand_alone/byte_dump.config.h
build/stand_alone/example.config.h
build/stand_alone/fake.config.h
build/stand_alone/fss_identify.config.h
build/stand_alone/fss_read.config.fss_basic.h
build/stand_alone/fss_read.config.fss_basic_list.h
build/stand_alone/fss_read.config.fss_embedded_list.h
build/stand_alone/fss_read.config.fss_extended.h
build/stand_alone/fss_read.config.fss_extended_list.h
build/stand_alone/fss_read.config.fss_payload.h
build/stand_alone/fss_read.config.h
build/stand_alone/fss_write.config.fss_basic.h
build/stand_alone/fss_write.config.fss_basic_list.h
build/stand_alone/fss_write.config.fss_embedded_list.h
build/stand_alone/fss_write.config.fss_extended.h
build/stand_alone/fss_write.config.fss_extended_list.h
build/stand_alone/fss_write.config.fss_payload.h
build/stand_alone/fss_write.config.h
build/stand_alone/iki_read.config.eki.h
build/stand_alone/iki_read.config.h
build/stand_alone/iki_write.config.eki.h
build/stand_alone/iki_write.config.h
build/stand_alone/status_code.config.fss.h
build/stand_alone/status_code.config.h
build/stand_alone/utf8.config.h
level_0/f_fss/c/fss.c
level_0/f_fss/c/fss.h
level_1/fl_fss/c/fss/basic_list.c
level_1/fl_fss/c/fss/basic_list.h
level_1/fl_fss/c/fss/embedded_list.c
level_1/fl_fss/c/fss/embedded_list.h
level_1/fl_fss/c/fss/extended_list.c
level_1/fl_fss/c/fss/extended_list.h
level_1/fl_fss/c/private-fss.c
level_1/fl_fss/c/private-fss.h
specifications/fss.txt

index 3cb3dc3b6d5b0b969977b9bb2252fa016fc88bec..476ebb639f8d80a75601def1937c2863dbebf54f 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 //#define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 //#define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index 85d7859cba83a8a7317ecd4aad4a2081381c3ff6..cd01de073758077b13fb27d474e66f9c446e2fda 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 #define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 #define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index 45cc3e753f545ce4fa22374fd6ccc25d1d378a79..07c5bf881e81c40243de471a87921421382da256 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 #define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 #define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index 6f2f88849cc807a473786fffefec3f24bbca50d2..11c204fc781415b2d06a2b3760b0fdddcf192cbf 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 #define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 #define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index 2526178cf1bf72fe76f8078b37d5e91a6cd8cd7b..982b5152d778c36ced3f54784bc9560c49516172 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 #define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 #define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index 4f9e105d28095a4c14da63e2bb5d33a8c74ad092..61ccb44916edb6e5b9434a69536cd27a7c4f5c2b 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 #define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 #define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index 65624b4035dc4d67a880ba9a1c4b785dfa0bd3f0..ab49238c9e55472eeaaef309a8aa07ee440778cd 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 #define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 #define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index ced1f3d32b59f08ffd843de51af8973648185322..775aea20e349663edefc281b9b1a5711f173fb85 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 #define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 #define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index 8b045020d6b6be0e22d2fe82f6314a0d585e1083..06bda9390130496b89b9c5e97ac00404c72ef786 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 #define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 #define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index 18bfdec07d92add2172a3058bec5c12e03216fe9..74bfd57a786068f14deb93b4dfebc5b68206c8ca 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 #define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 #define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index 991feb200120d0a6fa343b9f9d32eb1ba9c9bede..2716bb3003d2ddcfe5601411a43be9d2b946cd7a 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 #define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 #define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index 34e03ce2b3696e1a207510c893ac6581d555e4d0..d45a69d202d2d18c84208a0cc6ccf5135b914a23 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 #define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 #define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index 3132f4b83f824978f06b4164c607443a92228057..f33fd27735a9cecebd7b3ca43fa527efc5686785 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 #define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 #define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index 04d8e995679991dccb176065777abe015ad66c25..bfcdffcafb3408b1ba8309e2e1fe980ac4180969 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 #define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 #define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index 215ce9705b3ccf11bb5e8ad323b0af386af08524..c5a29b777b7da64efa75fce2957f5f9268d56470 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 #define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 #define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index 57536a753d4285c4766feee9f708c4107b4f9f0f..2b46edf13968ca2986f20b9d4a13a9e8144ebb37 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 #define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 #define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index ce360aafeed00797864abf3337c3a1b43a13e746..4ab9d178cba353732a86d58e7447a8b3173165c2 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 #define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 #define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index 406054a1333ebcc1108395ecf67f15053a8e5665..b44dcde9804d7385c635e5a7f26d966ebac9a4ba 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 #define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 #define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index 9d18e39369bd1aa458333274852ef239ff1385a0..3e207ebb0d0429d41fd00d5eb2f82eadd96711f4 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 #define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 #define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index b6756f88e7c8607bfc920c7e1faba9a77d6585f9..afc332121fee3c849f7e81d8ad6575825a843925 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 #define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 #define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index 02e8376473696ac1b1a04121fb89e4cb8ee707db..3d03e395786265a86e1e42b5c9ea6b100f611824 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 #define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 #define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index 01ea4f28000443ede316db4997b08d400e3a2e7e..3832f9a3b5771d22f201dddcfe72ec18e7584aef 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 #define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 #define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index a07a4448681b94b2bf44c686e4a05817a53cee28..e20ceaf5cb940d7c273f497291f11ac08fd50353 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 #define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 #define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index ea8486fb4104e11508c49cd1e9cdab7b3e1a016b..a08336293a69217ed191c0981c61555f872ce571 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 #define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 #define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index 65a1880203f5b04417f7c84603136bf7b203617b..ec06427387d8b944745093b1451a0b7cf7848285 100644 (file)
 #define _di_f_utf_character_is_alphabetic_numeric_
 #define _di_f_utf_character_is_ascii_
 //#define _di_f_utf_character_is_combining_
-#define _di_f_utf_character_is_combining_joinger_
+#define _di_f_utf_character_is_combining_joiner
 //#define _di_f_utf_character_is_control_
 #define _di_f_utf_character_is_control_code_
 #define _di_f_utf_character_is_control_format_
index 335dde1e165eba5cd429ab91429e7a5dca0178dc..3c59400adcf832d0322562de9474bbbb7761c359 100644 (file)
@@ -24,6 +24,11 @@ extern "C" {
 
     for (f_number_unsigned_t i = 0; i < delimits.used; ++i) {
 
+      if (state->interrupt) {
+        state->interrupt((void *) state, 0);
+        if (F_status_set_fine(state->status) == F_interrupt) return;
+      }
+
       if (delimits.array[i] < buffer->used) {
         buffer->string[delimits.array[i]] = f_fss_placeholder_s.string[0];
       }
@@ -53,6 +58,11 @@ extern "C" {
 
     for (f_number_unsigned_t i = 0; i < delimits.used; ++i) {
 
+      if (state->interrupt) {
+        state->interrupt((void *) state, 0);
+        if (F_status_set_fine(state->status) == F_interrupt) return;
+      }
+
       if (delimits.array[i] < buffer->used && delimits.array[i] >= range.start && delimits.array[i] <= range.stop) {
         buffer->string[delimits.array[i]] = f_fss_placeholder_s.string[0];
       }
@@ -82,6 +92,11 @@ extern "C" {
 
     for (f_number_unsigned_t i = 0; i < before && i < buffer.used; i += macro_f_utf_byte_width(buffer.string[i])) {
 
+      if (state->interrupt) {
+        state->interrupt((void *) state, 0);
+        if (F_status_set_fine(state->status) == F_interrupt) return;
+      }
+
       if (buffer.string[i] == f_fss_eol_s.string[0]) {
         ++(*line);
       }
@@ -111,6 +126,11 @@ extern "C" {
 
     for (f_number_unsigned_t i = range.start; i <= range.stop && i < buffer.used; i += macro_f_utf_byte_width(buffer.string[i])) {
 
+      if (state->interrupt) {
+        state->interrupt((void *) state, 0);
+        if (F_status_set_fine(state->status) == F_interrupt) return;
+      }
+
       if (buffer.string[i] == f_fss_eol_s.string[0]) {
         ++(*line);
       }
@@ -171,7 +191,11 @@ extern "C" {
         : (range.stop - range.start) + 1
     );
 
-    if (state->status == F_true) return F_true;
+    if (state->status == F_true) {
+      state->status = F_combarudoo;
+
+      return F_true;
+    }
 
     f_fss_fail_utf_to_false(state);
 
@@ -179,6 +203,52 @@ extern "C" {
   }
 #endif // _di_f_fss_is_combining_
 
+#ifndef _di_f_fss_is_combining_joiner_
+  f_status_t f_fss_is_combining_joiner(const f_string_static_t buffer, const f_range_t range, f_state_t * const state) {
+    #ifndef _di_level_0_parameter_checking_
+      if (!state) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    if (!buffer.used || range.start > range.stop || range.start >= buffer.used) {
+      state->status = F_data_not;
+
+      return F_false;
+    }
+
+    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_true;
+    }
+
+    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;
+
+        return F_true;
+      }
+    }
+
+    f_fss_fail_utf_to_false(state);
+
+    return F_false;
+  }
+#endif // _di_f_fss_is_combining_joiner_
+
 #ifndef _di_f_fss_is_graph_
   f_status_t f_fss_is_graph(const f_string_static_t buffer, const f_range_t range, f_state_t * const state) {
     #ifndef _di_level_0_parameter_checking_
@@ -206,6 +276,37 @@ extern "C" {
   }
 #endif // _di_f_fss_is_graph_
 
+#ifndef _di_f_fss_is_joiner_
+  f_status_t f_fss_is_joiner(const f_string_static_t buffer, const f_range_t range, f_state_t * const state) {
+    #ifndef _di_level_0_parameter_checking_
+      if (!state) return F_status_set_error(F_parameter);
+    #endif // _di_level_0_parameter_checking_
+
+    if (!buffer.used || range.start > range.stop || range.start >= buffer.used) {
+      state->status = F_data_not;
+
+      return F_false;
+    }
+
+    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;
+
+      return F_true;
+    }
+
+    f_fss_fail_utf_to_false(state);
+
+    return F_false;
+  }
+#endif // _di_f_fss_is_joiner_
+
 #ifndef _di_f_fss_is_space_
   f_status_t f_fss_is_space(const f_string_static_t buffer, const f_range_t range, f_state_t * const state) {
     #ifndef _di_level_0_parameter_checking_
@@ -319,6 +420,11 @@ extern "C" {
 
     for (;; ++range->start) {
 
+      if (state->interrupt) {
+        state->interrupt((void *) state, 0);
+        if (F_status_set_fine(state->status) == F_interrupt) return;
+      }
+
       if (range->start >= buffer.used) {
         state->status = F_okay_eos;
 
@@ -338,8 +444,8 @@ extern "C" {
   }
 #endif // _di_f_fss_seek_to_eol_
 
-#ifndef _di_f_fss_skip_past_combining_
-  void f_fss_skip_past_combining(const f_string_static_t buffer, f_range_t * const range, f_state_t * const state) {
+#ifndef _di_f_fss_skip_past_combining_joiner_
+  void f_fss_skip_past_combining_joiner(const f_string_static_t buffer, f_range_t * const range, f_state_t * const state) {
     #ifndef _di_level_0_parameter_checking_
       if (!state) return;
 
@@ -359,6 +465,11 @@ extern "C" {
     // Skip past initial place holders.
     for (;; ++range->start) {
 
+      if (state->interrupt) {
+        state->interrupt((void *) state, 0);
+        if (F_status_set_fine(state->status) == F_interrupt) return;
+      }
+
       if (range->start >= buffer.used) {
         state->status = F_okay_eos;
 
@@ -392,8 +503,16 @@ extern "C" {
       }
     }
 
+    // 0x1 = last is combining, 0x2 = last is joiner.
+    uint8_t flag = 0x0;
+
     for (;;) {
 
+      if (state->interrupt) {
+        state->interrupt((void *) state, 0);
+        if (F_status_set_fine(state->status) == F_interrupt) return;
+      }
+
       if (range->start >= buffer.used) {
         state->status = F_okay_eos;
 
@@ -449,11 +568,22 @@ extern "C" {
       }
 
       range->start += macro_f_utf_byte_width(buffer.string[range->start]);
+
+      if (state->status == F_bound) {
+        flag = 0x1;
+      }
+      else if (state->status == F_combarudoo) {
+        flag = 0x2;
+      }
     } // for
 
-    state->status = F_okay;
+    status->status = flag & 0x1
+      ? F_bound
+      : flag & 0x2
+        ? F_combarudoo
+        : F_okay;
   }
-#endif // _di_f_fss_skip_past_combining_
+#endif // _di_f_fss_skip_past_combining_joiner_
 
 #ifndef _di_f_fss_skip_past_delimit_
   void f_fss_skip_past_delimit(const f_string_static_t buffer, f_range_t * const range, f_state_t * const state) {
@@ -475,6 +605,11 @@ extern "C" {
 
     for (;; ++range->start) {
 
+      if (state->interrupt) {
+        state->interrupt((void *) state, 0);
+        if (F_status_set_fine(state->status) == F_interrupt) return;
+      }
+
       if (range->start >= buffer.used) {
         state->status = F_okay_eos;
 
@@ -515,6 +650,11 @@ extern "C" {
     // Skip past initial place holders.
     for (;; ++range->start) {
 
+      if (state->interrupt) {
+        state->interrupt((void *) state, 0);
+        if (F_status_set_fine(state->status) == F_interrupt) return;
+      }
+
       if (range->start >= buffer.used) {
         state->status = F_okay_eos;
 
@@ -550,7 +690,7 @@ extern "C" {
       }
     }
 
-    // Check that the first character is not a combining character or a joiner.
+    // Check that the first character is not a combining character or a joiner character.
     state->status = f_utf_is_combining_joiner(
       buffer.string + previous,
       (range->stop - previous) + 1 > buffer.used - previous
@@ -570,6 +710,11 @@ extern "C" {
 
     for (;;) {
 
+      if (state->interrupt) {
+        state->interrupt((void *) state, 0);
+        if (F_status_set_fine(state->status) == F_interrupt) return;
+      }
+
       if (range->start >= buffer.used) {
         state->status = F_okay_eos;
 
index 2bd98e299438e1372f2ddb49c659d21bb54df9b2..1355646ec09cbe8cb63279235d4dd08a4fd9f0fb 100644 (file)
@@ -52,6 +52,7 @@ extern "C" {
  *     F_okay on success.
  *     F_data_not on success but buffer.used is 0.
  *
+ *     F_interrupt (with error bit) if stopping due to an interrupt.
  *     F_parameter (with error bit) if a parameter is invalid.
  */
 #ifndef _di_f_fss_apply_delimit_
@@ -76,6 +77,7 @@ extern "C" {
  *     F_okay on success.
  *     F_data_not on success but buffer.used is 0.
  *
+ *     F_interrupt (with error bit) if stopping due to an interrupt.
  *     F_parameter (with error bit) if a parameter is invalid.
  */
 #ifndef _di_f_fss_apply_delimit_range_
@@ -104,7 +106,8 @@ extern "C" {
  *     F_okay on success.
  *     F_data_not on success but buffer.used is 0 (line is set to 0).
  *
- *   F_parameter (with error bit) if a parameter is invalid.
+ *     F_interrupt (with error bit) if stopping due to an interrupt.
+ *     F_parameter (with error bit) if a parameter is invalid.
  */
 #ifndef _di_f_fss_count_lines_
   extern void f_fss_count_lines(const f_string_static_t buffer, const f_number_unsigned_t before, f_number_unsigned_t * const line, f_state_t * const state);
@@ -132,6 +135,7 @@ extern "C" {
  *     F_okay on success.
  *     F_data_not on success but the range.start is greater than buffer.used or buffer.used is 0 (line is set to 0).
  *
+ *     F_interrupt (with error bit) if stopping due to an interrupt.
  *     F_parameter (with error bit) if a parameter is invalid.
  */
 #ifndef _di_f_fss_count_lines_range_
@@ -200,10 +204,11 @@ extern "C" {
  *   A state for providing flags and handling interrupts during long running operations.
  *
  *   This alters state.status:
+ *     F_combarudoo character in the buffer is a combining character (future versions will provide a more accurate status, like F_combine).
  *     F_data_not on success but nothing is processed.
  *     F_false if the character in the buffer is not a combining character.
- *     F_true if the character in the buffer is a combining character.
  *
+ *     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().
@@ -219,6 +224,49 @@ extern "C" {
   extern f_status_t f_fss_is_combining(const f_string_static_t buffer, const f_range_t range, f_state_t * const state);
 #endif // _di_f_fss_is_combining_
 
+/**
+ * Identify whether or not a character in the buffer is a combining (ASCII or UTF-8) character or a joiner (ASCII or UTF-8) character.
+ *
+ * This only checks if the given character is a combining character and does not check what this combines into.
+ *
+ * The combining characters combine from right to left.
+ * It is recommended to use this after testing for other characters, such as f_fss_is_space() or f_fss_is_graph().
+ * A combining character can follow any character, even if it is something like a control character.
+ * This is unclear behavior so a simple strategy is to assume that a combining character results in a graph for anything except a non-combining zero-width character.
+ * U+0020 followed by U+0301 would result in the combination of the two being considered a graph rather than a space.
+ * Given that NULL characters are ignored by the general FSS standard, combining characters are not considered to combine into NULL.
+ *
+ * @param buffer
+ *   The string to process.
+ * @param range
+ *   The character at the start position will be checked against the graph.
+ * @param state
+ *   A state for providing flags and handling interrupts during long running operations.
+ *
+ *   This alters state.status:
+ *     F_bound character in the buffer is a joiner character (future versions will provide a more accurate status, like F_join).
+ *     F_combarudoo character in the buffer is a combining character (future versions will provide a more accurate status, like F_combine).
+ *     F_data_not on success but nothing is processed.
+ *     F_false if the character in the buffer is not a combining character.
+ *
+ *     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_joiner().
+ *
+ * @return
+ *   F_false if the character in the buffer is not a combining character.
+ *   F_false is returned on any error.
+ *   F_true if the character in the buffer is a combining character.
+ *
+ * @see f_utf_is_combining()
+ * @see f_utf_is_joiner()
+ */
+#ifndef _di_f_fss_is_combining_joiner_
+  extern f_status_t f_fss_is_combining_joiner(const f_string_static_t buffer, const f_range_t range, f_state_t * const state);
+#endif // _di_f_fss_is_combining_joiner_
+
 /**
  * Identify whether or not a character in the buffer is a graph (ASCII or UTF-8) character.
  *
@@ -236,6 +284,7 @@ extern "C" {
  *     F_false if the character in the buffer is not a graph character.
  *     F_true on success and is a graph character.
  *
+ *     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_graph().
@@ -251,6 +300,46 @@ extern "C" {
   extern f_status_t f_fss_is_graph(const f_string_static_t buffer, const f_range_t range, f_state_t * const state);
 #endif // _di_f_fss_is_graph_
 
+/**
+ * Identify whether or not a character in the buffer is a joiner (ASCII or UTF-8) character.
+ *
+ * This only checks if the given character is a combining character and does not check what this combines into.
+ *
+ * The combining characters combine from right to left.
+ * It is recommended to use this after testing for other characters, such as f_fss_is_space() or f_fss_is_graph().
+ * A combining character can follow any character, even if it is something like a control character.
+ * This is unclear behavior so a simple strategy is to assume that a combining character results in a graph for anything except a non-combining zero-width character.
+ * U+0020 followed by U+0301 would result in the combination of the two being considered a graph rather than a space.
+ * Given that NULL characters are ignored by the general FSS standard, combining characters are not considered to combine into NULL.
+ *
+ * @param buffer
+ *   The string to process.
+ * @param range
+ *   The character at the start position will be checked against the graph.
+ * @param state
+ *   A state for providing flags and handling interrupts during long running operations.
+ *
+ *   This alters state.status:
+ *     F_bound character in the buffer is a joiner character (future versions will provide a more accurate status, like F_join).
+ *     F_data_not on success but nothing is processed.
+ *     F_false if the character in the buffer is not a combining character.
+ *
+ *     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_joiner().
+ *
+ * @return
+ *   F_false if the character in the buffer is not a combining character.
+ *   F_false is returned on any error.
+ *   F_true if the character in the buffer is a combining character.
+ *
+ * @see f_utf_is_joiner()
+ */
+#ifndef _di_f_fss_is_joiner_
+  extern f_status_t f_fss_is_joiner(const f_string_static_t buffer, const f_range_t range, f_state_t * const state);
+#endif // _di_f_fss_is_joiner_
+
 /**
  * Identify whether or not a character in the buffer is a non-zero-width white space or non-zero-width control (ASCII or UTF-8) character.
  *
@@ -270,6 +359,7 @@ extern "C" {
  *     F_control if the character is a control character (F_false is returned by this function when zero-width or F_true when is both a space and a control character).
  *     F_true on success and is a space character.
  *
+ *     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_control().
@@ -310,6 +400,7 @@ extern "C" {
  *     F_false if the character in the buffer is not a zero-width character.
  *     F_true if the character in the buffer is a zero-width character.
  *
+ *     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_zero_width().
@@ -347,6 +438,7 @@ extern "C" {
  *     F_okay_eos on success and EOS was reached.
  *     F_okay_stop on success and stop point was reached.
  *
+ *     F_interrupt (with error bit) if stopping due to an interrupt.
  *     F_parameter (with error bit) if a parameter is invalid.
  */
 #ifndef _di_f_fss_seek_to_eol_
@@ -359,7 +451,7 @@ extern "C" {
  * This will do nothing if the first character is not a combining character and is not a joiner character.
  *
  * This skips past place holders.
- *
+ * This does not stop on a place holder (unless it is the end of string or the stop point).
  * This stops on end of line.
  *
  * @param buffer
@@ -371,7 +463,9 @@ extern "C" {
  *   A state for providing flags and handling interrupts during long running operations.
  *
  *   This alters state.status:
- *     F_okay on success.
+ *     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.
@@ -380,15 +474,16 @@ extern "C" {
  *     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_joiner().
  *
  * @see f_utf_is_combining_joiner()
  */
-#ifndef _di_f_fss_skip_past_combining_
-  extern void f_fss_skip_past_combining(const f_string_static_t buffer, f_range_t * const range, f_state_t * const state);
-#endif // _di_f_fss_skip_past_combining_
+#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);
+#endif // _di_f_fss_skip_past_combining_joiner_
 
 /**
  * Skip past all delimit placeholders until a non-delimit placeholder is reached.
@@ -407,6 +502,7 @@ extern "C" {
  *     F_okay_eos on success and EOS was reached.
  *     F_okay_stop on success and stop point was reached.
  *
+ *     F_interrupt (with error bit) if stopping due to an interrupt.
  *     F_parameter (with error bit) if a parameter is invalid.
  */
 #ifndef _di_f_fss_skip_past_delimit_
@@ -445,6 +541,7 @@ extern "C" {
  *     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.
  *     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_joiner().
index a04b3a942c19fe5f14f8956cce1d8a237a53003d..b240f01cadd9bbef8340d28ce7a11d6d5ade1052 100644 (file)
@@ -329,14 +329,23 @@ extern "C" {
     state->status = f_memory_array_increase_by(3, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
     if (F_status_is_error(state->status)) return;
 
+    #define ___fl_flag_do_prepend___         0x1
+    #define ___fl_flag_has_graph___          0x2
+    #define ___fl_flag_is_comment___         0x4
+    #define ___fl_flag_is_combining___       0x8
+    #define ___fl_flag_is_combining_graph___ 0xa
+    #define ___fl_flag_is_joined___          0x10
+    #define ___fl_flag_is_joiner___          0x20
+    #define ___fl_flag_is_joiner_graph___    0x22
+    #define ___fl_flag_is_joinerd___         0x30
+
     const f_number_unsigned_t destination_used = destination->used;
 
-    uint8_t is_comment = F_false;
-    uint8_t has_graph = F_false;
-    uint8_t do_prepend = prepend ? F_true : F_false;
+    uint8_t flag = prepend ? ___fl_flag_do_prepend___ : 0x0;
     uint8_t width = 0;
 
     f_number_unsigned_t i = 0;
+    f_number_unsigned_t previous = 0;
     f_number_unsigned_t slash_count = 0;
     f_number_unsigned_t start = 0;
 
@@ -347,18 +356,50 @@ extern "C" {
         if (F_status_set_fine(state->status) == F_interrupt) break;
       }
 
-      if (content.string[range->start] == f_fss_slash_s.string[0] && !is_comment) {
+      if (flag & ___fl_flag_is_combining___) {
+        f_fss_skip_past_delimit(content, range, state);
+        if (F_status_is_error(state->status)) break;
+
+        if (f_fss_is_combining(content, *range, state) != F_true) {
+          if (F_status_is_error(state->status)) break;
+
+          flag &= ~___fl_flag_is_combining___;
+        }
+      }
+
+      if (flag & ___fl_flag_is_joinerd___) {
+        f_fss_skip_past_delimit(content, range, state);
+        if (F_status_is_error(state->status)) break;
+
+        if (f_fss_is_joiner(content, *range, state) == F_true) {
+          flag |= ___fl_flag_is_joiner___;
+          flag &= ~___fl_flag_is_joined___;
+        }
+        else {
+          if (F_status_is_error(state->status)) break;
+
+          if (flag & ___fl_flag_is_joiner___) {
+            flag |= ___fl_flag_is_joined___;
+            flag &= ~___fl_flag_is_joiner___;
+          }
+          else {
+            flag &= ~___fl_flag_is_joined___;
+          }
+        }
+      }
+
+      if (content.string[range->start] == f_fss_slash_s.string[0] && !(flag & ___fl_flag_is_comment___)) {
         slash_count = 1;
 
-        if (do_prepend) {
+        if (flag & ___fl_flag_do_prepend___) {
           state->status = f_string_dynamic_append(*prepend, destination);
           if (F_status_is_error(state->status)) break;
 
-          do_prepend = F_false;
+          flag &= ~___fl_flag_do_prepend___;
         }
 
         destination->string[destination->used++] = content.string[range->start];
-        has_graph = F_true;
+        flag |= ___fl_flag_has_graph___;
 
         for (++range->start; range->start <= range->stop && range->start < content.used; ++range->start) {
 
@@ -418,17 +459,17 @@ extern "C" {
           continue;
         }
       }
-      else if (content.string[range->start] == f_fss_basic_list_open_s.string[0] && !is_comment) {
+      else if (content.string[range->start] == f_fss_basic_list_open_s.string[0] && !(flag & ___fl_flag_is_comment___)) {
         start = range->start++;
 
-        if (do_prepend) {
+        if (flag & ___fl_flag_do_prepend___) {
           state->status = f_string_dynamic_append(*prepend, destination);
           if (F_status_is_error(state->status)) break;
 
-          do_prepend = F_false;
+          flag &= ~___fl_flag_do_prepend___;
         }
 
-        has_graph = F_true;
+        flag |= ___fl_flag_has_graph___;
 
         f_fss_skip_past_space(content, range, state);
         if (F_status_is_error(state->status)) break;
@@ -458,32 +499,48 @@ extern "C" {
 
         continue;
       }
-      else if (content.string[range->start] == f_fss_comment_s.string[0] && !has_graph) {
-        is_comment = F_true;
+      else if (content.string[range->start] == f_fss_comment_s.string[0] && !(flag & ___fl_flag_has_graph___)) {
+        flag |= ___fl_flag_is_comment___;
       }
       else if (content.string[range->start] == f_fss_eol_s.string[0]) {
-        has_graph = F_false;
-        is_comment = F_false;
+        flag = 0x0;
       }
-      else {
-        if (f_fss_is_graph(content, *range, state) == F_false) {
-          if (F_status_is_error(state->status)) break;
-        }
-        else {
-          has_graph = F_true;
+      else if (f_fss_is_graph(content, *range, state) == F_false) {
+        if (F_status_is_error(state->status)) break;
+
+        previous = range->start;
+
+        f_fss_skip_past_delimit(content, range, state);
+
+        if (state->status == F_okay) {
+          if (f_fss_is_combining_joiner(content, *range, state)) {
+            if (state->status == F_combarudoo) {
+              flag |= ___fl_flag_is_combining_graph___;
+            }
+            else if (state->status == F_bound) {
+              flag |= ___fl_flag_is_joiner_graph___;
+            }
+          }
         }
+
+        if (F_status_is_error(state->status)) break;
+
+        range->start = previous;
+      }
+      else {
+        flag |= ___fl_flag_has_graph___;
       }
 
       if (content.string[range->start] != f_fss_placeholder_s.string[0]) {
-        if (do_prepend) {
+        if (flag & ___fl_flag_do_prepend___) {
           state->status = f_string_dynamic_append(*prepend, destination);
           if (F_status_is_error(state->status)) break;
 
-          do_prepend = F_false;
+          flag &= ~___fl_flag_do_prepend___;
         }
 
         if (content.string[range->start] == f_fss_eol_s.string[0] && prepend) {
-          do_prepend = F_true;
+          flag |= ___fl_flag_do_prepend___;
         }
 
         width = macro_f_utf_byte_width(content.string[range->start]);
@@ -536,6 +593,16 @@ extern "C" {
     else {
       state->status = F_okay;
     }
+
+    #undef ___fl_flag_do_prepend___
+    #undef ___fl_flag_has_graph___
+    #undef ___fl_flag_is_comment___
+    #undef ___fl_flag_is_combining___
+    #undef ___fl_flag_is_combining_graph___
+    #undef ___fl_flag_is_joined___
+    #undef ___fl_flag_is_joiner___
+    #undef ___fl_flag_is_joiner_graph___
+    #undef ___fl_flag_is_joinerd___
   }
 #endif // _di_fl_fss_basic_list_content_write_
 
@@ -595,9 +662,21 @@ extern "C" {
       return;
     }
 
+    #define ___fl_flag_has_graph___          0x1
+    #define ___fl_flag_is_comment___         0x2
+    #define ___fl_flag_is_combining___       0x4
+    #define ___fl_flag_is_combining_graph___ 0x5
+    #define ___fl_flag_is_joined___          0x8
+    #define ___fl_flag_is_joiner___          0x10
+    #define ___fl_flag_is_joiner_graph___    0x11
+    #define ___fl_flag_is_joinerd___         0x18
+
     const f_number_unsigned_t destination_used = destination->used;
+
+    f_number_unsigned_t previous = 0;
     f_number_unsigned_t slash_count = 0;
 
+    uint8_t flag = 0;
     uint8_t width = 0;
 
     // Find the first graph character.
@@ -619,8 +698,59 @@ extern "C" {
         break;
       }
 
+      if (flag & ___fl_flag_is_combining___) {
+        f_fss_skip_past_delimit(object, range, state);
+        if (F_status_is_error(state->status)) break;
+
+        if (f_fss_is_combining(object, *range, state) != F_true) {
+          if (F_status_is_error(state->status)) break;
+
+          flag &= ~___fl_flag_is_combining___;
+        }
+      }
+
+      if (flag & ___fl_flag_is_joinerd___) {
+        f_fss_skip_past_delimit(object, range, state);
+        if (F_status_is_error(state->status)) break;
+
+        if (f_fss_is_joiner(object, *range, state) == F_true) {
+          flag |= ___fl_flag_is_joiner___;
+          flag &= ~___fl_flag_is_joined___;
+        }
+        else {
+          if (F_status_is_error(state->status)) break;
+
+          if (flag & ___fl_flag_is_joiner___) {
+            flag |= ___fl_flag_is_joined___;
+            flag &= ~___fl_flag_is_joiner___;
+          }
+          else {
+            flag &= ~___fl_flag_is_joined___;
+          }
+        }
+      }
+
       if (f_fss_is_graph(object, *range, state) == F_false) {
         if (F_status_is_error(state->status)) break;
+
+        previous = range->start;
+
+        f_fss_skip_past_delimit(object, range, state);
+
+        if (state->status == F_okay) {
+          if (f_fss_is_combining_joiner(object, *range, state)) {
+            if (state->status == F_combarudoo) {
+              flag |= ___fl_flag_is_combining_graph___;
+            }
+            else if (state->status == F_bound) {
+              flag |= ___fl_flag_is_joiner_graph___;
+            }
+          }
+        }
+
+        if (F_status_is_error(state->status)) break;
+
+        range->start = previous;
       }
       else {
         break;
@@ -770,6 +900,15 @@ extern "C" {
     else {
       state->status = F_okay;
     }
+
+    #undef ___fl_flag_has_graph___
+    #undef ___fl_flag_is_comment___
+    #undef ___fl_flag_is_combining___
+    #undef ___fl_flag_is_combining_graph___
+    #undef ___fl_flag_is_joined___
+    #undef ___fl_flag_is_joiner___
+    #undef ___fl_flag_is_joiner_graph___
+    #undef ___fl_flag_is_joinerd___
   }
 #endif // _di_fl_fss_basic_list_object_write_
 
index 5f74cd1465d02c9df2f9cccad353bb692bbb7c13..4e704a7e943fb43643d70e2f2e909ba42e21fed9 100644 (file)
@@ -158,7 +158,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_fss_is_combining().
+ *     Errors (with error bit) from: f_fss_is_combining_joiner().
  *     Errors (with error bit) from: f_fss_is_graph().
+ *     Errors (with error bit) from: f_fss_is_joiner().
  *     Errors (with error bit) from: f_fss_skip_past_delimit().
  *     Errors (with error bit) from: f_fss_skip_past_space().
  *     Errors (with error bit) from: f_memory_array_increase().
@@ -166,7 +169,10 @@ extern "C" {
  *     Errors (with error bit) from: f_string_dynamic_append().
  *     Errors (with error bit) from: f_utf_buffer_increment().
  *
+ * @see f_fss_is_combining()
+ * @see f_fss_is_combining_joiner()
  * @see f_fss_is_graph()
+ * @see f_fss_is_joiner()
  * @see f_fss_skip_past_delimit()
  * @see f_fss_skip_past_space()
  * @see f_memory_array_increase()
@@ -301,14 +307,20 @@ extern "C" {
  *     F_okay_eol (with error bit) after reaching an EOL, which is not supported by the standard.
  *     F_parameter (with error bit) if a parameter is invalid.
  *
+ *     Errors (with error bit) from: f_fss_is_combining().
+ *     Errors (with error bit) from: f_fss_is_combining_joiner().
  *     Errors (with error bit) from: f_fss_is_graph().
+ *     Errors (with error bit) from: f_fss_is_joiner().
  *     Errors (with error bit) from: f_fss_is_space().
  *     Errors (with error bit) from: f_memory_array_increase().
  *     Errors (with error bit) from: f_memory_array_increase_by().
  *     Errors (with error bit) from: f_fss_skip_past_delimit().
  *     Errors (with error bit) from: f_utf_buffer_increment().
  *
+ * @see f_fss_is_combining()
+ * @see f_fss_is_combining_joiner()
  * @see f_fss_is_graph()
+ * @see f_fss_is_joiner()
  * @see f_fss_is_space()
  * @see f_memory_array_increase()
  * @see f_memory_array_increase_by()
index 63d18ccb9f2420882f097b1eedef56d20a78bb71..b7f3acadc9cd4bf660f74ca89bb5f509a1c38516 100644 (file)
@@ -595,15 +595,26 @@ extern "C" {
       return;
     }
 
+    #define ___fl_flag_do_prepend___         0x1
+    #define ___fl_flag_has_eol___            0x2
+    #define ___fl_flag_has_eol_do_prepend___ 0x3
+    #define ___fl_flag_has_graph___          0x4
+    #define ___fl_flag_is_comment___         0x8
+    #define ___fl_flag_is_comment_graph___   0xc
+    #define ___fl_flag_is_combining___       0x10
+    #define ___fl_flag_is_combining_graph___ 0x14
+    #define ___fl_flag_is_joined___          0x20
+    #define ___fl_flag_is_joiner___          0x40
+    #define ___fl_flag_is_joiner_graph___    0x44
+    #define ___fl_flag_is_joinerd___         0x60
+
     const f_number_unsigned_t destination_used = destination->used;
 
-    uint8_t is_comment = F_false;
-    uint8_t ends_on_eol = F_false;
-    uint8_t has_graph = F_false;
-    uint8_t do_prepend = prepend ? F_true : F_false;
+    uint8_t flag = prepend ? ___fl_flag_do_prepend___ : 0x0;
     uint8_t width = 0;
 
     f_number_unsigned_t i = 0;
+    f_number_unsigned_t previous = 0;
     f_number_unsigned_t r = 0;
     f_number_unsigned_t slash_count = 0;
     f_number_unsigned_t start = 0;
@@ -615,14 +626,46 @@ extern "C" {
         if (F_status_set_fine(state->status) == F_interrupt) break;
       }
 
-      if (content.string[range->start] == f_fss_slash_s.string[0] && !is_comment) {
+      if (flag & ___fl_flag_is_combining___) {
+        f_fss_skip_past_delimit(content, range, state);
+        if (F_status_is_error(state->status)) break;
+
+        if (f_fss_is_combining(content, *range, state) != F_true) {
+          if (F_status_is_error(state->status)) break;
+
+          flag &= ~___fl_flag_is_combining___;
+        }
+      }
+
+      if (flag & ___fl_flag_is_joinerd___) {
+        f_fss_skip_past_delimit(content, range, state);
+        if (F_status_is_error(state->status)) break;
+
+        if (f_fss_is_joiner(content, *range, state) == F_true) {
+          flag |= ___fl_flag_is_joiner___;
+          flag &= ~___fl_flag_is_joined___;
+        }
+        else {
+          if (F_status_is_error(state->status)) break;
+
+          if (flag & ___fl_flag_is_joiner___) {
+            flag |= ___fl_flag_is_joined___;
+            flag &= ~___fl_flag_is_joiner___;
+          }
+          else {
+            flag &= ~___fl_flag_is_joined___;
+          }
+        }
+      }
+
+      if (content.string[range->start] == f_fss_slash_s.string[0] && !(flag & ___fl_flag_is_comment___)) {
         slash_count = 1;
 
-        if (do_prepend) {
+        if (flag & ___fl_flag_do_prepend___) {
           state->status = f_string_dynamic_append(*prepend, destination);
           if (F_status_is_error(state->status)) break;
 
-          do_prepend = F_false;
+          flag &= ~___fl_flag_do_prepend___;
         }
 
         state->status = f_memory_array_increase(state->step_large, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
@@ -683,7 +726,7 @@ extern "C" {
             if (F_status_is_error(state->status)) break;
 
             if (content.string[range->start] != f_fss_eol_s.string[0]) {
-              has_graph = F_true;
+              flag |= ___fl_flag_has_graph___;
             }
 
             continue;
@@ -697,10 +740,10 @@ extern "C" {
 
           if (content.string[range->start] == f_fss_eol_s.string[0]) {
             destination->string[destination->used++] = f_fss_eol_s.string[0];
-            ends_on_eol = F_true;
+            flag |= ___fl_flag_has_eol___;
           }
           else {
-            ends_on_eol = F_false;
+            flag &= ~___fl_flag_has_eol___;
           }
 
           range->start = start + 1;
@@ -708,17 +751,17 @@ extern "C" {
           continue;
         }
       }
-      else if ((content.string[range->start] == f_fss_embedded_list_open_s.string[0] || (!has_graph && content.string[range->start] == f_fss_embedded_list_close_s.string[0])) && !is_comment) {
+      else if ((content.string[range->start] == f_fss_embedded_list_open_s.string[0] || (!(flag & ___fl_flag_has_graph___) && content.string[range->start] == f_fss_embedded_list_close_s.string[0])) && !(flag & ___fl_flag_is_comment___)) {
         start = range->start++;
 
-        if (do_prepend) {
+        if (flag & ___fl_flag_do_prepend___) {
           state->status = f_string_dynamic_append(*prepend, destination);
           if (F_status_is_error(state->status)) break;
 
-          do_prepend = F_false;
+          flag &= ~___fl_flag_do_prepend___;
         }
 
-        has_graph = F_true;
+        flag |= ___fl_flag_has_graph___;
 
         f_fss_skip_past_space(content, range, state);
         if (F_status_is_error(state->status)) break;
@@ -726,11 +769,10 @@ extern "C" {
         if (range->start >= content.used || range->start > range->stop || content.string[range->start] == f_fss_eol_s.string[0]) {
 
           if (content.string[range->start] == f_fss_eol_s.string[0] && prepend) {
-            do_prepend = F_true;
-            ends_on_eol = F_true;
+            flag |= ___fl_flag_has_eol_do_prepend___;
           }
           else {
-            ends_on_eol = F_false;
+            flag &= ~___fl_flag_has_eol___;
           }
 
           if (ignore && ignore->used) {
@@ -773,34 +815,51 @@ extern "C" {
 
         continue;
       }
-      else if (content.string[range->start] == f_fss_comment_s.string[0] && !has_graph) {
-        is_comment = F_true;
+      else if (content.string[range->start] == f_fss_comment_s.string[0] && !(flag & ___fl_flag_has_graph___)) {
+        flag |= ___fl_flag_is_comment___;
       }
       else if (content.string[range->start] == f_fss_eol_s.string[0]) {
-        has_graph = F_false;
-        is_comment = F_false;
+        flag &= ~___fl_flag_is_comment_graph___;
       }
       else if (f_fss_is_graph(content, *range, state) == F_false) {
         if (F_status_is_error(state->status)) break;
+
+        previous = range->start;
+
+        f_fss_skip_past_delimit(content, range, state);
+
+        if (state->status == F_okay) {
+          if (f_fss_is_combining_joiner(content, *range, state)) {
+            if (state->status == F_combarudoo) {
+              flag |= ___fl_flag_is_combining_graph___;
+            }
+            else if (state->status == F_bound) {
+              flag |= ___fl_flag_is_joiner_graph___;
+            }
+          }
+        }
+
+        if (F_status_is_error(state->status)) break;
+
+        range->start = previous;
       }
       else {
-        has_graph = F_true;
+        flag |= ___fl_flag_has_graph___;
       }
 
       if (content.string[range->start] != f_fss_placeholder_s.string[0]) {
-        if (do_prepend) {
+        if (flag & ___fl_flag_do_prepend___) {
           state->status = f_string_dynamic_append(*prepend, destination);
           if (F_status_is_error(state->status)) break;
 
-          do_prepend = F_false;
+          flag &= ~___fl_flag_do_prepend___;
         }
 
         if (content.string[range->start] == f_fss_eol_s.string[0] && prepend) {
-          do_prepend = F_true;
-          ends_on_eol = F_true;
+          flag |= ___fl_flag_has_eol_do_prepend___;
         }
         else {
-          ends_on_eol = F_false;
+          flag &= ~___fl_flag_has_eol___;
         }
 
         width = macro_f_utf_byte_width(content.string[range->start]);
@@ -827,7 +886,7 @@ extern "C" {
       state->status = f_memory_array_increase_by(3, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
       if (F_status_is_error(state->status)) return;
 
-      if (!ends_on_eol) {
+      if (!(flag & ___fl_flag_has_eol___)) {
         destination->string[destination->used++] = f_fss_eol_s.string[0];
       }
 
@@ -844,6 +903,19 @@ extern "C" {
     else {
       state->status = F_okay;
     }
+
+    #undef ___fl_flag_do_prepend___
+    #undef ___fl_flag_has_eol___
+    #undef ___fl_flag_has_eol_do_prepend___
+    #undef ___fl_flag_has_graph___
+    #undef ___fl_flag_is_comment___
+    #undef ___fl_flag_is_comment_graph___
+    #undef ___fl_flag_is_combining___
+    #undef ___fl_flag_is_combining_graph___
+    #undef ___fl_flag_is_joined___
+    #undef ___fl_flag_is_joiner___
+    #undef ___fl_flag_is_joiner_graph___
+    #undef ___fl_flag_is_joinerd___
   }
 #endif // _di_fl_fss_embedded_list_content_write_
 
@@ -876,8 +948,7 @@ extern "C" {
     #endif // _di_level_1_parameter_checking_
 
     f_fss_skip_past_delimit(object, range, state);
-    if (F_status_is_error(state->status)) return;
-    if (state->status == F_data_not) return;
+    if (F_status_is_error(state->status) || state->status == F_data_not) return;
 
     if (state->status == F_okay_eos) {
       state->status = F_data_not_eos;
@@ -912,11 +983,22 @@ extern "C" {
     state->status = f_memory_array_increase_by(4, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
     if (F_status_is_error(state->status)) return;
 
+    #define ___fl_flag_has_graph___          0x2
+    #define ___fl_flag_is_comment___         0x4
+    #define ___fl_flag_is_combining___       0x8
+    #define ___fl_flag_is_combining_graph___ 0xa
+    #define ___fl_flag_is_joined___          0x10
+    #define ___fl_flag_is_joiner___          0x20
+    #define ___fl_flag_is_joiner_graph___    0x22
+    #define ___fl_flag_is_joinerd___         0x30
+
     const f_number_unsigned_t destination_used = destination->used;
+
+    f_number_unsigned_t previous = 0;
     f_number_unsigned_t slash_count = 0;
 
+    uint8_t flag = 0;
     uint8_t ends_on_space = F_false;
-
     uint8_t width = 0;
 
     // Find the first graph character.
@@ -927,6 +1009,38 @@ extern "C" {
         if (F_status_set_fine(state->status) == F_interrupt) break;
       }
 
+      if (flag & ___fl_flag_is_combining___) {
+        f_fss_skip_past_delimit(object, range, state);
+        if (F_status_is_error(state->status)) break;
+
+        if (f_fss_is_combining(object, *range, state) != F_true) {
+          if (F_status_is_error(state->status)) break;
+
+          flag &= ~___fl_flag_is_combining___;
+        }
+      }
+
+      if (flag & ___fl_flag_is_joinerd___) {
+        f_fss_skip_past_delimit(object, range, state);
+        if (F_status_is_error(state->status)) break;
+
+        if (f_fss_is_joiner(object, *range, state) == F_true) {
+          flag |= ___fl_flag_is_joiner___;
+          flag &= ~___fl_flag_is_joined___;
+        }
+        else {
+          if (F_status_is_error(state->status)) break;
+
+          if (flag & ___fl_flag_is_joiner___) {
+            flag |= ___fl_flag_is_joined___;
+            flag &= ~___fl_flag_is_joiner___;
+          }
+          else {
+            flag &= ~___fl_flag_is_joined___;
+          }
+        }
+      }
+
       if (object.string[range->start] == f_fss_comment_s.string[0]) {
 
         // When a comment is found, escape it.
@@ -940,6 +1054,25 @@ extern "C" {
 
       if (f_fss_is_graph(object, *range, state) == F_false) {
         if (F_status_is_error(state->status)) break;
+
+        previous = range->start;
+
+        f_fss_skip_past_delimit(object, range, state);
+
+        if (state->status == F_okay) {
+          if (f_fss_is_combining_joiner(object, *range, state)) {
+            if (state->status == F_combarudoo) {
+              flag |= ___fl_flag_is_combining_graph___;
+            }
+            else if (state->status == F_bound) {
+              flag |= ___fl_flag_is_joiner_graph___;
+            }
+          }
+        }
+
+        if (F_status_is_error(state->status)) break;
+
+        range->start = previous;
       }
       else {
         break;
@@ -1116,6 +1249,15 @@ extern "C" {
     else {
       state->status = F_okay;
     }
+
+    #undef ___fl_flag_has_graph___
+    #undef ___fl_flag_is_comment___
+    #undef ___fl_flag_is_combining___
+    #undef ___fl_flag_is_combining_graph___
+    #undef ___fl_flag_is_joined___
+    #undef ___fl_flag_is_joiner___
+    #undef ___fl_flag_is_joiner_graph___
+    #undef ___fl_flag_is_joinerd___
   }
 #endif // _di_fl_fss_embedded_list_object_write_
 
index 46b291c3b871a4438a8706ba3580f0671a630f91..19210fc2af17cceea10261258a00d04259cfa9dc 100644 (file)
@@ -209,7 +209,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_fss_is_combining().
+ *     Errors (with error bit) from: f_fss_is_combining_joiner().
  *     Errors (with error bit) from: f_fss_is_graph().
+ *     Errors (with error bit) from: f_fss_is_joiner().
  *     Errors (with error bit) from: f_fss_skip_past_delimit().
  *     Errors (with error bit) from: f_fss_skip_past_space().
  *     Errors (with error bit) from: f_memory_array_increase().
@@ -217,7 +220,10 @@ extern "C" {
  *     Errors (with error bit) from: f_memory_array_increase_by().
  *     Errors (with error bit) from: f_utf_buffer_increment().
  *
+ * @see f_fss_is_combining()
+ * @see f_fss_is_combining_joiner()
  * @see f_fss_is_graph()
+ * @see f_fss_is_joiner()
  * @see f_fss_skip_past_delimit()
  * @see f_fss_skip_past_space()
  * @see f_memory_array_increase()
@@ -352,14 +358,20 @@ extern "C" {
  *     F_okay_eol (with error bit) after reaching an EOL, which is not supported by the standard.
  *     F_parameter (with error bit) if a parameter is invalid.
  *
+ *     Errors (with error bit) from: f_fss_is_combining().
+ *     Errors (with error bit) from: f_fss_is_combining_joiner().
  *     Errors (with error bit) from: f_fss_is_graph().
+ *     Errors (with error bit) from: f_fss_is_joiner().
  *     Errors (with error bit) from: f_fss_is_space().
  *     Errors (with error bit) from: f_fss_skip_past_delimit().
  *     Errors (with error bit) from: f_memory_array_increase().
  *     Errors (with error bit) from: f_memory_array_increase_by().
  *     Errors (with error bit) from: f_utf_buffer_increment().
  *
+ * @see f_fss_is_combining()
+ * @see f_fss_is_combining_joiner()
  * @see f_fss_is_graph()
+ * @see f_fss_is_joiner()
  * @see f_fss_is_space()
  * @see f_fss_skip_past_delimit()
  * @see f_memoy_array_increase()
index 5da2e51d0e0b03bc36e49b1a24cd9b87fd665d28..957a31cf924b1962b9b504eb0dfe9297e512aabb 100644 (file)
@@ -274,20 +274,24 @@ extern "C" {
     state->status = f_memory_array_increase_by(4, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
     if (F_status_is_error(state->status)) return;
 
-    const f_number_unsigned_t destination_used = destination->used;
+    #define ___fl_flag_do_prepend___         0x1
+    #define ___fl_flag_has_eol___            0x2
+    #define ___fl_flag_has_eol_do_prepend___ 0x3
+    #define ___fl_flag_has_graph___          0x4
+    #define ___fl_flag_is_comment___         0x8
+    #define ___fl_flag_is_comment_graph___   0xc
+    #define ___fl_flag_is_combining___       0x10
+    #define ___fl_flag_is_combining_graph___ 0x14
+    #define ___fl_flag_is_joined___          0x20
+    #define ___fl_flag_is_joiner___          0x40
+    #define ___fl_flag_is_joiner_graph___    0x44
+    #define ___fl_flag_is_joinerd___         0x60
 
-    #define ___fl_flag_is_comment___             0x1
-    #define ___fl_flag_has_graph___              0x2
-    #define ___fl_flag_is_comment_graph___       0x3
-    #define ___fl_flag_ends_on_eol___            0x4
-    #define ___fl_flag_do_prepend___             0x8
-    #define ___fl_flag_do_prepend_ends_on_eol___ 0xc
-    #define ___fl_flag_graph_combine___          0x10 // Is a graph only due to combining character.
-    #define ___fl_flag_graph_joiner___           0x20 // Is a graph only due to a joining character.
-    #define ___fl_flag_graph_joiner_combine___   0x30
+    const f_number_unsigned_t destination_used = destination->used;
 
     uint8_t flag = prepend ? ___fl_flag_do_prepend___ : 0x0;
 
+    f_number_unsigned_t previous = 0;
     f_number_unsigned_t r = 0;
     f_number_unsigned_t start = 0;
 
@@ -300,6 +304,38 @@ extern "C" {
         if (F_status_set_fine(state->status) == F_interrupt) break;
       }
 
+      if (flag & ___fl_flag_is_combining___) {
+        f_fss_skip_past_delimit(content, range, state);
+        if (F_status_is_error(state->status)) break;
+
+        if (f_fss_is_combining(content, *range, state) != F_true) {
+          if (F_status_is_error(state->status)) break;
+
+          flag &= ~___fl_flag_is_combining___;
+        }
+      }
+
+      if (flag & ___fl_flag_is_joinerd___) {
+        f_fss_skip_past_delimit(content, range, state);
+        if (F_status_is_error(state->status)) break;
+
+        if (f_fss_is_joiner(content, *range, state) == F_true) {
+          flag |= ___fl_flag_is_joiner___;
+          flag &= ~___fl_flag_is_joined___;
+        }
+        else {
+          if (F_status_is_error(state->status)) break;
+
+          if (flag & ___fl_flag_is_joiner___) {
+            flag |= ___fl_flag_is_joined___;
+            flag &= ~___fl_flag_is_joiner___;
+          }
+          else {
+            flag &= ~___fl_flag_is_joined___;
+          }
+        }
+      }
+
       if (content.string[range->start] == f_fss_slash_s.string[0] && !(flag & ___fl_flag_is_comment___)) {
 
         if (flag & ___fl_flag_do_prepend___) {
@@ -379,10 +415,10 @@ extern "C" {
 
           if (content.string[range->start] == f_fss_eol_s.string[0]) {
             destination->string[destination->used++] = f_fss_eol_s.string[0];
-            flag |= ___fl_flag_ends_on_eol___;
+            flag |= ___fl_flag_has_eol___;
           }
           else {
-            flag &= ~___fl_flag_ends_on_eol___;
+            flag &= ~___fl_flag_has_eol___;
           }
 
           range->start = start + 1;
@@ -408,10 +444,10 @@ extern "C" {
         if (content.string[range->start] == f_fss_eol_s.string[0] || range->start >= content.used || range->start > range->stop) {
 
           if (content.string[range->start] == f_fss_eol_s.string[0] && prepend) {
-            flag |= ___fl_flag_do_prepend_ends_on_eol___;
+            flag |= ___fl_flag_has_eol_do_prepend___;
           }
           else {
-            flag &= ~___fl_flag_ends_on_eol___;
+            flag &= ~___fl_flag_has_eol___;
           }
 
           if (ignore && ignore->used) {
@@ -463,11 +499,30 @@ extern "C" {
       else if (f_fss_is_graph(content, *range, state) == F_true) {
         flag |= ___fl_flag_has_graph___;
       }
-      else {
+      else if (f_fss_is_graph(content, *range, state) == F_false) {
+        if (F_status_is_error(state->status)) break;
+
+        previous = range->start;
+
+        f_fss_skip_past_delimit(content, range, state);
+
+        if (state->status == F_okay) {
+          if (f_fss_is_combining_joiner(content, *range, state)) {
+            if (state->status == F_combarudoo) {
+              flag |= ___fl_flag_is_combining_graph___;
+            }
+            else if (state->status == F_bound) {
+              flag |= ___fl_flag_is_joiner_graph___;
+            }
+          }
+        }
+
         if (F_status_is_error(state->status)) break;
 
-        // TODO: flag |= ___fl_flag_graph_combine___;
-        // TODO: flag |= ___fl_flag_graph_joiner___;
+        range->start = previous;
+      }
+      else {
+        flag |= ___fl_flag_has_graph___;
       }
 
       if (content.string[range->start] != f_fss_placeholder_s.string[0]) {
@@ -479,34 +534,20 @@ extern "C" {
         }
 
         if (content.string[range->start] == f_fss_eol_s.string[0] && prepend) {
-          flag |= ___fl_flag_do_prepend_ends_on_eol___;
+          flag |= ___fl_flag_has_eol_do_prepend___;
         }
         else {
-          flag &= ~___fl_flag_ends_on_eol___;
+          flag &= ~___fl_flag_has_eol___;
         }
 
         width = macro_f_utf_byte_width(content.string[range->start]);
 
-        // ___fl_flag_graph_combine___ and ___fl_flag_graph_joiner___ are only set if the characters can be found, so it is therefore safe to trust that range->start + width can be used.
-        if (flag & ___fl_flag_graph_combine___) {
-          width += macro_f_utf_byte_width(content.string[range->start + width]);
-        }
-
         state->status = f_memory_array_increase_by(width, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
         if (F_status_is_error(state->status)) break;
 
         memcpy(destination->string + destination->used, content.string + range->start, width);
 
         destination->used += width;
-
-        if (flag & ___fl_flag_graph_combine___) {
-          state->status = f_utf_buffer_increment(content, range, 2);
-          if (F_status_is_error(state->status)) break;
-
-          flag &= ~___fl_flag_graph_combine___;
-
-          continue;
-        }
       }
 
       state->status = f_utf_buffer_increment(content, range, 1);
@@ -529,7 +570,7 @@ extern "C" {
         return;
       }
 
-      if (!(flag & ___fl_flag_ends_on_eol___)) {
+      if (!(flag & ___fl_flag_has_eol___)) {
         destination->string[destination->used++] = f_fss_eol_s.string[0];
       }
 
@@ -547,15 +588,17 @@ extern "C" {
       state->status = F_okay;
     }
 
-    #undef ___fl_flag_is_comment___
-    #undef ___fl_flag_has_graph___
-    #undef ___fl_flag_is_comment_graph___
-    #undef ___fl_flag_ends_on_eol___
     #undef ___fl_flag_do_prepend___
-    #undef ___fl_flag_do_prepend_ends_on_eol___
-    #undef ___fl_flag_graph_combine___
-    #undef ___fl_flag_graph_joiner___
-    #undef ___fl_flag_graph_joiner_combine___
+    #undef ___fl_flag_has_eol___
+    #undef ___fl_flag_has_eol_do_prepend___
+    #undef ___fl_flag_has_graph___
+    #undef ___fl_flag_is_comment___
+    #undef ___fl_flag_is_combining___
+    #undef ___fl_flag_is_combining_graph___
+    #undef ___fl_flag_is_joined___
+    #undef ___fl_flag_is_joiner___
+    #undef ___fl_flag_is_joiner_graph___
+    #undef ___fl_flag_is_joinerd___
   }
 #endif // _di_fl_fss_extended_list_content_write_
 
@@ -624,12 +667,25 @@ extern "C" {
     state->status = f_memory_array_increase_by(4, sizeof(f_char_t), (void **) &destination->string, &destination->used, &destination->size);
     if (F_status_is_error(state->status)) return;
 
+    #define ___fl_flag_has_eol___            0x2
+    #define ___fl_flag_has_eol_do_prepend___ 0x3
+    #define ___fl_flag_has_graph___          0x4
+    #define ___fl_flag_is_comment___         0x8
+    #define ___fl_flag_is_comment_graph___   0xc
+    #define ___fl_flag_is_combining___       0x10
+    #define ___fl_flag_is_combining_graph___ 0x14
+    #define ___fl_flag_is_joined___          0x20
+    #define ___fl_flag_is_joiner___          0x40
+    #define ___fl_flag_is_joiner_graph___    0x44
+    #define ___fl_flag_is_joinerd___         0x60
+
     const f_number_unsigned_t destination_used = destination->used;
 
+    f_number_unsigned_t previous = 0;
     f_number_unsigned_t slash_count = 0;
 
+    uint8_t flag = 0;
     uint8_t ends_on_space = F_false;
-
     uint8_t width = 0;
 
     // Find the first graph character.
@@ -640,6 +696,38 @@ extern "C" {
         if (F_status_set_fine(state->status) == F_interrupt) break;
       }
 
+      if (flag & ___fl_flag_is_combining___) {
+        f_fss_skip_past_delimit(object, range, state);
+        if (F_status_is_error(state->status)) break;
+
+        if (f_fss_is_combining(object, *range, state) != F_true) {
+          if (F_status_is_error(state->status)) break;
+
+          flag &= ~___fl_flag_is_combining___;
+        }
+      }
+
+      if (flag & ___fl_flag_is_joinerd___) {
+        f_fss_skip_past_delimit(object, range, state);
+        if (F_status_is_error(state->status)) break;
+
+        if (f_fss_is_joiner(object, *range, state) == F_true) {
+          flag |= ___fl_flag_is_joiner___;
+          flag &= ~___fl_flag_is_joined___;
+        }
+        else {
+          if (F_status_is_error(state->status)) break;
+
+          if (flag & ___fl_flag_is_joiner___) {
+            flag |= ___fl_flag_is_joined___;
+            flag &= ~___fl_flag_is_joiner___;
+          }
+          else {
+            flag &= ~___fl_flag_is_joined___;
+          }
+        }
+      }
+
       if (object.string[range->start] == f_fss_comment_s.string[0]) {
 
         // When a comment is found, escape it.
@@ -653,6 +741,25 @@ extern "C" {
 
       if (f_fss_is_graph(object, *range, state) == F_false) {
         if (F_status_is_error(state->status)) break;
+
+        previous = range->start;
+
+        f_fss_skip_past_delimit(object, range, state);
+
+        if (state->status == F_okay) {
+          if (f_fss_is_combining_joiner(object, *range, state)) {
+            if (state->status == F_combarudoo) {
+              flag |= ___fl_flag_is_combining_graph___;
+            }
+            else if (state->status == F_bound) {
+              flag |= ___fl_flag_is_joiner_graph___;
+            }
+          }
+        }
+
+        if (F_status_is_error(state->status)) break;
+
+        range->start = previous;
       }
       else {
         break;
@@ -829,6 +936,17 @@ extern "C" {
     else {
       state->status = F_okay;
     }
+
+    #undef ___fl_flag_has_eol___
+    #undef ___fl_flag_has_eol_do_prepend___
+    #undef ___fl_flag_has_graph___
+    #undef ___fl_flag_is_comment___
+    #undef ___fl_flag_is_combining___
+    #undef ___fl_flag_is_combining_graph___
+    #undef ___fl_flag_is_joined___
+    #undef ___fl_flag_is_joiner___
+    #undef ___fl_flag_is_joiner_graph___
+    #undef ___fl_flag_is_joinerd___
   }
 #endif // _di_fl_fss_extended_list_object_write_
 
index 54cca342a622cfb0c47f599ca740255095ca0a06..8c51acd007e4610aff079591fe11b5ea63e286f1 100644 (file)
@@ -169,7 +169,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_fss_is_combining().
+ *     Errors (with error bit) from: f_fss_is_combining_joiner().
  *     Errors (with error bit) from: f_fss_is_graph().
+ *     Errors (with error bit) from: f_fss_is_joiner().
  *     Errors (with error bit) from: f_fss_skip_past_delimit().
  *     Errors (with error bit) from: f_fss_skip_past_space().
  *     Errors (with error bit) from: f_memory_array_increase().
@@ -177,7 +180,10 @@ extern "C" {
  *     Errors (with error bit) from: f_memory_array_increase_by().
  *     Errors (with error bit) from: f_utf_buffer_increment().
  *
+ * @see f_fss_is_combining()
+ * @see f_fss_is_combining_joiner()
  * @see f_fss_is_graph()
+ * @see f_fss_is_joiner()
  * @see f_fss_skip_past_delimit()
  * @see f_fss_skip_past_space()
  * @see f_memory_array_increase()
@@ -312,14 +318,20 @@ extern "C" {
  *     F_okay_eol (with error bit) after reaching an EOL, which is not supported by the standard.
  *     F_parameter (with error bit) if a parameter is invalid.
  *
+ *     Errors (with error bit) from: f_fss_is_combining().
+ *     Errors (with error bit) from: f_fss_is_combining_joiner().
  *     Errors (with error bit) from: f_fss_is_graph().
+ *     Errors (with error bit) from: f_fss_is_joiner().
  *     Errors (with error bit) from: f_fss_is_space().
  *     Errors (with error bit) from: f_fss_skip_past_delimit().
  *     Errors (with error bit) from: f_memory_array_increase().
  *     Errors (with error bit) from: f_memory_array_increase_by().
  *     Errors (with error bit) from: f_utf_buffer_increment().
  *
+ * @see f_fss_is_combining()
+ * @see f_fss_is_combining_joiner()
  * @see f_fss_is_graph()
+ * @see f_fss_is_joiner()
  * @see f_fss_is_space()
  * @see f_fss_skip_past_delimit()
  * @see f_memory_array_increase()
index 20741781fb5be0922cc72478973aaee2eb6c1d09..61c362f41cbc85158c03cb82c6a0c1043db671aa 100644 (file)
@@ -12,6 +12,7 @@ extern "C" {
     if (F_status_is_error(state->status) || state->status == F_data_not) return;
 
     if (state->status == F_okay_eol) {
+
       // Move the start position to after the EOL.
       ++range->start;
       state->status = F_fss_found_object_not;
@@ -25,16 +26,21 @@ extern "C" {
       return;
     }
 
-    // Save the delimits used position in case of unterminated quote.
     const f_number_unsigned_t delimits_used = delimits->used;
-
-    // Begin the search.
     const f_number_unsigned_t begin = range->start;
-    found->start = range->start;
+
+    f_number_unsigned_t previous = 0;
+
+    found->start = begin;
 
     // Ignore all comment lines.
-    if ((flag & 0x1) && buffer.string[range->start] == f_fss_comment_s.string[0]) {
-      f_fss_seek_to_eol(buffer, range, state);
+    if ((flag & 0x1) && buffer.string[begin] == f_fss_comment_s.string[0]) {
+      state->status = f_utf_buffer_increment(buffer, range, 1);
+
+      if (state->status == F_okay) {
+        f_fss_skip_past_delimit(buffer, range, state);
+      }
+
       if (F_status_is_error(state->status)) return;
 
       if (range->start >= buffer.used || range->start > range->stop) {
@@ -43,23 +49,36 @@ extern "C" {
         return;
       }
 
-      // Move the start position to after the EOL.
-      ++range->start;
-      state->status = F_fss_found_object_not;
+      if (f_fss_is_combining_joiner(buffer, *range, state) == F_false) {
+        if (F_status_is_error_not(state->status)) {
+          f_fss_seek_to_eol(buffer, range, state);
+        }
 
-      return;
+        if (F_status_is_error(state->status)) return;
+
+        if (range->start >= buffer.used || range->start > range->stop) {
+          state->status = range->start >= buffer.used ? F_data_not_eos : F_data_not_stop;
+
+          return;
+        }
+
+        // Move the start position to after the EOL.
+        ++range->start;
+        state->status = F_fss_found_object_not;
+
+        return;
+      }
+
+      range->start = begin;
     }
 
-    // Handle quote support.
-    f_char_t quote_found = 0; // TODO: check if quote has combining characters?
+    f_char_t quote_found = 0;
 
     if (quote) *quote = f_fss_quote_type_none_e;
 
     // Identify where the object begins.
     if (buffer.string[range->start] == f_fss_slash_s.string[0]) {
-      f_number_unsigned_t first_slash = range->start;
-
-      found->start = range->start;
+      f_number_unsigned_t first_slash = found->start = range->start;
 
       state->status = f_utf_buffer_increment(buffer, range, 1);
 
@@ -71,41 +90,46 @@ extern "C" {
             if (F_status_is_error(state->status)) return;
           }
 
-          if (f_fss_is_zero_width(buffer, *range, state) == F_false) {
-            if (F_status_is_error(state->status)) return;
-          }
-          else {
+          if (buffer.string[range->start] == f_fss_placeholder_s.string[0]) {
             state->status = f_utf_buffer_increment(buffer, range, 1);
             if (F_status_is_error(state->status)) return;
 
             continue;
           }
 
-          if (buffer.string[range->start] != f_fss_slash_s.string[0]) {
-            if (f_fss_is_space(buffer, *range, state) == F_false) {
+          if (f_fss_is_combining_joiner(buffer, *range, state) == F_false) {
+            if (F_status_is_error(state->status)) return;
+
+            if (f_fss_is_zero_width(buffer, *range, state) == F_false) {
               if (F_status_is_error(state->status)) return;
-            }
 
-            // Found the end of the object while processing the slash for potential delimits.
-            if (state->status == F_true) {
-              if (range->start > begin) {
-                found->stop = range->start - 1;
-              }
-              else {
-                found->start = 1;
-                found->stop = 0;
-              }
+              if (buffer.string[range->start] != f_fss_slash_s.string[0]) {
+                if (f_fss_is_space(buffer, *range, state) == F_false) {
+                  if (F_status_is_error(state->status)) return;
+                }
 
-              state->status = f_utf_buffer_increment(buffer, range, 1);
+                // Found the end of the object while processing the slash for potential delimits.
+                if (state->status == F_true) {
+                  if (range->start > begin) {
+                    found->stop = range->start - 1;
+                  }
+                  else {
+                    found->start = 1;
+                    found->stop = 0;
+                  }
 
-              if (F_status_is_error_not(state->status)) {
-                state->status = buffer.string[range->start] == f_fss_eol_s.string[0] ? F_fss_found_object_content_not : F_fss_found_object;
-              }
+                  state->status = f_utf_buffer_increment(buffer, range, 1);
 
-              return;
-            }
+                  if (F_status_is_error_not(state->status)) {
+                    state->status = buffer.string[range->start] == f_fss_eol_s.string[0] ? F_fss_found_object_content_not : F_fss_found_object;
+                  }
 
-            break;
+                  return;
+                }
+
+                break;
+              }
+            }
           }
 
           state->status = f_utf_buffer_increment(buffer, range, 1);
@@ -139,7 +163,7 @@ extern "C" {
       }
     }
     else if (!(flag & 0x2) && (buffer.string[range->start] == f_fss_quote_single_s.string[0] || buffer.string[range->start] == f_fss_quote_double_s.string[0] || buffer.string[range->start] == f_fss_quote_grave_s.string[0])) {
-      quote_found = buffer.string[range->start];
+      quote_found = buffer.string[range->start]; // TODO: check for combining and joiner.
       found->start = ++range->start;
     }
 
@@ -148,7 +172,6 @@ extern "C" {
       f_number_unsigned_t first_slash = 0;
       f_number_unsigned_t slash_count = 0;
       f_number_unsigned_t location = 0;
-      f_number_unsigned_t previous = 0;
 
       while (range->start <= range->stop && range->start < buffer.used) {
 
@@ -157,6 +180,8 @@ extern "C" {
           if (F_status_set_fine(state->status) == F_interrupt) return;
         }
 
+        // TODO: check for combinign and joiner flags.
+
         if (buffer.string[range->start] == f_fss_slash_s.string[0]) {
           first_slash = range->start;
           slash_count = 1;
@@ -201,10 +226,11 @@ extern "C" {
             return;
           }
 
-          if (buffer.string[range->start] == quote_found) {
+          if (buffer.string[range->start] == quote_found) { // TODO: check for combining and joiner.
             location = range->start;
 
             // Check to see if there is a whitespace, EOS, or EOL after the quote, if not, then this is not a closing quote and delimits do not apply.
+            // TODO: This should check for combining and joining and set flags.
             if (range->start + 1 <= range->stop && range->start + 1 < buffer.used) {
               ++range->start;
 
@@ -271,48 +297,42 @@ extern "C" {
 
                 range->start = location + 1;
 
-                while (buffer.string[range->start] == f_fss_placeholder_s.string[0]) {
-
-                  if (state->interrupt) {
-                    state->interrupt((void *) state, 0);
-                    if (F_status_set_fine(state->status) == F_interrupt) return;
-                  }
-
-                  if (++range->start >= buffer.used) {
-                    state->status = F_okay_eos;
-
-                    return;
-                  }
-
-                  if (range->start > range->stop) {
-                    state->status = F_okay_stop;
-
-                    return;
-                  }
-                } // while
+                state->status = f_fss_skip_past_delimit(buffer, range, 1);
+                if (F_status_is_error(state->status)) return;
 
                 if (f_fss_is_graph(buffer, *range, state) != F_true) {
                   if (F_status_is_error(state->status)) return;
 
                   // Anything other than a new line must be checked if a combining or joiner is in the next character.
-                  if (buffer.string[range->start] != f_fss_eol_s.string[0] && range->start <= range->stop && range->start < buffer.used) {
+                  // TODO: review this logic.
+                  if (buffer.string[range->start] != f_fss_eol_s.string[0]) {
                     previous = range->start;
 
                     state->status = f_utf_buffer_increment(buffer, range, 1);
                     if (F_status_is_error(state->status)) return;
 
-                    state->status = f_utf_is_combining_joiner(
-                      buffer.string + range->start,
-                      (range->stop - range->start) + 1 > buffer.used - range->start
-                        ? buffer.used - range->start
-                        : (range->stop - range->start) + 1
-                    );
-
-                    // When status is F_true, then this is a combining or joiner that causes the previous character to be treated as a graph.
-                    if (state->status == F_false) {
-                      range->start = previous;
-                    } else if (F_status_is_error(state->status)) {
-                      return;
+                    if (state->status == F_okay) {
+                      f_fss_skip_past_delimit(buffer, range, state);
+                      if (F_status_is_error(state->status)) return;
+
+                      if (state->status == F_okay) {
+                        f_fss_is_combining_joiner(buffer, *range, state);
+                        if (F_status_is_error(state->status)) return;
+                      }
+
+                      // TODO: the status is F_combarudoo for combining and F_bound for joiner.
+
+                      // Swap the status to represent F_true for is graph and otherwise for not is graph.
+                      if (state->status == F_true) {
+                        range->start = previous;
+                        state->status = F_false;
+                      }
+                      else {
+                        state->status = F_true;
+                      }
+                    }
+                    else {
+                      state->status = F_true;
                     }
                   }
                 }
@@ -573,6 +593,9 @@ extern "C" {
 
           return;
         }
+        else {
+          // TODO: check for combining and joiner and set flag.
+        }
 
         state->status = f_utf_buffer_increment(buffer, range, 1);
         if (F_status_is_error(state->status)) return;
@@ -602,10 +625,31 @@ extern "C" {
           if (F_status_set_fine(state->status) == F_interrupt) return;
         }
 
-        if (f_fss_is_space(buffer, *range, state) == F_false) {
+        f_fss_skip_past_delimit(object, range, state);
+        if (F_status_is_error(state->status)) break;
+        if (range->start > range->stop || range->start >= buffer.used) break;
+
+        if (f_fss_is_combining_joiner(buffer, *range, state) == F_true) {
+          f_fss_skip_past_combining_joiner(buffer, range, state);
+          if (F_status_is_error(state->status)) return;
+
+          if (state->status == F_combarudoo) {
+            state->status = f_utf_buffer_increment(buffer, range, 2);
+            if (F_status_is_error(state->status)) return;
+
+            continue;
+          }
+        }
+        else if (F_status_is_error(state->status)) {
+          return;
+        }
+        else if (f_fss_is_space(buffer, *range, state) == F_false) {
           if (F_status_is_error(state->status)) return;
         }
         else {
+          // TODO: Set internal flag here for designating that a space is found.
+          //       The combining/joiner check above should check for this flag so that.
+          //       If the flag is already set, then decrement/reset back to space position (maybe create a peek or similar function to check?).
           break;
         }
 
index 6a5ce20094905bbf62d891ff6a34ce17e7b7e521..05b3b01fd9dc968f3dfdd52b00c62941a82f7c49 100644 (file)
@@ -70,11 +70,10 @@ extern "C" {
  *
  *     Errors (with error bit) from: f_memory_array_increase().
  *     Errors (with error bit) from: f_memory_array_increase_by().
- *     Errors (with error bit) from: f_fss_is_combining().
+ *     Errors (with error bit) from: f_fss_is_combining_joiner().
  *     Errors (with error bit) from: f_fss_is_graph().
  *     Errors (with error bit) from: f_fss_is_space().
  *     Errors (with error bit) from: f_fss_is_zero_width().
- *     Errors (with error bit) from: f_fss_skip_past_combining().
  *     Errors (with error bit) from: f_fss_skip_past_delimit().
  *     Errors (with error bit) from: f_fss_skip_past_space().
  *     Errors (with error bit) from: f_utf_buffer_increment().
@@ -82,11 +81,10 @@ extern "C" {
  *
  * @see f_memory_array_increase()
  * @see f_memory_array_increase_by()
- * @see f_fss_is_combining()
+ * @see f_fss_is_combining_joiner()
  * @see f_fss_is_graph()
  * @see f_fss_is_space()
  * @see f_fss_is_zero_width()
- * @see f_fss_skip_past_combining()
  * @see f_fss_skip_past_delimit()
  * @see f_fss_skip_past_space()
  * @see f_utf_buffer_increment()
@@ -157,7 +155,7 @@ extern "C" {
  *   Set to NULL to not use.
  *
  * @see f_fss_is_space()
- * @see f_fss_skip_past_combining()
+ * @see f_fss_skip_past_combining_joiner()
  * @see f_fss_skip_past_delimit()
  * @see f_fss_skip_past_space()
  * @see f_memory_array_increase()
index 53a570338bb3862a4d9ada6f4666f80672e1df11..b714e36a05efc1f1b423bf377c093aa7ee9059d0 100644 (file)
@@ -1,7 +1,7 @@
 # fss-0002 iki-0000
 #
 # license open-standard-license-1.0-or-later
-# version 2026/06/20
+# version 2026/06/27
 #
 # This file (assumed to be named fss.txt) can be more easily read using the following iki_read commands:
 #   iki_read fss.txt +Q -w -rrrrrrrr anti-KISS anti-KISS ASCII ASCII BOM BOM FSS FSS KISS KISS UTF-8 UTF-8 URL URL XML XML -WWW character "'" "'" code '"' '"' italic '"' '"'
@@ -134,6 +134,7 @@ Featureless Settings Specifications:
   This delimit only applies to the start of a comment (the pound character:"#" character) as there is no terminating character for a comment (other than a new line character:"\n").
   A line containing a valid comment is in its entirety ignored.
   This means that if there is white space before the designation symbol (the pound character:"#" character) then that white space is ignored.
+  Comments follow the standard combining and joiner rules.
 
   Unless otherwise specified, all designation characters italic:"must" represent ASCII:"American Standard Code for Information Interchange" codes.
   With designation characters being any character code used to designate how to identify an Object or Content (such as a colon character:":" at the end of a basic list).