]> Kevux Git Server - fll/commitdiff
Progress: Work on embedded list read.
authorKevin Day <Kevin@kevux.org>
Mon, 5 Oct 2026 02:18:31 +0000 (21:18 -0500)
committerKevin Day <Kevin@kevux.org>
Mon, 5 Oct 2026 02:18:31 +0000 (21:18 -0500)
Base the combining test for embedded list content off of extended list content.

I completed the initial pass.
I need to now review the code, look for problems, and get the unit tests passing.

Fix a problem in the extended list test where I wasn't actually checking a potentially valid object opener.

level_1/fl_fss/c/fss/embedded_list.c
level_1/fl_fss/data/tests/contents/embedded_list-combining_read-1.txt
level_1/fl_fss/data/tests/contents/embedded_list-combining_read-4.txt
level_1/fl_fss/data/tests/contents/embedded_list-combining_read-5.txt [deleted file]
level_1/fl_fss/data/tests/contents/extended_list-combining_read-4.txt
level_1/fl_fss/data/tests/counts/embedded_list-combining_read.txt [new file with mode: 0644]
level_1/fl_fss/data/tests/matches/embedded_list-combining_read.txt [new file with mode: 0644]
level_1/fl_fss/data/tests/strings/embedded_list-combining_read.txt
level_1/fl_fss/data/tests/strings/extended_list-combining_read.txt
level_1/fl_fss/tests/unit/c/test-fss-embedded_list_content_read.c
level_1/fl_fss/tests/unit/c/test-fss.c

index 6f9e86a733616ddf2ea27a39704e3f1e097a242d..0ebc91c09f2d261aa528ce74ced333466a242192 100644 (file)
@@ -53,24 +53,25 @@ extern "C" {
     #define ___fl_flag_has_graph_first___                  0x2
     #define ___fl_flag_has_delimit_comment___              0x4
     #define ___fl_flag_has_delimit_comment_graph_first___  0x6
-    #define ___fl_flag_is_delimit_close___                 0x8
-    #define ___fl_flag_is_delimit_close_delimit_comment___ 0xc
-    #define ___fl_flag_is_object___                        0x10
-    #define ___fl_flag_is_open___                          0x20
-    #define ___fl_flag_is_open_close_graph_first___        0x2a
+    #define ___fl_flag_has_joiner_combining___             0x8
+    #define ___fl_flag_is_delimit_close___                 0x10
+    #define ___fl_flag_is_delimit_close_delimit_comment___ 0x14
+    #define ___fl_flag_is_object___                        0x20
+    #define ___fl_flag_is_open___                          0x40
+    #define ___fl_flag_is_open_close_graph_first___        0x52
 
     const f_number_unsigned_t delimits_used = delimits->used;
     const f_number_unsigned_t comments_used = comments->used;
 
     f_number_unsigned_t depth = 0;
     f_number_unsigned_t position = 0;
-    f_number_unsigned_t position_previous = range->start;
+    f_number_unsigned_t previous = range->start;
     f_number_unsigned_t line_start = range->start;
     f_number_unsigned_t newline_last = range->start;
     f_number_unsigned_t comment_delimit = 0;
     f_number_unsigned_t slash_first = 0;
     f_number_unsigned_t slash_last = 0;
-    f_number_unsigned_t before_list_open = position_previous;
+    f_number_unsigned_t before_list_open = previous;
     f_number_unsigned_t close_location = 0;
 
     uint8_t flag_fl = ___fl_flag_has_graph_first___;
@@ -98,15 +99,26 @@ extern "C" {
           delimits->array[delimits->used++] = comment_delimit;
         }
 
-        newline_last = position_previous = range->start++;
+        newline_last = previous = range->start++;
         line_start = range->start;
         flag_fl |= ___fl_flag_has_graph_first___;
       }
       else if (buffer.string[range->start] == f_fss_slash_s.string[0] && (flag_fl & ___fl_flag_has_graph_first___)) {
-        slash_first = slash_last = position_previous = range->start++;
-        cache->slashes->array[depth] = 1;
+        previous = range->start++;
+
+        if (f_fss_is_combining_joiner(buffer, *range, state) == F_true) {
+
+          // This cannot be a valid object close at this point, seek until EOL.
+          f_fss_seek_to_eol(buffer, range, state);
+          if (F_status_is_error(state->status)) break;
 
-        // TODO: needs combining/joiner check.
+          continue;
+        }
+
+        if (F_status_is_error(state->status)) break;
+
+        slash_first = slash_last = previous;
+        cache->slashes->array[depth] = 1;
 
         for (; range->start <= range->stop && range->start < buffer.used && (buffer.string[range->start] == f_fss_placeholder_s.string[0] || buffer.string[range->start] == f_fss_slash_s.string[0]); ++range->start) {
 
@@ -115,16 +127,35 @@ extern "C" {
             if (F_status_set_fine(state->status) == F_interrupt) break;
           }
 
-          position_previous = range->start;
+          previous = range->start;
 
-          if (buffer.string[position_previous] == f_fss_slash_s.string[0]) {
-            slash_last = position_previous;
+          if (buffer.string[previous] == f_fss_slash_s.string[0]) {
+            ++range->start;
+
+            if (f_fss_is_combining_joiner(buffer, *range, state) == F_true) {
+              cache->slashes->array[depth] = 0;
+              flag_fl |= ___fl_flag_has_joiner_combining___;
+
+              // This cannot be a valid object close at this point, seek until EOL.
+              f_fss_seek_to_eol(buffer, range, state);
+
+              break;
+            }
+
+            range->start = previous;
+            slash_last = previous;
             ++cache->slashes->array[depth];
           }
         } // for
 
         if (F_status_is_error(state->status) || range->start >= buffer.used || range->start > range->stop) break;
 
+        if (flag_fl & ___fl_flag_has_joiner_combining___) {
+          flag_fl &= ~___fl_flag_has_joiner_combining___;
+
+          continue;
+        }
+
         // All slashes for an open are delimited (because it could represent a slash in the object name).
         // For example 'object {' = valid open, name 'object', 'object \{' represents 'object {', 'object \\{' = valid open, name 'object \', 'object \\\{' represents 'object \{', etc..
         // Only the first slash before a close is delimited, all others are maintained.
@@ -138,23 +169,35 @@ extern "C" {
             delimits->array[delimits->used++] = comment_delimit;
           }
 
-          newline_last = position_previous = range->start++;
+          newline_last = previous = range->start++;
           line_start = range->start;
           flag_fl |= ___fl_flag_has_graph_first___;
         }
         else if (buffer.string[range->start] == f_fss_embedded_list_open_s.string[0] || buffer.string[range->start] == f_fss_embedded_list_close_s.string[0]) {
-          before_list_open = position_previous;
-          flag_fl &= ~___fl_flag_is_open_close_graph_first___;
+          before_list_open = range->start++;
+
+          if (f_fss_is_combining_joiner(buffer, *range, state) == F_true) {
+
+            // This cannot be a valid object close at this point, seek until EOL.
+            f_fss_seek_to_eol(buffer, range, state);
+            if (F_status_is_error(state->status)) break;
 
-          // TODO: needs combining/joiner check.
+            continue;
+          }
+
+          if (F_status_is_error(state->status)) break;
+
+          range->start = before_list_open;
+          before_list_open = previous;
+          flag_fl &= ~___fl_flag_is_open_close_graph_first___;
 
           if (buffer.string[range->start] == f_fss_embedded_list_open_s.string[0]) {
             flag_fl |= ___fl_flag_is_open___;
           }
 
-          position_previous = range->start++;
+          previous = range->start++;
 
-          f_fss_skip_past_space_previous(buffer, range, state, &position_previous);
+          f_fss_skip_past_space_previous(buffer, range, state, &previous);
 
           if (F_status_is_error(state->status)) break;
           if (range->start > range->stop || range->start >= buffer.used) break;
@@ -189,7 +232,7 @@ extern "C" {
                 }
 
                 // Delimit slashes and placeholders are required to be in the ASCII range.
-                position_previous = range->start++;
+                previous = range->start++;
               } // while
 
               // When slashes are even, the object is valid and needs to be processed.
@@ -246,28 +289,49 @@ extern "C" {
           }
         }
         else if (buffer.string[range->start] == f_fss_comment_s.string[0] && (flag_fl & ___fl_flag_has_graph_first___)) {
+          previous = range->start++;
+
+          if (f_fss_is_combining_joiner(buffer, *range, state) == F_true) {
+
+            // This cannot be a valid object close at this point, seek until EOL.
+            f_fss_seek_to_eol(buffer, range, state);
+            if (F_status_is_error(state->status)) break;
+
+            continue;
+          }
+
+          if (F_status_is_error(state->status)) break;
+
           flag_fl |= ___fl_flag_is_delimit_close___;
           flag_fl &= ~___fl_flag_has_graph_first___;
           comment_delimit = slash_first;
-
-          // TODO: needs combining/joiner check.
+          range->start = previous;
         }
         else {
           flag_fl &= ~___fl_flag_has_graph_first___;
         }
       }
       else if (buffer.string[range->start] == f_fss_embedded_list_open_s.string[0]) {
-        flag_fl &= ~___fl_flag_has_graph_first___;
-        before_list_open = position_previous;
-        position_previous = range->start++;
+        before_list_open = previous;
+        previous = range->start++;
 
-        // TODO: needs combining/joiner check.
+        f_fss_skip_past_space_previous(buffer, range, state, &previous);
 
-        f_fss_skip_past_space_previous(buffer, range, state, &position_previous);
+        // 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) {
+
+          // This cannot be a valid object close at this point, seek until EOL.
+          f_fss_seek_to_eol(buffer, range, state);
+          if (F_status_is_error(state->status)) break;
+
+          continue;
+        }
 
         if (F_status_is_error(state->status)) break;
         if (range->start > range->stop || range->start >= buffer.used) break;
 
+        flag_fl &= ~___fl_flag_has_graph_first___;
+
         if (buffer.string[range->start] == f_fss_eol_s.string[0]) {
           if (++depth >= cache->objects->size) {
             state->status = f_memory_array_resize(depth + 2, sizeof(f_range_t), (void **) &cache->objects->array, &cache->objects->used, &cache->objects->size);
@@ -336,9 +400,17 @@ extern "C" {
       else if (buffer.string[range->start] == f_fss_embedded_list_close_s.string[0] && (flag_fl & ___fl_flag_has_graph_first___)) {
         close_location = range->start;
 
-        // TODO: needs combining/joiner check.
+        f_fss_skip_past_space_previous(buffer, range, state, &previous);
+
+        // 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) {
 
-        f_fss_skip_past_space_previous(buffer, range, state, &position_previous);
+          // This cannot be a valid object close at this point, seek until EOL.
+          f_fss_seek_to_eol(buffer, range, state);
+          if (F_status_is_error(state->status)) break;
+
+          continue;
+        }
 
         if (F_status_is_error(state->status)) break;
         if (range->start > range->stop || range->start >= buffer.used) break;
@@ -432,41 +504,26 @@ extern "C" {
         }
         else {
 
-          // No valid object close found, seek until EOL.
-          while (range->start <= range->stop && range->start < buffer.used) {
-
-            if (state->interrupt) {
-              state->interrupt((void *) state, 0);
-              if (F_status_set_fine(state->status) == F_interrupt) break;
-            }
-
-            if (buffer.string[range->start] == f_fss_eol_s.string[0]) {
-              if (flag_fl & ___fl_flag_has_delimit_comment___) {
-                state->status = f_memory_array_increase(state->step_small, sizeof(f_number_unsigned_t), (void **) &delimits->array, &delimits->used, &delimits->size);
-                if (F_status_is_error(state->status)) break;
-
-                delimits->array[delimits->used++] = comment_delimit;
-              }
-
-              newline_last = range->start;
-              line_start = newline_last + 1;
-              flag_fl |= ___fl_flag_has_graph_first___;
-
-              break;
-            }
-
-            position_previous = range->start;
-
-            state->status = f_utf_buffer_increment(buffer, range, 1);
-            if (F_status_is_error(state->status)) break;
-          } // while
-
+          // This cannot be a valid object close at this point, seek until EOL.
+          f_fss_seek_to_eol(buffer, range, state);
           if (F_status_is_error(state->status)) break;
         }
       }
       else if (buffer.string[range->start] == f_fss_comment_s.string[0] && (flag_fl & ___fl_flag_has_graph_first___)) {
+        previous = range->start++;
 
-        // TODO: needs combining/joiner check.
+        if (f_fss_is_combining_joiner(buffer, *range, state) == F_true) {
+
+          // This cannot be a valid object close at this point, seek until EOL.
+          f_fss_seek_to_eol(buffer, range, state);
+          if (F_status_is_error(state->status)) break;
+
+          continue;
+        }
+
+        if (F_status_is_error(state->status)) break;
+
+        range->start = previous;
 
         // The newline_last is initialized to the range->start, which may not actually be a new line.
         position = (buffer.string[newline_last] == f_string_eol_s.string[0]) ? newline_last + 1 : newline_last;
@@ -497,7 +554,7 @@ extern "C" {
         comments->array[comments->used++].stop = range->start++;
       }
       else if (buffer.string[range->start] != f_fss_eol_s.string[0]) {
-        position_previous = range->start;
+        previous = range->start;
 
         if (flag_fl & ___fl_flag_has_graph_first___) {
           if (f_fss_is_space(buffer, *range, state) == F_false) {
@@ -529,6 +586,7 @@ extern "C" {
     #undef ___fl_flag_has_graph_first___
     #undef ___fl_flag_has_delimit_comment___
     #undef ___fl_flag_has_delimit_comment_graph_first___
+    #undef ___fl_flag_has_joiner_combining___
     #undef ___fl_flag_is_delimit_close___
     #undef ___fl_flag_is_delimit_close_delimit_comment___
     #undef ___fl_flag_is_object___
@@ -810,7 +868,7 @@ extern "C" {
         f_fss_skip_past_delimit(content, range, state);
 
         if (state->status == F_okay) {
-          if (f_fss_is_combining_joiner(content, *range, state)) {
+          if (f_fss_is_combining_joiner(content, *range, state) == F_true) {
             if (state->status == F_combarudoo) {
               flag |= ___fl_flag_is_combining_graph___;
             }
@@ -1041,7 +1099,7 @@ extern "C" {
         f_fss_skip_past_delimit(object, range, state);
 
         if (state->status == F_okay) {
-          if (f_fss_is_combining_joiner(object, *range, state)) {
+          if (f_fss_is_combining_joiner(object, *range, state) == F_true) {
             if (state->status == F_combarudoo) {
               flag |= ___fl_flag_is_combining_graph___;
             }
index dc1e830211ffe79370e62523b3d6a6607df42f22..2fed02e6c71c90f6530c35c7d4178fa4fe489a52 100644 (file)
@@ -1,3 +1,3 @@
+́
   is_second and content 2.
- ́{
-  has ́ content 3.
+  does have ́ content 3.
index a5e0c698b8c7e74c10ee013666695091d73f6eb0..449318919c028b803efaccab19128cc5514b0449 100644 (file)
@@ -1,2 +1,2 @@
   sixtẖ̚ is content 6.
-  not a valid list {́
+  not a valid list{́
diff --git a/level_1/fl_fss/data/tests/contents/embedded_list-combining_read-5.txt b/level_1/fl_fss/data/tests/contents/embedded_list-combining_read-5.txt
deleted file mode 100644 (file)
index d765694..0000000
+++ /dev/null
@@ -1 +0,0 @@
-  sixtẖ̚ is content 6.
index 51eaa89ac10d93d041f06bf88c0035c74e8a8991..449318919c028b803efaccab19128cc5514b0449 100644 (file)
@@ -1,2 +1,2 @@
   sixtẖ̚ is content 6.
-  not a valid list{:́
+  not a valid list{́
diff --git a/level_1/fl_fss/data/tests/counts/embedded_list-combining_read.txt b/level_1/fl_fss/data/tests/counts/embedded_list-combining_read.txt
new file mode 100644 (file)
index 0000000..627e109
--- /dev/null
@@ -0,0 +1,5 @@
+1
+1
+1
+1
+1
diff --git a/level_1/fl_fss/data/tests/matches/embedded_list-combining_read.txt b/level_1/fl_fss/data/tests/matches/embedded_list-combining_read.txt
new file mode 100644 (file)
index 0000000..5ee4e75
--- /dev/null
@@ -0,0 +1,6 @@
+2
+2
+2
+2
+2
+2
index a20d70e1a88d4f20e1563f910602b2512f51ea1e..bb228fea1c25628ea89b850495a0d016785adbe1 100644 (file)
@@ -2,10 +2,9 @@ first valid.{
   content 1.
 }
 is_second and does not have embedded new line.{
+́
   is_second and content 2.
- ́{
-  has ́ content 3.
-}
+  does have ́ content 3.
 }
 fourth ͜no_space{
   has ͜no_space content 4.
@@ -15,6 +14,5 @@ fifth is valid.{
 }
 sixtẖ̚ is valid with two combiners.{
   sixtẖ̚ is content 6.
-  not a valid list {́
-  }
+  not a valid list{́
 }
index 9b8083371bbb652466e8ef5dfcdb1eaecb1618b3..bb228fea1c25628ea89b850495a0d016785adbe1 100644 (file)
@@ -14,5 +14,5 @@ fifth is valid.{
 }
 sixtẖ̚ is valid with two combiners.{
   sixtẖ̚ is content 6.
-  not a valid list{:́
+  not a valid list{́
 }
index de6241d7d74c0fe70f9bbc6845214f05cecbc11a..1a9d39b05405ecdc3bd80edf01aa222d4f65888d 100644 (file)
@@ -343,6 +343,9 @@ void test__fl_fss_embedded_list_content_read__works_using_combining(void **void_
 
   {
     // Note: These files are required to have the same number of lines and each line should probably be at max 255 characters.
+    FILE *file_counts = data__file_open__named("counts", "embedded_list", "combining_read");
+    FILE *file_matches = data__file_open__named("matches", "embedded_list", "combining_read");
+    FILE *file_objects = data__file_open__named("objects", "embedded_list", "combining_read");
     FILE *file_strings = data__file_open__named("strings", "embedded_list", "combining_read");
 
     FILE *file_contents[] = {
@@ -351,42 +354,51 @@ void test__fl_fss_embedded_list_content_read__works_using_combining(void **void_
       data__file_open__named_at("contents", "embedded_list", "combining_read", 2),
       data__file_open__named_at("contents", "embedded_list", "combining_read", 3),
       data__file_open__named_at("contents", "embedded_list", "combining_read", 4),
-      data__file_open__named_at("contents", "embedded_list", "combining_read", 5),
     };
 
+    assert_non_null(file_counts);
+    assert_non_null(file_matches);
+    assert_non_null(file_objects);
     assert_non_null(file_strings);
     assert_non_null(file_contents[0]);
     assert_non_null(file_contents[1]);
     assert_non_null(file_contents[2]);
     assert_non_null(file_contents[3]);
     assert_non_null(file_contents[4]);
-    assert_non_null(file_contents[5]);
 
+    const uint8_t sets_total = 5;
+
+    int counts = 0;
+    int matches = 0;
     size_t max = 0;
-    char *line_string = 0;
-    char *line_content[] = {
-      0,
-      0,
-      0,
-      0,
-      0,
-      0,
-    };
     ssize_t result = 0;
-    const uint8_t total_content = 6;
 
-    f_string_static_t buffer_string = f_string_static_t_initialize;
+    char *line_counts = 0;
+    char *line_matches = 0;
+    char *line_object = 0;
 
-    f_state_t state = f_state_t_initialize;
     f_range_t range = f_range_t_initialize;
     f_range_t found_object = f_range_t_initialize;
-    f_fss_nest_t found = f_fss_nest_t_initialize;
+    f_ranges_t found_content = f_ranges_t_initialize;
     f_ranges_t comments = f_ranges_t_initialize;
+
+    f_fss_nest_t found = f_fss_nest_t_initialize;
+    f_state_t state = f_state_t_initialize;
+    f_status_t status_object = F_okay;
     f_uint8s_t quotes = f_uint8s_t_initialize;
     f_number_unsigneds_t delimits = f_number_unsigneds_t_initialize;
-    f_string_dynamic_t result_string = f_string_dynamic_t_initialize;
-    f_string_dynamic_t delimit_string = f_string_dynamic_t_initialize;
-    f_status_t status_object = F_okay;
+
+    f_string_dynamic_t set_delimit = f_string_dynamic_t_initialize;
+    f_string_dynamic_t set_result = f_string_dynamic_t_initialize;
+    f_string_dynamic_t set_strings = f_string_dynamic_t_initialize;
+
+    f_string_dynamic_t set_contents[] = {
+      macro_f_string_dynamic_t_initialize_2(0, 0),
+      macro_f_string_dynamic_t_initialize_2(0, 0),
+      macro_f_string_dynamic_t_initialize_2(0, 0),
+      macro_f_string_dynamic_t_initialize_2(0, 0),
+      macro_f_string_dynamic_t_initialize_2(0, 0),
+    };
 
     f_ranges_t objects = f_ranges_t_initialize;
     f_number_unsigneds_t positions = f_number_unsigneds_t_initialize;
@@ -395,112 +407,245 @@ void test__fl_fss_embedded_list_content_read__works_using_combining(void **void_
 
     state.data = (void *) &cache;
 
-    for (;;) {
+    {
+      const f_status_t status = data__file_load_buffer(file_strings, &set_strings);
+
+      if (F_status_is_error(status)) {
+        printf("[ -------> ] --- [00] Failure with data__file_load_buffer() for loading file strings, status=%u has error bit set.\n", status);
+      }
+
+      assert_true(F_status_is_error_not(status));
+    }
+
+    for (uint8_t i = 0; i < sets_total; ++i) {
+
+      const f_status_t status = data__file_load_buffer(file_contents[i], &set_contents[i]);
+
+      if (F_status_is_error(status)) {
+        printf("[ -------> ] --- [01] Failure with data__file_load_buffer() for loading file contents at %u, status=%u has error bit set.\n", i, status);
+      }
+
+      assert_true(F_status_is_error_not(state.status));
+    } // for
+
+    {
+      const f_status_t status = f_string_dynamic_append(set_strings, &set_delimit);
+
+      if (status != F_okay) {
+        printf("[ -------> ] --- [02] Failure with f_string_dynamic_append() for preparing delimit string, status=%u, expected=%u.\n", status, F_okay);
+      }
+
+      assert_int_equal(status, F_okay);
+    }
+
+    range.start = 0;
+    range.stop = set_strings.used - 1;
+
+    for (f_number_unsigned_t set = 0; set < sets_total; ++set) {
 
       max = 255;
 
-      result = getline(&line_string, &max, file_strings);
-      if (result == -1) break;
+      result = getline(&line_object, &max, file_objects);
 
-      buffer_string.string = line_string;
-      buffer_string.used = (f_number_unsigned_t) result;
-      buffer_string.size = buffer_string.used;
+      if (result < 0) {
+        printf("[ -------> ] --- [03] Failure with getline() for objects, with set %lu, result is negative.\n", set);
+      }
 
-      for (uint8_t i = 0; i < total_content; ++i) {
+      assert_return_code(result, 0);
 
-        max = 255;
+      // The newline is copied by getline(), and so remove that newline before comparing.
+      line_object[result ? result - 1 : 0] = 0;
 
-        result = getline(&line_content[i], &max, file_contents[i]);
+      max = 255;
 
-        assert_return_code(result, 0);
+      result = getline(&line_matches, &max, file_matches);
 
-        // The newline is copied by getline(), and so remove that newline before comparing.
-        line_content[i][result ? result - 1 : 0] = 0;
-      } // or
+      if (result < 0) {
+        printf("[ -------> ] --- [04] Failure with getline() for matches, with set %lu, result is negative.\n", set);
+      }
+
+      assert_true(result >= 0);
+
+      matches = atoi(line_matches);
 
-      state.status = F_none;
-      range.start = 0;
-      range.stop = buffer_string.used - 1;
       found_object.start = 1;
       found_object.stop = 0;
+      state.status = F_none;
 
-      fl_fss_embedded_list_object_read(buffer_string, &range, &found_object, &delimits, &state);
+      fl_fss_embedded_list_object_read(set_strings, &range, &found_object, &delimits, &state);
 
-      assert_true(state.status == F_fss_found_object || state.status == F_fss_found_object_not);
+      if (matches) {
+
+        // When matches is 2, then this matches both object and content.
+        if (matches == 2) {
+          if (!(state.status == F_fss_found_object)) {
+            printf("[ -------> ] --- [05] Failure with fl_fss_embedded_list_object_read(), with set %lu, matches=%d, status=%u, expected %u.\n", set, matches, state.status, F_fss_found_object);
+          }
+
+          assert_true(state.status == F_fss_found_object);
+        }
+
+        // When matches is 1, then this matches only object.
+        else {
+          if (!(state.status == F_fss_found_object_content_not)) {
+            printf("[ -------> ] --- [06] Failure with fl_fss_embedded_list_object_read(), with set %lu, matches=%d, status=%u, expected %u.\n", set, matches, state.status, F_fss_found_object_content_not);
+          }
+
+          assert_true(state.status == F_fss_found_object_content_not);
+        }
+      }
+      else {
+        if (!(state.status == F_fss_found_object_not)) {
+          printf("[ -------> ] --- [07] Failure with with fl_fss_embedded_list_object_read(), set %lu, matches=%d, status=%u, expected %u.\n", set, matches, state.status, F_fss_found_object_not);
+        }
+
+        assert_true(state.status == F_fss_found_object_not);
+      }
 
       status_object = state.status;
       state.status = F_none;
 
       if (status_object == F_fss_found_object) {
-        fl_fss_embedded_list_content_read(buffer_string, &range, &found, &delimits, &comments, &state);
+
+        // The Object had to be read before getting to the Content, so test it as well.
+        {
+          const f_status_t status = data__extract_from_source(set_strings, found_object, &set_result);
+
+          if (F_status_is_error(status)) {
+            printf("[ -------> ] --- [14] Failure with data__extract_from_source() for extract object, with set %lu, status=%u has error bit set.\n", set, status);
+          }
+
+          assert_true(F_status_is_error_not(status));
+        }
+
+        if (strcmp(set_result.string, line_object)) {
+          printf("[ -------> ] --- [09] Failure with set %lu, object strings do not match.\n", set);
+        }
+
+        assert_string_equal(set_result.string, line_object);
+
+        max = 255;
+
+        result = getline(&line_counts, &max, file_counts);
+
+        if (result < 0) {
+          printf("[ -------> ] --- [10] Failure with getline() for counts, with set %lu, result is negative.\n", set);
+        }
+
+        assert_true(result >= 0);
+
+        counts = atoi(line_counts);
+
+        fl_fss_embedded_list_content_read(set_strings, &range, &found, &delimits, &comments, &state);
+
+        if (!(state.status == F_fss_found_content || state.status == F_data_not)) {
+          printf("[ -------> ] --- [11] Failure with fl_fss_embedded_list_content_read(), with set %lu, status=%u, expected %u, or %u.\n", set, state.status, F_fss_found_content, F_data_not);
+        }
 
         assert_true(state.status == F_fss_found_content || state.status == F_data_not);
 
         if (state.status == F_fss_found_content) {
-          // @todo
+          if (!found_content.used) {
+            printf("[ -------> ] --- [12] Failure with fl_fss_embedded_list_content_read(), with set %lu, expected found_content.used (%lu) <> 0.\n", set, found_content.used);
+          }
+
+          assert_true(found_content.used);
+
+          if (found_content.used != (f_number_unsigned_t) counts) {
+            printf("[ -------> ] --- [13] Failure with fl_fss_embedded_list_content_read(), with set %lu, expected found_content.used (%lu) == %lu, found = '%s', expected = '%s'.\n", set, found_content.used, (f_number_unsigned_t) counts, set_result.string ? set_result.string : "", set_contents[set].string ? set_contents[set].string : "");
+          }
+
+          assert_true(found_content.used == (f_number_unsigned_t) counts);
+
+          state.status = F_none;
+
+          f_fss_apply_delimit(delimits, &set_delimit, &state);
+
+          if (state.status != F_okay) {
+            printf("[ -------> ] --- [14] Failure with f_fss_apply_delimit(), with set %lu, status=%u, expected=%u.\n", set, state.status, F_okay);
+          }
+
+          assert_int_equal(state.status, F_okay);
+
+          {
+            const f_status_t status = data__extract_from_source(set_delimit, found_content.array[0], &set_result);
+
+            if (F_status_is_error(status)) {
+              printf("[ -------> ] --- [15] Failure with data__extract_from_source() for extract set contents, with set %lu, status=%u has error bit set.\n", set, status);
+            }
+
+            assert_true(F_status_is_error_not(status));
+          }
+
+          if (strcmp(set_result.string, set_contents[set].string)) {
+            printf("[ -------> ] --- [16] Failure with set %lu, content strings do not match.\n", set);
+          }
+
+          assert_string_equal(set_result.string, set_contents[set].string);
         }
         else {
-          assert_true(!found.used);
+          if (found_content.used) {
+            printf("[ -------> ] --- [17] Failure with set %lu, should not have any content, but match %lu.\n", set, found_content.used);
+          }
+
+          assert_true(!found_content.used);
         }
       }
 
-      if (line_string) free(line_string);
-      if (result_string.string) free(result_string.string);
-      if (delimit_string.string) free(delimit_string.string);
-      if (delimits.array) free(delimits.array);
       if (comments.array) free(comments.array);
+      if (delimits.array) free(delimits.array);
+      if (found_content.array) free(found_content.array);
       if (quotes.array) free(quotes.array);
 
-      f_fss_nest_delete(&found);
-
-      for (uint8_t i = 0; i < total_content; ++i) {
+      if (line_counts) free(line_counts);
+      if (line_matches) free(line_matches);
+      if (line_object) free(line_object);
+      if (set_result.string) free(set_result.string);
 
-        if (line_content[i]) free(line_content[i]);
-
-        line_content[i] = 0;
-      } // for
+      f_fss_nest_delete(&found);
 
-      line_string = 0;
-      result_string.string = 0;
-      result_string.used = 0;
-      result_string.size = 0;
-      delimit_string.string = 0;
-      delimit_string.used = 0;
-      delimit_string.size = 0;
-      delimits.array = 0;
-      delimits.used = 0;
-      delimits.size = 0;
-      found.depth = 0;
-      found.used = 0;
-      found.size = 0;
       comments.array = 0;
       comments.used = 0;
       comments.size = 0;
+      delimits.array = 0;
+      delimits.used = 0;
+      delimits.size = 0;
+      found_content.array = 0;
+      found_content.used = 0;
+      found_content.size = 0;
+      line_counts = 0;
+      line_matches = 0;
+      line_object = 0;
       quotes.array = 0;
       quotes.used = 0;
       quotes.size = 0;
+      set_result.string = 0;
+      set_result.used = 0;
+      set_result.size = 0;
     } // for
 
-    for (uint8_t i = 0; i < total_content; ++i) {
+    for (uint8_t i = 0; i < sets_total; ++i) {
 
       if (file_contents[i]) fclose(file_contents[i]);
-      if (line_content[i]) free(line_content[i]);
-
-      line_content[i] = 0;
+      if (set_contents[i].string) free(set_contents[i].string);
     } // for
 
+    if (line_counts) free(line_counts);
+    if (line_matches) free(line_matches);
+    if (line_object) free(line_object);
+    if (set_delimit.string) free(set_delimit.string);
+    if (set_result.string) free(set_result.string);
+    if (set_strings.string) free(set_strings.string);
+
+    if (file_counts) fclose(file_counts);
+    if (file_matches) fclose(file_matches);
+    if (file_objects) fclose(file_objects);
     if (file_strings) fclose(file_strings);
 
-    if (delimits.array) free(delimits.array);
     if (comments.array) free(comments.array);
+    if (delimits.array) free(delimits.array);
+    if (found_content.array) free(found_content.array);
     if (quotes.array) free(quotes.array);
-    if (line_string) free(line_string);
-    if (result_string.string) free(result_string.string);
-    if (delimit_string.string) free(delimit_string.string);
-
-    if (objects.array) free(objects.array);
-    if (positions.array) free(positions.array);
-    if (slashes.array) free(slashes.array);
 
     f_fss_nest_delete(&found);
   }
index f7429c7a814655893c710cd95760232ec21d15e7..8921e6d1e8946a53a214e279788c382cdd775e78 100644 (file)
@@ -45,7 +45,7 @@ int main(void) {
     cmocka_unit_test(test__fl_fss_embedded_list_object_write__returns_data_not),
 
     cmocka_unit_test(test__fl_fss_embedded_list_content_read__works),
-    //cmocka_unit_test(test__fl_fss_embedded_list_content_read__works_using_combining),
+    cmocka_unit_test(test__fl_fss_embedded_list_content_read__works_using_combining),
     cmocka_unit_test(test__fl_fss_embedded_list_object_read__works),
     // fl_fss_embedded_list_object_read() combining check is handled by test__fl_fss_embedded_list_content_read__works_using_combining().